經過一系列算法摸索后,我們終于要進入C語言編譯器開發的進程,這一節,我么你的目的是實現C語言的變量聲明語句的解析算法,要解析的語句形式如下:
long int *x,y;
完成變量聲明的解析后,我們便進入符號表和類型系統的研究。
自底向上的語法解析算法中,shift/reduce算法步驟解析
我們c語言編譯器所采用的語法即系算法將依上一章的自底向上語法解析算法,在上一章算法中,我們通過形成語法解析狀態機,進而構造語法解析跳轉表, 從而實現語法解析的自動化,我們要實現c語言編譯器基于上一章的代碼,只不過把語法規則換成c語言的語法而已,在簽名的算法拆解中,構造了狀態機后,某些節點會存在shift/reduce矛盾,這個矛盾的處理辦法,我再前面的講解中有些問題,這里進一步澄清一下:
1 [S->a.rB,C]
2 r->r1.
r是一個非終結符,a,B代表0個或多個終結符或非終結符的集合。
對于上面的兩個表達式,如果當前語法解析到表達式2,而且符號.處于表達式2 的末尾,那么當前解析器收到下一個字符時,采取shift操作還是reduce操作呢,如果要采取reduce操作,那么r->r1 reduce后,解析器進入到表達式1所代表的的節點,如果解析進程要能夠順利地進行下去的話,當前的輸入字符必須符號B的規則,也就是當前輸入字符必須屬于First(B)。
具體來說,假定B對應的是一個終結符+,也就是:
S->a.r+
那么如果當前輸入字符正好是“+”的話,那么當解析器處于表達式2時,做reduce操作是合理的,如果當前輸入字符不是“+”,那么如果是reduce操作的話就無法繼續進行下去了,因此做shift操作就是合理的選擇。
因此表達式2的look ahead集合是First(B),如果B是空,那么2的look ahead集合就等于C,如果B是nullable,那么表達式2的look ahead集合就是First(B) 冰 C
C語言變量聲明語句的解析語法:
1、program->ext_def_list
2、ext_def_list->ext_def_list ext_def
3、ext_def_list->ext_def
4、ext_def->opt_specifiers ext_dec_list SEMI
| opt_specifiers SEMI
5、ext_dec_list->ext_decl
| ext_decl_list COMMA ext_decl
6、ext_decl->var_decl
7、opt_specifiers->specifiers
| EMPTY
8、 specifiers->type_or_class
| specifiers type_or_class
9、type_or_class->type_specifier
9、type_specifier->TYPE
10、new_name->NAME
11、var_decl->new_name | star var_decl
上面的語法中,大寫的表示終結符,TYPE是C語言數據類型的關鍵字例如long int float 等對應的token,NAME是所有Cyuyan變量名token,STAR代表的是符號*,接下來我們看語句:
long int *x,y;
首先執行一次shift操作,把對應的token TYPE壓入解析棧:
TYPE
通過type_specifier->TYPE 進行reduce
type_specifier
通過type_or_class->type_specifier進行reduce
type_or_class
通過specifiers->type_or_class進行reduce
specifiers
接著把int對應的token TYPEshift進來
specifiers TYPE
通過type_or_class ->TYPE進行reduce
specifiers type_or_class
通過specifiers->specifiers type_or_class進行reduce
specifiers
通過opt_specifiers->specifiers進行reduce
opt_specifiers
接著分別把*和x對應的token shift到解析棧中
opt_specifiers STAR NAME
接著通過new_name ->NAME進行reduce
opt_specifiers STAR new_name
通過var-decl->STAR var_decl進行reduce
opt_specifiers var_decl
通過ext-decl->var_decl進行reduce
opt_specifiers ext_decl
再通過ext_decl_list->ext_decl
opt_specifiers ext_decl_list
接著再把逗號和y shift進去
opt_specifiers ext_decl_list COMMA NAME
然后經過new_name->NAME 以及var_decl->new_name 進行reduce
opt_specifiers ext_decl_list COMMA var_decl
再通過ext_decl_list=>ext_decl_list COMMA ext_decl 進行reduce
opt_specifiers ext_decl_list
接著把SEMI shift進去
opt_specifiers ext_decl_list SEMI
通過 ext_def -> opt_specifiers ext_list SEMI 進行reduce, 這樣堆棧的頭三個元素就出棧了:
ext_def
通過 ext_def_list -> ext_def 進行reduce:
ext_def_list
再通過 program -> ext_def_list 進行 reduce:
program
由于全句非終結符被壓入堆棧,由此解析結束,語句能被我們的語法接受。
在解析過程中,reduce進行了之后,便是代碼生成的適當時機,代碼生成出來 將高級語言轉換為低級語言之外,還有很重要的一部分是根據語言的類型系統創建符號表,符號表和類型系統是編譯原理中,極具技術福鞥厚度,難度,和趣味的一部分。
走到這里,大家是否覺得,編譯原理是一門博大精深的邏輯知識系統。隨著學習和研究的不斷推進,我越來越為編譯原理各種算法的巧妙性,完備性所折服,不得不感慨,那些大牛前輩長得是什么大腦,怎么會構建出如此精妙邏輯系統,站在這些巨人的肩膀上,擴展了我們的知識視野,也體會到了“風物長宜放眼量”的愉悅
版權聲明:本文內容由互聯網用戶自發貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如發現本站有涉嫌抄襲侵權/違法違規的內容, 請發送郵件至 舉報,一經查實,本站將立刻刪除。