Flex-Bison开发Python解析器:Bison无法识别令牌显示$undefined
问题:Flex-Bison开发Python解析器时,解析器无法识别词法分析器返回的Token ID
我用Flex-Bison编写Python解析器,词法分析器已完成,能正确识别import/from等关键字,但解析器始终无法识别对应的Token ID,报错提示unexpected $undefined。
词法分析器代码(python.l)
%{ #include <stdio.h> // 大量宏定义 #define TOKEN_IDENTIFIER 259 // 大量宏定义 #define TOKEN_WHITE 294 // 大量宏定义 #define TOKEN_KEYWORD_FROM 306 // 大量宏定义 #define TOKEN_KEYWORD_IMPORT 311 // 大量宏定义 int displayToken(int); void yyerror(char *sp); numbers ((0|[1-9][0-9]*)(\.[0-9]+)?) identifiers ([a-zA-Z\_][0-9a-zA-Z\_]*) identation (^\t+) whites (\ |\t|\r|\n)+ // 大量代码行 "from" { return displayToken(TOKEN_KEYWORD_FROM); } // 大量代码行 "import" { return displayToken(TOKEN_KEYWORD_IMPORT); } // 大量代码行 {identifiers} { return displayToken(TOKEN_IDENTIFIER); } {identation} { return displayToken(TOKEN_IDENTATION); } {whites} { return displayToken(TOKEN_WHITE); } // 大量代码行 . { yyerror("Unknown token!!!"); } %% int displayToken(int token) { #ifdef DEBUG // 调试逻辑 #endif return token; }
解析器代码(python.y)
%{ #pragma GCC diagnostic ignored "-Wimplicit-function-declaration" #include <stdio.h> #include <stdlib.h> int yylex(); %} %define parse.error verbose %token TOKEN_KEYWORD_IMPORT TOKEN_KEYWORD_FROM TOKEN_IDENTIFIER TOKEN_WHITE %start input %% input: import_def | from_def TOKEN_WHITE import_def ; import_def: import TOKEN_WHITE identifier; from_def: from TOKEN_WHITE identifier; import: TOKEN_KEYWORD_IMPORT { printf("found import\n"); }; from: TOKEN_KEYWORD_FROM { printf("found from\n"); }; identifier: TOKEN_IDENTIFIER { printf("found an identifier\n"); }; %% int main (int argc, char **argv) { #ifdef YYDEBUG yydebug = 1; #endif yyparse(); } int yywrap(void) { return 1; } int yyerror(char *s) { fprintf(stderr, "error: %s\n", s); exit(1); }
编译运行命令
flex python.l bison python.y --debug gcc lex.yy.c python.tab.c -lfl ./a.out
错误输出
输入from math import sqrt后得到:
Starting Starting parse Entering state 0 Reading a token: from math import sqrt Token ID 306 (TOKEN_KEYWORD_FROM) Next token is token $undefined () error: syntax error, unexpected $undefined, expecting TOKEN_KEYWORD_IMPORT or TOKEN_KEYWORD_FROM
我确认词法分析器能正确识别Token,但解析器无法匹配对应的ID,试过引入lex.yy.c、复制宏定义都没用,求解决办法。
解决方案
问题核心是Flex和Bison的Token ID不匹配:你在Flex中手动定义了Token数值(如TOKEN_KEYWORD_FROM 306),但Bison会自动为%token声明的符号分配独立ID,两者数值不一致导致解析器无法识别Flex返回的Token。
正确解决步骤:
让Bison生成统一的Token宏定义
在Bison文件(python.y)中添加%defines选项,Bison会生成python.tab.h头文件,包含所有Token的正确ID定义:%{ #pragma GCC diagnostic ignored "-Wimplicit-function-declaration" #include <stdio.h> #include <stdlib.h> int yylex(); %} %define parse.error verbose %defines // 添加此行,生成Token定义头文件Flex引入Bison生成的头文件
在Flex的python.l文件中,删除所有手动定义的TOKEN_*宏,引入Bison生成的python.tab.h:%{ #include <stdio.h> #include "python.tab.h" // 引入Bison生成的Token定义 int displayToken(int); void yyerror(char *sp); // 删除所有手动定义的TOKEN_*宏保持Flex返回Token的一致性
Flex中直接使用Bison头文件里的宏返回Token,现有代码无需修改(只要宏名一致即可):"from" { return displayToken(TOKEN_KEYWORD_FROM); } "import" { return displayToken(TOKEN_KEYWORD_IMPORT); }重新编译
按原命令重新编译,Bison会自动生成python.tab.h:bison python.y --debug flex python.l gcc lex.yy.c python.tab.c -lfl ./a.out
额外注意事项:
- 禁止手动定义Token数值,始终由Bison统一管理,避免ID冲突。
- 词法分析器中
identation对应的TOKEN_IDENTATION未在解析器中声明,若无需在语法中处理缩进,可直接跳过(不返回该Token);若需要则在Bison中添加%token TOKEN_IDENTATION。 - 空白字符(TOKEN_WHITE)若无需在语法规则中显式处理,可在Flex中直接跳过(将动作改为
{ /* skip whitespace */ }),简化语法规则。
内容的提问来源于stack exchange,提问作者Havarem
相关产品推荐
相关产品推荐

