編譯器實現(四)

1.自頂向下的分析

參考:https://blog.csdn.net/hjc256/article/details/87949500算法

自頂向下的分析算法經過在最左推導中描述出各個步驟來分析記號串輸入。spa

分析樹隱含的編號是一個前序編號,順序是由根到葉。.net

自頂向下的分析程序有兩類:回溯分析程序,預測分析程序。code

 

1.1使用遞歸降低分析算法進行自頂向下的分析

 1.1.1遞歸降低分析的基本方法

概念:blog

  將一個非終結符A的文法規則看做將識別A的一個過程的定義。遞歸

 遞歸降低分析程序由一組過程組成,每一個非終結符號有一個對應的過程。程序的執行從開始符號對應的過程開始,若是這個過程的過程體掃描了整個輸入串,他就中止執行並宣佈語法分析完成。rem

當非終結符有多個產生式時,可能須要回溯,即重複掃描。

get

產生式:io

  A→a | b | . . .class

若a,b均爲非終結符時,須要計算a,b的First集合,來肯定什麼時候使用A→a或A→b。

產生式:

  A→ε

須要瞭解什麼記號能夠正規地出如今非終結符A以後,這個集合爲Follow集合。

進行First集合和Follow集合的計算是爲了對早期錯誤進行探測。

 

1.2 LL(1)分析

1.2.1 LL(1)文法

參考:https://blog.csdn.net/jxch____/article/details/78693775

第一個L表示從左向右掃描輸入,第二個L表示產生最左推導,而「1」表示在每一步中只須要向前看一個輸入符號來決定語法分析的動做。

文法G是LL(1)的,當且僅當對於G的每一個非終結符Α的任何兩個不一樣產生式
Α→α,Α→β均知足下面條件(其中α和β不能同時推出ε):
1、FIRST(α)∩FIRST(β)=Φ
2、倘若β=>*ε,那麼FIRST(α)∩FOLLOW(A)=Φ

 

LL(1)分析使用顯示棧來完成分析。

例:(LL(1))分析的基本方法)

  對文法:S→ (S) S | ε

  

                   自頂向下的分析動做

 

1.2.2 LL(1)分析與算法

構造一個LL(1)分析表表達出可能的自頂向下分析選擇,這個表稱爲M[N,T]。N是文法的非終結符的集合,T是終結符或記號的集合(禁止將ε加入)。

構造規則:

  1) 若是A→α是一個產生式選擇,且有推導 α ⇒ *ab成立,其中a 是一個記號,則將A→a添加到表項目M [A, a] 中。

  2) 若是A→α是一個產生式選擇,且有推導 α⇒ *ε 和 S $ ⇒*βAaγ成立,其中S是開始符號,α是一個記號(或$),則將A→α添加到表項目M [A, a]中。

例: (LL(1)分析表)

  對文法:S→ (S) S | ε

  

定義:若是文法G相關的LL(1)分析表的每一個項目中至多隻有一個產生式,則該文法就是LL(1)文法(LL(1) grammar)。

 

利用LL(1)文法表構造出一個無二義性的分析。

1.2.3 消除左遞歸和提取左因子

將BNF表示法中的文法重寫到LL (1)分析算法所能接受的格式上。應用的兩個標準技術是左遞歸消除(left recursion removal)和提取左因子(left factoring)。這兩個技術沒法保證可將一個文法變成LL(1)文法,這就同EBNF同樣沒法保證在編寫遞歸降低程序中能夠解決全部的問題。

1.左遞歸消除

  左遞歸被廣泛地用來運算左結合。

  (1)簡單直接左遞歸

      A→Aα | β

    其中α和β是終結符和非終結符的串,並且β不以A開頭。

    重寫規則:一個是首先生成β,另外一個是生成α的重複,它不用左遞歸卻用右遞歸:

      A →βA

      A’ →αA | ε

  (2)廣泛的直接左遞歸

      A → Aα1 | Aα2 | . . . | Aαn| β1 | β2 | . . . | βn

      其中β1 ,β2  . . .  βn均不以A開頭。

      重寫規則:

        A →β1 A| β2 A | . . . | βm A’

        Aα1A| α2A | . . . | αn A

  (3)通常的左遞歸

    待寫。。。

2.提取左因子

  當兩個或更多文法規則選擇共享一個通用前綴串時,須要提取左因子。

  A→αβ | αγ

  重寫規則:

  A →αA 

  A  → β γ

1.2.4 在LL(1)分析中構造語法樹

主要緣由倒是分析棧所表明的僅是預測的結構,而不是已經看到的結構。所以,語法樹節點的構造必須推遲到將結構從分析棧中移走時,而不是當它們首次被壓入時。通常而言,這就要求使用一個額外的棧來記錄語法樹節點,並在分析棧中放入「動做」標記來指出什麼動做什麼時候將在樹棧中發生。

例:E → E + n | n

  重寫:

  E → n E

  E’ → + n E | ε
   

  

1.2 First集合和Follow集合

1.2.1 First集合

定義:令X爲一個文法符號(一個終結符或非終結符)或,則集合First (X) 由終結符組成,此外可能還有ε,它的定義以下:

  1. 若X是終結符或,則First (X) = {X}。

  2. 若X是非終結符,則對於每一個產生式X→X1X2 . . . Xn ,First (X)都包含了First(X1 ) - { ε}。若對於某個i < n,全部的集合First (X1 ), . . . , First   (Xi ) 都包括了ε,則First (X) 也包括了First (Xi + 1) - {ε }。若全部集合First (X1 ), . . . , First (Xn)包括了ε,則First (X)也包括ε。

  

    

 

 

1.2.3 Follow集合

定義:給出一個非終結符A,那麼集合Follow (A)則是由終結符組成,此外可能還有$。
集合Follow (A)的定義以下:
  1. 若A是開始符號,則$就在Follow (A)中。
  2. 若存在產生式B→αAγ,則First (γ) - {ε}在Follow (A)中。
  3. 若存在產生式B→αAγ,且ε在First (γ)中,則Follow (A)包括Follow (B)。

 

    

1.2.4 構造LL(1)分析表

參見1.2.2中LL(1)分析表:

  1) 若是A→α是一個產生式選擇,且有推導 α ⇒ *αβ成立,其中α 是一個記號,則將A→α添加到表項目M [A, α] 中。

  2) 若是A→ε是ε產生式選擇,且有推導 S$ ⇒*αAα β 成立,其中S是開始符號,α是一個記號(或$),則將A→ε 添加到表項目M [A, a]中。

規則1中的記號 α很明顯是在First (α) 中,且規則2的記號α 是在Follow (A)中,所以,就可獲得LL(1) 分析表的如下算法構造:

LL(1) 分析表M[N, T] 的構造:爲每一個非終結符A和產生式A→α重複如下兩個步驟:

  1) 對於First (α)中的每一個記號α,都將A→α添加到項目M [A, a]中。

  2) 若ε在First (α)中,則對於Follow (A) 的每一個元素α(記號或是$),都將A→α 添加到M[A, a]中。

 

LL(1)文法的斷定規則:

  定理:若知足如下條件,則B N F中的文法就是L L(1)文法(LL(1) grammar)。

    1. 在每一個產生式A→a1 | a2 | . . . |an 中,對於全部的 i 和 j:1≤i,j≤n,i≠j,First (ai ) ∩ First (aj )爲空。

    2. 若對於每一個非終結符A都有First (A) 包含了 ε,那麼First (A) ∩ Follow (A)爲空。

相關文章
相關標籤/搜索