You need to enable JavaScript to run this app. 编写yacc算术表达式校验程序出现shift/reduce冲突如何解决
优惠活动
大模型
产品
解决方案
定价
更多

编写yacc算术表达式校验程序出现shift/reduce冲突如何解决

解决yacc算术表达式校验的shift/reduce冲突问题

冲突原因

你遇到的2个移位/规约冲突由以下两个问题共同导致:

  • 你将+、-、*、/四种优先级、结合性完全不同的运算符统一归为OPERATOR这一个token,yacc无法区分不同运算符的优先级差异
  • 没有显式指定运算符的结合性,解析连续同优先级运算时,yacc无法判断应该优先规约左边的表达式,还是优先移位读入右边的运算符

修复步骤

1. 修改lex代码,拆分运算符token返回值

不要统一返回OPERATOR,改为为每个运算符返回独立的token:

%{
    #include "y.tab.h"
%}

%%
[0-9]+ { return NUMBER; }
[_a-zA-Z][_a-zA-Z0-9]* { return ID; }
"+" { return PLUS; }
"-" { return MINUS; }
"*" { return MUL; }
"/" { return DIV; }
.|\n { return *yytext; }
%%

int yywrap(){
    return 1;
}

2. 修改yacc代码,指定运算符结合性和优先级

通过%left指定左结合性,按优先级从低到高排列运算符,优先级低的写在前面,优先级高的写在后面:

%{
    #include<stdio.h>
    int yylex();
    void yyerror(const char*);
%}

%token NUMBER ID
/* 指定结合性和优先级,越靠后优先级越高 */
%left PLUS MINUS
%left MUL DIV

%%
E : E '\n' { return 0; }
  | E PLUS E
  | E MINUS E
  | E MUL E
  | E DIV E
  | '(' E ')'
  | NUMBER
  | ID
  ;
%%

void yyerror(const char* s){
    printf("%s\n", s);
}

int main(){
    if(yyparse() == 0)
        printf("Valid Arithmetic Expression\n");
    else
        printf("Invalid Arithmetic Expression\n");
}

修改完成后重新编译即可消除移位/规约冲突警告,同时解析逻辑也符合常规算术运算的优先级和结合性规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 16:06:01