LexYacc编写计算器编译出现yylex隐式声明、y.tab.h缺失错误怎么办
报错原因及修复方案
1. 致命错误:fatal error: y.tab.h: No such file or directory
原因:你使用的bison命令默认会生成和输入y文件前缀一致的头文件,也就是exp.tab.h,但你的Lex代码里引用的是旧版yacc工具默认生成的y.tab.h,文件名不匹配导致找不到头文件。
修复二选一即可:
- 方法1:修改bison命令,添加
-y参数强制生成y.tab.c和y.tab.h,命令改为bison -d -y exp.y - 方法2:修改
exp.l里的头文件引用,改为#include "exp.tab.h"
2. 警告:implicit declaration of function ‘yylex’
原因:bison生成的语法分析代码里需要调用flex生成的yylex()词法分析函数,但代码里没有提前声明这个外部函数,触发C语言的隐式声明警告。
修复:在exp.y的%{ %}代码块里添加yylex的前置声明:
extern int yylex(void);
3. 警告:implicit declaration of function ‘yyerror’
原因:yyparse运行时需要调用错误处理函数yyerror,但这个函数的定义在语法规则后面,代码运行到调用位置时还没有读到函数定义,触发隐式声明警告。
修复:在exp.y的%{ %}代码块里添加yyerror的前置声明:
void yyerror(char *s);
4. 警告:return type defaults to ‘int’
原因:C标准要求所有函数必须明确声明返回值类型,你写的main()和yyerror()都没有声明返回值,编译器默认按int类型处理,不符合C规范。
修复:
- 把
main()改为int main(),函数末尾添加return 0; - 把
yyerror (char *s)改为void yyerror(char *s),该函数不需要返回值。
修正后的完整代码
修正后的exp.l
/*%option outfile="scanner.cpp"*/ %{ #include "exp.tab.h" extern int yylval; %} %% 0|[1-9][0-9]* { yylval = atoi(yytext); return INTEGER; } [+*()\n] { return yytext[0]; } . { /* do nothing */ } %%
修正后的exp.y
/* %output "parser.cpp" %skeleton "lalr1.cc" */ %{ #include <stdio.h> extern int yylex(void); void yyerror(char *s); %} %token INTEGER %left '+' %left '*' %% input : /* empty string */ | input line ; line : '\n' | exp '\n' { printf ("\t%d\n", $1); } | error '\n' ; exp : INTEGER { $$ = $1; } | exp '+' exp { $$ = $1 + $3; } | exp '*' exp { $$ = $1 * $3; } | '(' exp ')' { $$ = $2; } ; %% int main () { yyparse(); return 0; } void yyerror (char *s) { printf ("%s\n", s); }
编译运行命令
flex exp.l bison -d exp.y gcc exp.tab.c lex.yy.c -o exp -lfl ./exp
运行后输入算术表达式即可得到计算结果。
内容的提问来源于stack exchange,提问作者dubugger
相关产品推荐
相关产品推荐

