Flex/Bison中YYABORT未识别及相关编译错误求助
Flex 2.6.4 + Bison 3.8 解析器编译错误解决指南
使用Flex 2.6.4与Bison 3.8开发JavaScript子集解析器,已在Bison代码中添加%locations启用位置跟踪,但编译时出现YYLTYPE未识别、YYABORT未定义、yyerror函数隐式声明/类型冲突等错误,手动声明无效。以下是相关代码、错误信息及解决建议:
js.l 代码
%{ #include "js-parser.h" #define YY_USER_ACTION \ yylloc.first_line = yylloc.last_line; \ yylloc.first_column = yylloc.last_column; \ yylloc.last_column += yyleng; \ if (yytext[yyleng-1] == '\n') { \ yylloc.last_line++; \ yylloc.last_column = 1; \ }; void yyerror(YYLTYPE *loc, const char *s); %} %option yylineno %% "var" { return VAR; } "const" { return CONST; } "let" { return LET; } [a-zA-Z_][a-zA-Z0-9_]* { yylval.sval = strdup(yytext); return IDENTIFIER; } [0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)?|\.[0-9]+([eE][-+]?[0-9]+)? { yylval.ival = atoi(yytext); return NUMBER; } "//" { input(); while (input() != '\n'); } "/*" { do { while(input() != '*'); } while (input() != '/'); } "+" { return PLUS; } "-" { return MINUS; } "*" { return MULTIPLY; } "/" { return DIVIDE; } "(" { return LPAREN; } ")" { return RPAREN; } "=" { return ASSIGN; } ";" { return SEMICOLON; } [ \t\n]+ ; . { return yytext[0]; } %%
js.y 代码
%{ #include <stdio.h> #include <stdlib.h> #include <string.h> int yylex(); void yyerror(YYLTYPE *loc, const char *s); int main(); %} %locations %union { int ival; char *sval; }; %token <ival> IDENTIFIER %token <ival> NUMBER %token VAR CONST LET PLUS MINUS MULTIPLY DIVIDE LPAREN RPAREN ASSIGN SEMICOLON %left PLUS MINUS %left MULTIPLY DIVIDE %right NEG %type <ival> expr %% program: | program statement SEMICOLON ; statement: type IDENTIFIER | type IDENTIFIER ASSIGN expr ; type: VAR | CONST | LET ; expr: NUMBER | IDENTIFIER | expr PLUS expr { $$ = $1 + $3; } | expr MINUS expr { $$ = $1 - $3; } | expr MULTIPLY expr { $$ = $1 * $3; } | expr DIVIDE expr { if ($3) $$ = $1 / $3; else { yyerror(@3, "division by zero"); }; } | LPAREN expr RPAREN { $$ = $2; } | MINUS expr %prec NEG { $$ = -$2; } ; %% void yyerror(YYLTYPE *loc, const char *s) { fprintf(stderr, "Error at %d: %s\n", loc->first_line, s); YYABORT; }; int main() { printf("Use this js parser"); yyparse(); return 0; };
编译错误信息
js.y:7:14: 错误:未知类型名‘YYLTYPE’ 7 | void yyerror(YYLTYPE *loc, const char *s); | ^~~~~~~ js.y: 在函数‘yyparse’中: js.y:53:117: 警告:隐式声明函数‘yyerror’;您指的是‘yyerrok’吗? [-Wimplicit-function-declaration] 53 | | expr DIVIDE expr { if ($3) $$ = $1 / $3; else { yyerror(@3, "division by zero"); }; } | ^ | yyerrok js.y: 在顶层: js.y:60:6: 警告:‘yyerror’的类型冲突;应为‘void(YYLTYPE *, const char *)’ 60 | void yyerror(YYLTYPE *loc, const char *s) { | ^~~~~~~ js.y:53:117: 附注:‘yyerror’的先前隐式声明类型为‘void(YYLTYPE *, const char *)’ 53 | | expr DIVIDE expr { if ($3) $$ = $1 / $3; else { yyerror(@3, "division by zero"); }; } | ^ js.y: 在函数‘yyerror’中: js.y:62:5: 错误:标签‘yyabortlab’已使用但未定义 62 | YYABORT; | ^~~~~~~
解决建议
1. 修复YYLTYPE未定义错误
YYLTYPE是Bison生成的位置结构体,定义在Bison输出的头文件(即js-parser.h)中。需在js.y的%{ ... %}块中先包含该头文件,让编译器识别类型:
%{ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "js-parser.h" // 添加此行 int yylex(); void yyerror(YYLTYPE *loc, const char *s); int main(); %}
2. 移除yyerror中的YYABORT调用
YYABORT是Bison为yyparse函数定义的内部宏,仅能在Bison语法动作块(%%之间的代码)中使用,无法在外部yyerror函数中调用。若需错误时终止解析,可改为直接退出程序:
void yyerror(YYLTYPE *loc, const char *s) { fprintf(stderr, "Error at %d: %s\n", loc->first_line, s); exit(EXIT_FAILURE); };
3. 解决yyerror隐式声明问题
通过提前包含js-parser.h,确保yyerror的声明在yyparse调用前被编译器识别。也可在Bison代码中添加%define api.header.include "js-parser.h",让Bison自动在生成的头文件中包含必要声明。
4. 修正语义值类型不匹配问题
js.l中IDENTIFIER的语义值赋值给yylval.sval(字符串),但js.y中声明为<ival>(整数),会导致运行时内存错误,需修正token声明:
%token <sval> IDENTIFIER // 将<ival>改为<sval> %token <ival> NUMBER
5. 正确编译命令
使用以下命令生成并编译代码:
# 生成解析器头文件与源码 bison -d -o js-parser.c js.y --defines=js-parser.h # 生成词法分析器 flex -o js-scanner.c js.l # 编译可执行文件 gcc -o js-parser js-parser.c js-scanner.c -lfl
内容的提问来源于stack exchange,提问作者Grrd
相关产品推荐
相关产品推荐

