banner
DIYgod

Hi, DIYgod

写代码是热爱,写到世界充满爱!
github
twitter
follow
bilibili
telegram
email
steam
playstation
nintendo switch

一個完整編譯器的實現(二)語法分析

1 系列說明

GitHub 地址 各階段源碼 各階段說明集合

2 語法分析說明

語法:組合單詞以形成詞組、從句或句子的方法。

經過詞法分析,我們已經可以將輸入文本識別成一個個的單詞,本階段的目標是將這些單詞識別成句子,判斷單詞的這種組合形式是否符合我們定義的語法。

2.1 用文法來定義語法

語法分析需要由遞歸而獲得的額外表示能力,顯然正則表達式已經不能滿足我們的需求。

事實上,文法也可以用來描述詞法單詞的結構,但正則表達式已經可以滿足需求,這時使用正則表達式更為簡潔。

2.2 LR (1) 分析法

@%……¥&%#¥太複雜不想說

總之,LR (1) 是一種非常非常強大的分析算法,能夠解決很多歸約 - 歸約衝突,大多數用上下文無關文法描述其語法的程式設計語言都有一個 LR (1) 文法。

2.3 使用 Yacc 生成語法分析器

構造 LR (1) 分析表的演算法簡單得足以用電腦來自動完成,而且手工構造十分麻煩無趣,所以使用 Yacc 是一個明智的決定。

類似 Lex,Yacc 規範分為三部分

第一部分同 Lex,包含 include 和聲明

第二部分定義從詞法分析中接收的終結符,開始符號,優先級等

第三部分定義文法及語義動作,語法分析階段只定義文法,語義動作到語義分析時候再完成。

2.3.1 衝突

Yacc 選擇移近來解決移進 - 歸約衝突,選擇使用在文法中先出現的規則來解決歸約 - 歸約衝突。

2.3.2 優先級指導

定義優先級是為了解決二義性,這樣寫文法的時候方便得多。

Yacc 在第二部分可以假如優先級指導命令

自上而下優先級降低,left right 說明單詞是左結合還是右結合。

3 具體實現

語法分析器和改進過的詞法分析器源碼見文章開頭。

進行到本階段,編譯器發展為四個模組:

1. 錯誤處理模組(errormsg.c errormsg.h):用來產生含文件名和行號的報錯信息
2. 常用工具模組(util.c util.h):定義一些常用的函數
3. 詞法分析模組(simplec.lex):通過 Lex 進行詞法分析
4. 語法分析模組(simplec.yacc):通過 Yacc 進行語法分析

其中上一階段的 token.h 已經不再需要,作為代替,Yacc 會根據我們寫的文法的單詞規範自動生成一個與單詞相關的頭文件 y.tab.h ;parsetest.c 是一個驅動程式,正常情況下會輸出 Parsing successful!

附:ANSI C grammar (Lex) ANSI C grammar (Yacc)

 

語法分析 Done.

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。