如何修复Lex/Yacc算术运算程序中的yyerror与yylex隐式声明问题
解决Lex/Yacc算术程序中的隐式声明警告问题
这些警告本质上都是C编译器找不到函数原型导致的隐式声明问题,我来帮你拆解原因并给出修复方案:
问题根源
yyerror隐式声明:不管是Lex生成的lex.yy.c还是Yacc生成的y.tab.c,编译器都找不到yyerror的函数原型,所以抛出警告。yylex隐式声明:Yacc生成的解析器需要调用yylex获取token,但编译器不知道这个函数的签名,同样报隐式声明。- 另外你的Lex代码还有个小语法问题,最后一行的错误处理缺少大括号,虽然不是当前警告的原因,但会导致潜在解析错误。
具体修复步骤
1. 给yyerror和yylex添加原型声明
修改你的ex1.y文件,在顶部的%{ ... %}块里添加两个函数的原型声明,这样Yacc生成的y.tab.h会包含这些声明,而Lex文件已经引用了y.tab.h,两边的代码就能找到正确的函数签名:
%{ #include <stdio.h> int sym[26]; // 添加函数原型,解决隐式声明问题 int yyerror(char *s); extern int yylex(void); %}
另外,原代码里的main()没有返回类型,这不符合C标准,我会在完整代码里一并修复。
2. 修复Lex代码的语法错误
把ex1.l最后一行的错误处理代码加上大括号:
. { yyerror("invalid character"); }
原来的写法缺少大括号,Lex可能无法正确解析这个规则。
修复后的完整代码
ex1.y
%{ #include <stdio.h> int sym[26]; int yyerror(char *s); extern int yylex(void); %} %token INTEGER VARIABLE %left '+' '-' %left '*' '/' '%' %% program: program statement '\n' | ; statement: expr {printf("%d\n", $1);} | VARIABLE '=' expr {sym[$1] = $3;} ; expr: INTEGER | VARIABLE { $$ = sym[$1];} | expr '+' expr { $$ = $1 + $3;} | expr '-' expr { $$ = $1 - $3;} | expr '*' expr { $$ = $1 * $3;} | expr '/' expr { $$ = $1 / $3;} | '(' expr ')' { $$ = $2;} ; %% int main() { return yyparse();} int yyerror(char *s){ fprintf(stderr,"%s\n",s); return 0; }
ex1.l
%{ #include <stdlib.h> #include "y.tab.h" %} %% /* variables */ [a-z] { yylval = *yytext -'a'; return VARIABLE; } /* integers */ [0-9]+ { yylval = atoi(yytext); return INTEGER; } /* operators */ [-+()=/*\n] { return *yytext;} /* skip whitespace */ [ \t] ; /* anything else is an error */ . { yyerror("invalid character"); } %% int yywrap (void){ return 1; }
重新编译
执行你原来的编译命令,现在所有警告都会消失:
$ bison -d -y ex1.y $ lex ex1.l $ gcc lex.yy.c y.tab.c -o ex1
内容的提问来源于stack exchange,提问作者user9178840
相关产品推荐
相关产品推荐

