如何解决编译Lex/Yacc代码时的‘undefined reference to `yyerror'’错误?
解决lex/yacc编译时"undefined reference to `yyerror'"错误
我跟着视频学习编写了lexer.l和parser.y文件,执行编译命令gcc lex.yy.c parser.tab.c时遇到以下错误:
undefined reference to `yyerror'
collect2.exe: error: ld returned 1 exit status
我的代码如下:
lexer.l
%{ /* definitions */ #include "parser.tab.h" %} /* rules */ %% [0-9]+ {yylval.num = atoi(yytext); return NUMBER; } \n {return EOL;} . {} %% yywrap() {} int main() { yylex(); return 0; }
parser.y
%{ /* definitions */ %} %union{ int num; char sym; } %token EOL %token<num> NUMBER %type<num> exp %token PLUS /* rules */ %% input: exp EOL {printf("%d\n", $1); } | EOL; exp: NUMBER { $$ = $1; } | exp PLUS exp { $$ = $1 + $3; } ; %% int main() { yyparse(); return 0; } void yyerror (char* s) { printf ("ERROR: %s\n", s); return 0; }
错误原因分析
这个链接错误是因为编译器找不到yyerror函数的定义关联,同时代码里还有几个隐性问题:
- lexer.l中未声明
yyerror函数,导致编译时无法识别该符号 - lexer.l和parser.y都定义了
main函数,链接时会出现多重定义冲突 - parser.y定义了
PLUStoken,但lexer.l没有匹配+的规则,语法分析时无法识别加号 yywrap函数没有返回值,不符合语法要求
解决步骤
1. 修正lexer.l代码
- 删除lexer.l中的
main函数,改用parser的yyparse作为程序入口 - 添加
+的匹配规则,返回PLUStoken - 声明
yyerror函数,避免编译警告 - 修复
yywrap的返回值问题
修正后的lexer.l:
%{ /* definitions */ #include "parser.tab.h" void yyerror(char* s); // 声明yyerror函数 %} /* rules */ %% [0-9]+ {yylval.num = atoi(yytext); return NUMBER; } "+" {return PLUS;} // 新增匹配加号的规则 \n {return EOL;} . {} // 忽略其他字符 %% int yywrap() { return 1; // 返回1表示没有更多输入,符合函数返回值要求 }
2. 修正parser.y中的yyerror函数
yyerror的返回类型是void,不需要返回值,删掉错误的return 0;:
void yyerror (char* s) { printf ("ERROR: %s\n", s); }
3. 重新生成并编译
执行以下命令完成编译:
- 生成parser的头文件和源文件:
yacc -d parser.y - 生成lex的源文件:
flex lexer.l - 编译链接生成可执行文件:
gcc lex.yy.c parser.tab.c -o calculator - 运行程序:Windows下执行
calculator.exe,Linux/macOS下执行./calculator
内容的提问来源于stack exchange,提问作者Hayfa Alsuhaimi
相关产品推荐
相关产品推荐

