编译Flex&Bison+C++代码时遇‘yylex未声明’错误,如何解决?
解决g++编译Flex+Bison代码时
yylex/yyerror未声明的问题 核心原因
Bison默认生成C风格代码,而g作为C编译器会对函数名进行名字修饰(Name Mangling),导致C风格的yylex/yyerror与C++代码中调用的函数名不匹配。你之前添加的extern "C"因位置不正确,未覆盖到关键的函数声明/定义,所以无效。
具体修复步骤
1. 修改Flex词法分析器文件
在词法文件的%{ ... %}块中,用extern "C"包裹yylex的声明及相关枚举、变量,确保Flex生成的yylex被识别为C风格函数:
/* lexer */ %{ extern "C" { enum yytokentype { NUMBER = 258, ADD = 259, SUB = 260, MUL = 261, DIV = 262, ABS = 263, EOL = 264 }; int yylval; int yylex(void); // 显式声明yylex为C风格 } %} %option nounput %% "+" { return ADD; } "-" { return SUB; } "*" { return MUL; } "/" { return DIV; } "|" { return ABS; } [0-9]+ { yylval = atoi(yytext); return NUMBER; } \n { return EOL; } [ \t] { /* ignore whitespace */ } . { printf("Mystery character %c\n", *yytext); } %%
2. 修改Bison语法分析器文件
在语法文件的%{ ... %}块中添加yylex的extern "C"声明,同时将yyerror的定义包裹在extern "C"块中,避免名字修饰:
/* parser */ %{ #include <stdio.h> extern "C" int yylex(void); // 告诉Bison调用C风格的yylex %} /* declare tokens */ %token NUMBER %token ADD SUB MUL DIV ABS %token EOL %% calclist: /* nothing */ | calclist exp EOL { printf("= %d\n", $2); } // 注意:原代码$1是calclist本身,逻辑错误,应改为$2获取exp的计算结果 ; exp: factor | exp ADD factor { $$ = $1 + $3; } | exp SUB factor { $$ = $1 - $3; } ; factor: term | factor MUL term { $$ = $1 * $3; } | factor DIV term { $$ = $1 / $3; } ; term: NUMBER | ABS term { $$ = $2 >= 0? $2 : -$2; } ; %% extern "C" { int yyerror(char *s) { fprintf(stderr, "error: %s\n", s); return 1; } }
3. 修改C++主文件
在调用yyparse()之前,添加yyparse的extern "C"声明,因为Bison生成的yyparse是C风格函数:
// 你的C++源码文件 #include "parser.tab.h" extern "C" int yyparse(void); // 声明yyparse为C风格 void execute() { yyparse(); }
4. 编译命令
按以下顺序执行编译步骤:
# 生成词法分析器代码 flex lexer.l # 生成语法分析器代码及头文件 bison -d parser.y # 用g++编译所有文件 g++ -o calculator lex.yy.c parser.tab.c main.cpp
内容的提问来源于stack exchange,提问作者user20417373
相关产品推荐
相关产品推荐

