[英]Make Bison accept an alternative EOF token
我正在用 flex 和 bison 用 C++ 編寫 ansi-C 解析器; 這很復雜。
我遇到的問題是編譯錯誤。 錯誤如下,這是因為yy_terminate
返回YY_NULL
定義為(一個 int) 0
並且yylex
的返回類型為yy::AnsiCParser::symbol_type
。 yy_terminate();
是由 flex 生成的掃描器中<<EOF>>
令牌的自動操作。 顯然,這會導致類型問題。
我的掃描器不會為 EOF 生成任何特殊標記,因為 EOF 在 C 語法中沒有用途。 我可以為<<EOF>>
創建一個令牌規則,但是如果我忽略它,那么掃描儀會在YY_STATE_EOF(INITIAL)
情況下的yylex
無限循環。
編譯錯誤,
ansi-c.yy.cc: In function ‘yy::AnsiCParser::symbol_type yylex(AnsiCDriver&)’:
ansi-c.yy.cc:145:17: error: could not convert ‘0’ from ‘int’ to ‘yy::AnsiCParser::symbol_type {aka yy::AnsiCParser::basic_symbol<yy::AnsiCParser::by_type>}’
ansi-c.yy.cc:938:30: note: in expansion of macro ‘YY_NULL’
ansi-c.yy.cc:1583:2: note: in expansion of macro ‘yyterminate’
此外,Bison 為我的開始規則 (translation_unit) 和 EOF ($end) 生成此規則。
$accept: translation_unit $end
所以yylex
必須為 EOF 返回一些東西,否則解析器永遠不會停止等待輸入,但我的語法不能支持 EOF 標記。 有沒有辦法讓 Bison 在不修改我的語法的情況下識別$end
條件的0
東西?
或者,是否可以從掃描儀中的<<EOF>>
令牌返回一些內容以滿足 Bison $end
條件?
通常,您不會在詞法分析器中包含顯式 EOF 規則,不是因為它沒有任何用途,而是因為默認值正是您想要做的。 (它的作用是表明輸入是完整的;否則,解析器將接受某些無效程序的有效前綴。)
不幸的是,C++ 接口可能會破壞默認 EOF 操作的簡單便利性,即返回 0(或 NULL)。 我從你的問題描述中假設你已經要求 bison 使用完整的符號生成解析器。 在這種情況下,您不能簡單地從yylex
返回 0,因為解析器需要一個完整的符號,這是一個比int
更復雜的類型(盡管報告 EOF 的標記通常沒有語義值,但它確實有一個位置,如果您正在使用位置。)對於其他令牌類型,bison 將自動生成一個函數,該函數生成一個令牌,命名為make_FOO_TOKEN
,您將在掃描儀操作中調用FOO_TOKEN
。
雖然 C bison 解析器會自動定義文件結尾標記(稱為END
),但 C++ 接口似乎沒有。 所以你需要在你的野牛輸入文件的%token
聲明中手動定義它:
%token END 0 "end of file"
(這定義了帶有整數值 0 和人類可讀標簽“文件結尾”的令牌類型END
。值 0 是強制性的。)
完成后,您可以在 flex 輸入文件中添加顯式 EOF 規則:
<<EOF>> return make_END();
如果您使用位置,則還必須給make_END
一個位置參數。
這是防止編譯器錯誤的另一種方法could not convert 0 from int to ...symbol_type
- 將yyterminate
宏的重新定義YY_DECL
重新定義YY_DECL
// change curLocation to the name of the location object used in yylex
// qualify symbol_type with the bison namespace used
#define yyterminate() return symbol_type(YY_NULL, curLocation)
啟用野牛位置時會出現編譯器錯誤,例如使用%define locations
- 這使得野牛向其symbol_type
構造函數添加location
參數,因此沒有位置的構造函數
symbol_type(int tok)
變成這個位置
symbol_type(int tok, location_type l)
渲染不再可能將int
轉換為symbol_type
,這是未啟用野牛位置時 flex 中yyterminate
的默認定義能夠執行的操作
#define yyterminate() return YY_NULL
使用此解決方法,如果您不需要,則無需在 flex 中處理EOF
如果您不需要,則不需要在野牛中使用多余的END
令牌
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.