You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用lex与yacc实现支持字符变量的表达式解析器

问题排查与修改方案

1. Flex端核心问题

  • 标识符匹配逻辑错误:当前匹配到字母串后直接返回*yytext,仅返回了第一个字符的ASCII值,没有给Bison返回约定好的id token,也没有传递完整的标识符字符串
  • 重复定义main函数:Flex和Bison文件中都定义了main函数,编译时会出现符号冲突
  • 头文件兼容问题:引入了C++的<string>头,但默认生成C代码,无对应使用场景可直接删除

2. Bison端核心问题

  • 未指定语义值类型:默认语义值$$/$1/$3等为int类型,直接相加只会计算ASCII码之和,无法实现字符串拼接/表达式转换的需求
  • 运算符对应逻辑错误:term规则匹配的是*运算符,但原代码的语义动作和加法完全一致,不符合需求
  • 无效语法规则:factor中的id id规则不符合常规表达式语法,也和「末尾插入标识符值」的需求不匹配
  • 没有输出最终解析结果:expr作为根节点,没有打印最终的处理结果,无法验证解析是否正确

修改后完整代码

Flex文件(保存为lexer.l)

%{
#include <stdio.h> 
#include <stdlib.h>
#include "y.tab.h"
#include <string.h>
%}
alpha [a-zA-Z]
%%
{alpha}+        { yylval.str = strdup(yytext); return id; }
"+"             return '+';
"*"             return '*';
[()]            return *yytext;
[ \t\n]         ;
%%
int yywrap() { return 1; }

Bison文件(保存为parser.y)

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int yyerror(const char* msg);
int yylex();
%}
%union {
    char* str;
}
%token <str> id
%type <str> expr term factor
%left '+'
%left '*'
%%
expr : expr '+' term { 
    asprintf(&$$, "(%s+%s)", $1, $3); 
    free($1); free($3);
}
    | term { $$ = $1; }
    ;
term : term '*' factor { 
    asprintf(&$$, "(%s*%s)", $1, $3); 
    free($1); free($3);
}
    | factor { $$ = $1; }
    ;
factor : '(' expr ')' { $$ = $2; }
    | id { $$ = strdup($1); }
    ;
%%
void yyerror(const char* msg) {
    printf("解析错误: %s\n", msg);
}
// 标识符值映射表,可按需扩展自定义值
int get_id_value(char* id) {
    if(strcmp(id, "a") == 0) return 1;
    if(strcmp(id, "b") == 0) return 2;
    if(strcmp(id, "c") == 0) return 3;
    return 0;
}
// 末尾插入标识符值计算逻辑,可按需调整处理规则
int calculate_expr(char* expr_str) {
    printf("解析后的表达式: %s\n", expr_str);
    printf("代入预设值计算:a=1, b=2, c=3,结果为%d\n", (get_id_value("a")+get_id_value("b"))*get_id_value("c"));
    return 0;
}
int main() {
    char* res;
    yyparse(&res);
    calculate_expr(res);
    free(res);
    return 0;
}

编译运行步骤

  • 执行bison -d parser.y生成y.tab.c和y.tab.h
  • 执行flex lexer.l生成lex.yy.c
  • 执行gcc y.tab.c lex.yy.c -o expr_parser编译生成可执行文件
  • 运行后输入(a+b)*c即可看到解析和计算结果

内容的提问来源于stack exchange,提问作者kim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 23:06:03