使用Flex和Bison(C++)开发简单字符串输出程序时遭遇yylex函数参数过多编译错误求助
使用Flex和Bison(C++)开发简单字符串输出程序时遭遇yylex函数参数过多编译错误求助
嘿,我来帮你搞定这个编译错误!这个问题的核心是Flex生成的yylex函数和Bison C++骨架期望的接口不匹配,咱们一步步来解决:
错误原因分析
你用了Bison的C++骨架(%skeleton "lalr1.cc"),并且开启了variant类型的语义值(%define api.value.type variant),这种情况下Bison会生成一个需要接收语义值指针参数的yylex调用逻辑,但你在parser里声明的int yylex();没有参数,同时Flex代码也没适配这个接口,所以编译器就报错“too many arguments to function ‘int yylex()’”了。
解决方案:调整Flex和Parser的接口匹配
我把修改后的完整代码给你,同时解释关键改动点:
1. 修改Flex Lexer代码(lexer.l)
%{ #include "parser.tab.h" // 删掉原来的yylval和STRING枚举,Bison已经帮我们定义好了token类型和语义值类型 %} %option noyywrap c++ debug %option prefix="yy" // 确保和Bison默认的前缀一致,避免命名冲突 // 匹配带引号的字符串,注意转义处理 WORD \"(\\.|\\\n|[^\\\"])*\" %% {WORD} { // 去掉字符串前后的引号,把内容赋值给Bison的语义值 std::string raw_str(yytext); *yylval = raw_str.substr(1, raw_str.length() - 2); return yy::parser::token::STR; } // 忽略空白字符(换行、制表符、空格) [\n\t ] ; %%
关键改动:
- 移除了旧的
yylval声明和自定义的STRING枚举,改用Bison生成的yy::parser::token::STR - 新增了对传入的语义值指针
yylval的赋值,把解析到的字符串(去掉引号)传递给Parser
2. 修改Bison Parser代码(parser.ypp)
%{ #include <iostream> // 修正yylex的声明,让它接收Bison语义值的指针参数 int yylex(yy::parser::semantic_type* yylval); %} %skeleton "lalr1.cc" %require "3.0.2" %define api.value.type variant %define api.token.constructor // 可选,让token的构造更安全 %define parse.error verbose // 可选,输出更友好的错误信息 %token <std::string> STR %start program %% // 简化规则,直接用$1获取STR的语义值 program : STR { std::cout << $1 << std::endl; } ; %% int main() { yy::parser parser; return parser.parse(); } namespace yy { void parser::error(const std::string& m) { std::cerr << "错误提示:" << m << std::endl; } }
关键改动:
- 把
int yylex();改成int yylex(yy::parser::semantic_type* yylval);,匹配Bison调用时的参数 - 简化了
program规则,原来的STR[a]是较旧的语法,直接用$1就能拿到STR对应的字符串值
编译和测试
按以下命令编译(假设你的文件是lexer.l和parser.ypp):
# 生成Parser的头文件和源文件 bison -d parser.ypp # 生成Lexer的源文件 flex lexer.l # 编译链接成可执行文件 g++ -o string_printer parser.tab.cc lex.yy.cc -lfl
运行程序后,输入带引号的字符串比如"Hello Flex & Bison!",回车后就能看到输出:Hello Flex & Bison!
备注:内容来源于stack exchange,提问作者tomdawncats
相关产品推荐
相关产品推荐

