學習 bison 原理(四) 算法
第5步: 轉變第 4 步的狀態機爲肯定的 LALR 狀態機. json
在(三)中咱們已經看到 LR0 狀態機極可能有 r/r 衝突, s/r 衝突,
那這關鍵的第5步就是用 lookahead(LA) 符號來試圖解決 LR0 文法的
不足而致使的衝突. c#
程序實如今 Lalr.cs 中, 要理解這部分程序, 必需要先理解論文1給出的
概念和算法. 包括以下幾個主要概念:
Direct Read 關係 (DR)
reads 關係
includes 關係
digraph -- 經過高效算法計算傳遞閉包(Transitive Closure) 數組
主入口函數爲 Lalr.lalr(), 其主要步驟以下:
1. 爲計算 lalr 作準備工做: 創建 states[] 等數組.
2. 初始化須要 LA 的狀態, 規則的數組. 創建 goto 數據,
即 (p, A) -- 從狀態 p 經非終結符 A 的轉移.
3. 構造 F[,] 矩陣, 根據 Direct Read, reads 關係計算出 Read.
結果在 F[,] 中.
4. 構造 includes, lookback 關係(以稀疏矩陣方式存儲).
5. 根據 F, includes 關係計算出每一個 (p, A) 的 FOLLOW[] 集合.
6. 根據 FOLLOW[], lookback 關係計算出每一個(p, A->w) 的 LA[] 集. 閉包
再次強調的是, 要細讀論文1, 由於 bison 這裏使用的算法就是該文中的算法.
我剛看這裏代碼的時候, 沒法和編譯原理龍書上的東西對照起來, 以致於即便
看懂了每行代碼, 可仍是不能理解在作什麼, 直到找到了該論文. 這裏再給出連接:
http://3e8.org/pub/scheme/doc/parsing/Efficient%20Computation%20of%20LALR(1)%20Look-Ahead%20Sets.pdf 函數
這裏描述的幾種關係, 矩陣, 圖算法在論文中都有詳細的說明, 我能理解部分,
但沒有能力轉述出來, 因此仍是請參見原文. 另就是看看我寫的代碼註解, 也許
能幫助理解一點. 學習
程序中, digraph() 函數給出了一種圖的求傳遞閉包的高效算法, 是值得學習的.
另程序中 Warshall.TC(), Warshall.RTC() 也是求傳遞閉包的, 可是時間複雜度
是 O(n^3), 因此能夠參照對比來學習的.
在求取出 LA 以後, 剩下的問題是解決仍然存在的衝突了, 位於文件 Conflicts.cs 中.
那裏 %prec 指定的優先級, %left, %right, %nonassoc 指定的結合性就在那裏發生效用,
尤爲是對錶達式中的各類運算符. 這裏可以幫助咱們理解爲什麼會產生衝突, 而解決方法則
能夠創建在對衝突的本質緣由的深入理解的基礎上. xml
在以後, 程序輸出可能的衝突提示/解決信息, 及或一個解析器的代碼. 這些略(cs 中也沒有
寫這些了). 須要瞭解的要去看 bison c 的源代碼. 但我略略的看了一下 bison 2.65
彷佛裏面還能夠輸出狀態的圖形化表示? 以及 xml, json 格式的? 實在沒有仔細瞭解.
可是若是真能如此, 那真是更方便了使用者了, 真是又進幾大步了...... ci
下面給出我改寫的 c# 的代碼, 供你們參考. 若是先後有不一致的地方, 請多諒解, 由於
看前面的時候總有不理解的地方, 就會打問號亂理解的... get