聲明:本系列文章,是根據中國大學MOOC網 哈工大的編譯原理 這門課學習而成的學習筆記。
一、自頂向下分析概述
最左推導(Left-most Derivation)
最右推導(Right-most Derivation)
自頂向下分析(Top-Down Parsing)
- 從分析樹的頂部(根節點)向底部(葉節點)方向構造分析樹可以看成是從文法開始符號S推導出詞串w的過程
- 每一步推導中,都需要做兩個選擇
- 替換當前句型中的哪個非終結符
- 用該非終結符的哪個候選式進行替換
自頂向下的語法分析採用最左推導方式
- 總是選擇每個句型的最左非終結符進行替換
- 根據輸入流中的下一個終結符,選擇最左非終結符的一個候選式
自頂向下語法分析的通用形式
遞歸下降分析 (Recursive-Descent Parsing)
- 由一組過程組成,每個過程對應一個非終結符
- 從文法開始符號S對應的過程開始,其中遞歸調用文法中其它非終結符對應的過程。如果S對應的過程體恰好掃描了整個輸入串,則成功完成語法分析
預測分析 (Predictive Parsing)
- 預測分析是遞歸下降分析技術的一個特例,通過在輸入中向前看固定個數(通常是一個)符號來選擇正確的A-產生式。
- 可以對某些文法構造出向前看k個輸入符號的預測分析器,該類文法有時也稱爲LL(k) 文法類
- 預測分析不需要回溯,是一種確定的自頂向下分析方法
二、文法轉換
遞歸下降分析器存在的問題
解決辦法
- 消除直接左遞歸
消除直接左遞歸的一般形式
- 消除間接左遞歸
- 消除左遞歸算法
- 提取左公因子
提取左公因子算法
三、LL(1)文法
S_文法(簡單的確定性文法,Korenjak & Hopcroft,1966)
- 每個產生式的右部都以終結符開始
- 同一非終結符的各個候選式的首終結符都不同
- S_文法不含ε產生式
預測分析法的工作過程:從文法開始符號出發,在每一步推導過程中根據當前句型的最左非終結符A和當前輸入符號a,選擇正確的A-產生式。爲保證分析的確定性,選出的候選式必須是唯一的。
非終結符的後繼符號集
產生式的可選集
串首終結符集
LL(1)文法
四、FIRST集和FOLLOW集的計算
計算文法符號X的FIRST(X )
- 由定義可知,FIRST(T)={ +,ε }, FIRST(T’)={ *, ε }, FIRST(F)={ (, ε }
- FIRST(E) 取決於 FIRST(T),而FIRST(T)取決於FIRST(F)
- 所以FIRST(E)=FIRST(F)=FIRST(F)
計算非終結符A的FOLLOW(A)
- E是文法的開始符號,屬於最右符號,將$加入其FOLLOW(E)中
- 根據①,跟着E後的符號可以直接跟在E’後面,故將FOLLOW(E)加入到FOLLOW(E’)中。同時根據②,E’可替換成 ε ,故直接跟在E後面的符號也有可能直接跟在T後面,所以將FOLLOW(E)加入到FOLLOW(T)中。
- 再根據①,E’緊跟在T後面,故將FIRST(E’)中的所有終結符,即+加入FOLLOW(T)中;
- 根據②推出的結果和①類似,沒有更新
- 根據③,T’緊跟在F後面,故將FIRST(T’)中的所有終結符,即*加入到FOLLOW(T)中;同時T’可推到出ε,跟在T後的終結符可能也會直接跟再F後面,故將FOLLOW(T)加入到FOLLOW(F)中。
- 再根據③,跟在T後面的終結符可以直接跟在T’後面,故將FOLLOW(T)加入到FOLLOW(T’)中。
- 根據④推出的結果和③類似,沒有更新
- 根據⑤,E後面直接跟有終結符號)。故直接將)加入到FOLLOW(E)中,同時根據上面的推理,發現FOLLOW集彼此之間存在相互依賴的關係,故每當一個FOLLOW集更新時,應再重新計算一遍,直到所有的FOLLOW集不再更新
計算SELECT集
五、LL(1)文法的分析方法
- 遞歸的預測分析法
- 非遞歸的預測分析法
遞歸的預測分析法
非遞歸的預測分析法
遞歸的預測分析法vs.非遞歸的預測分析法
預測分析法實現步驟
- 構造文法
- 改造文法:消除二義性、消除左遞歸、消除回溯
- 求每個變量的FIRST集和FOLLOW集,從而求得每個候選式的SELECT集
- 檢查是不是 LL(1) 文法。若是,構造預測分析表
- 對於遞歸的預測分析,根據預測分析表爲每一個非終結符編寫一個過程;對於非遞歸的預測分析,實現表驅動的預測分析算法
六、預測分析中的錯誤處理
預測分析中的錯誤檢測
兩種情況下可以檢測到錯誤
- 棧頂的終結符和當前輸入符號不匹配
- 棧頂非終結符與當前輸入符號在預測分析表對應項中的信息爲空
預測分析中的錯誤恢復
恐慌模式 :
- 忽略輸入中的一些符號,直到輸入中出現由設計者選定的同步詞法單元(synchronizingtoken)集合中的某個詞法單元。其效果依賴於同步集合的選取。集合的選取應該使得語法分析器能從實際遇到的錯誤中快速恢復。
·例如可以把FOLLOW(A)中的所有終結符放入非終結符A的同步記號集合
- 如果終結符在棧頂而不能匹配,一個簡單的辦法就是彈出此終結符