Bison构建Python解析器时含括号算术表达式语法错误排查
问题分析与修复方案
核心问题
你的语法规则层级设计错误:括号表达式被定义在arith_expr层级,但处理乘除模运算的factor无法引用arith_expr。当解析(a + b) * 2时,(a + b)会被直接归约为arith_expr,此时解析器认为赋值语句的右侧表达式已经完成,后续的*就变成了意外token,触发语法错误。
修复步骤
- 调整括号表达式的层级
把括号表达式移到term层级(最基础的表达式单元),这样它可以作为任何更高优先级运算的操作数:
term: identifier | literal_int | literal_float | TOKEN_PAREN_OPEN arith_expr TOKEN_PAREN_CLOSE { $$ = $2; };
- 移除
arith_expr中的括号规则
现在括号由term处理,arith_expr只需专注于加减运算:
arith_expr: factor | arith_expr TOKEN_ARITH_ADD factor { $$ = ast_init_arith_op($3, "+", $1); }; | arith_expr TOKEN_ARITH_SUB factor { $$ = ast_init_arith_op($3, "-", $1); }; ;
- 正确声明运算符优先级与结合性
用%left/%right明确运算符的优先级(括号 > 幂 > 乘除模 > 加减)和结合性(幂运算为右结合):
%left TOKEN_ARITH_ADD TOKEN_ARITH_SUB %left TOKEN_ARITH_MUL TOKEN_ARITH_DIV TOKEN_ARITH_MOD %right TOKEN_ARITH_POWER %token TOKEN_ASSIGN %token TOKEN_PAREN_OPEN TOKEN_PAREN_CLOSE %token identifier literal_int literal_float
- 修复赋值运算符的结合性声明
之前的错误是因为你给assign这个token错误地编写了语法规则,正确的做法是用%right声明其结合性(赋值为右结合):
%right TOKEN_ASSIGN
确保你的赋值语句规则类似:
statement: identifier TOKEN_ASSIGN arith_expr;
验证
修复后,(a + b) * 2会被正确解析:
(a + b)→term→power→factorfactor * power(2为term→power)归约为新的factor- 最终整个表达式作为
arith_expr,满足赋值语句的右侧要求
内容的提问来源于stack exchange,提问作者Havarem
相关产品推荐
相关产品推荐

