Lex與Yacc學習(十)之Yacc庫

2021-06-28 08:36:41 字數 1752 閱讀 1294

每個實現都需要有用的例程庫,在unix系統中,可以通過cc命令列尾端給出-ly標誌(或通過其他系統下的等價物)來包含庫。

庫的內容在不同的實現之間是不同的,但總是包括main()和yyerror()

yacc的所有版本都帶有最小的主程式,該程式對於簡短程式和測試有時是很有用的,它非常簡單,如下所示:

main(argc,argv)

和具有任何庫例程一樣,可以提供自己的main()。在幾乎所有有用的應用軟體中都可以提供main()用來接受命令引數和標誌、開啟檔案和檢查錯誤。

所有版本也都提供簡單的錯誤報告例程,它也是非常簡單:

yyerror(char *errmsg)

這有時能夠滿足要求,但是乙個好的錯誤報告例程至少能報告行號和最近的標記(如果詞法分析程式是用lex寫的,那麼會在yytext中),這將會對語法分析程式更有用。

特殊語句

yyabort

在動作中使得語法分析例程yyparse()以乙個非零值立即返回,顯示失敗。

當動作例程探測到錯誤非常嚴重以致於沒有繼續分析的點時是很有用的。

由於語法分析程式可以向前檢視乙個標記,所以在語法分析程式讀到另乙個標記前,包括yyabort的規則動作尅不被歸約。

特殊語句

yyaccept

在動作中使得語法分析例程yyparse()以乙個零值立即返回,顯示成功。

在詞法分析程式不能告知輸入資料何時結束而語法分析程式能告知的情況下是很有用的。

由於語法分析程式可以向前檢視乙個標記,所以在語法分析程式讀到另乙個標記前,包括yyaccept的規則動作尅不被歸約。

巨集yybackup使得你可以移出當前記號並把它替換為另乙個記號,該語法為:

sym:      token

它放棄已經被歸約的符號sym,並且假裝詞法分析器剛剛讀到記號newtok,其值為newval。如果此時存在乙個向前檢視的記號或者該規則在右部的符號超過乙個的話,這個規則將通過呼叫yyerror()來宣告失敗。

正確使用yybackup非常困難,一般不用。

由於跟蹤**又大又慢,所以不能自動編譯到目標程式中。為了包含跟蹤**,使用yacc命令列上的-t標誌,或者要麼在c編譯程式命令列上,或者通過在定義段包含類似下面的句式,來定義c預處理程式符號yydebug為非零值:

%

有時動作**能探測到上下文相關的而語法分析程式本身卻不能檢測到的語法錯誤。如果**檢測到乙個語法錯誤,就可以呼叫巨集yyerror,生成的效果與語法分析程式讀到乙個被語法禁止的標記時完全一樣。一呼叫yyerror,語法分析程式就訪問yyerror(),進入錯誤恢復模式,尋找可以移進error標記的狀態。

只要yacc語法分析程式探測到語法錯誤就呼叫yyerror()函式,將錯誤報告給使用者。傳遞單個引數即描述這個錯誤的字串,yacc庫中的yyerror的預設版本僅僅是在標準輸出檔案中列印引數。

yyerror(const char *msg)

yylineno是當前行號,yytext是包含當前標記的lex標記緩衝器。

yacc生成的語法分析程式的入口點是yyparse(),當程式呼叫yyparse()時,語法分析程式就試圖分析輸入流。如果分析成功,語法分析程式就返回乙個零值,反之,則返回乙個非零值。

每次呼叫該函式,語法分析程式就重新開始進行分析,而忘記上次返回的狀態,這與lex掃瞄程式十分不同,它能夠獲得呼叫後的每一次狀態。

Lex與Yacc學習(九)之Yacc語法

本文討論yacc語法的格式並描述可用的各種特徵和選項 yacc語法包括三部分 定義段 規則段和使用者子例程段 定義段.規則段.使用者子例程段.各部分由以兩個百分號開頭的行分開,儘管某乙個部分可以為空,但是前兩部分是必須的,第三部分和前面的百分號可以省略。yacc 語法由符號組成,即語法的 詞 符號是...

Lex與Yacc學習(四)之Lex規範

lex程式由三部分組成 定義段 規則段和使用者子例程式段 定義段.規則段.使用者子例程式段.這些部分由以兩個百分號組成的行分隔開。儘管某一部分可以為空,但前兩部分是必須的,第三部分和前面的 行可以忽略。定義段包括文字塊 定義 內部表宣告 起始條件和轉換。以空白開頭的行被逐字拷貝到c檔案中,通常,這用...

Lex與Yacc的結合

lex與yacc的結合 首先,我就不介紹lex的語法規則了,因為在一些書上這些是重點介紹的內容,我先把lex的源程式寫在下面,然後講解。number 0 9 其中 define number 257 define plus 258 define sub 259 define chen 260 def...