Bison编译文法规则时出现2个shift/reduce冲突的排查解决咨询
问题理解验证
你对冲突原因的判断完全正确。这两个冲突本质上是同一根源导致的:当解析器处于已匹配完pointer_opt的状态,遇到下一个输入为(时,存在两条合法推导路径:
- 路径1:将
(移入,匹配direct_declarator规则中的LPAR declarator RPAR分支,用于解析带括号的普通声明符,比如int (*a)里的(*a) - 路径2:先将空串归约为
direct_abstract_declarator_opt,后续匹配function_abstract_declarator规则中的LPAR parameter_type_list RPAR分支,用于解析无标识符的抽象声明符,比如int (*)(int)里的(*)(int)
LALR(1)解析器无法仅通过前看1个token(判断该走哪条路径,因此触发shift/reduce冲突。
冲突解决方法
问题的核心是array_abstract_declarator和function_abstract_declarator规则中使用了可空的direct_abstract_declarator_opt作为前缀,引入了不必要的空归约分支。只需要重构抽象声明符相关的文法规则,去掉可空前缀的设计即可解决冲突,修改后语义完全兼容原有规则:
原有需要删除的规则
direct_abstract_declarator_opt: %empty | direct_abstract_declarator ; array_abstract_declarator: direct_abstract_declarator_opt LBRA assignment_expression RBRA ; function_abstract_declarator: direct_abstract_declarator_opt LPAR parameter_type_list RPAR ;
替换后的新规则
direct_abstract_declarator: LPAR abstract_declarator RPAR // 直接支持无前缀的数组/函数抽象声明符 | LBRA assignment_expression RBRA | LPAR parameter_type_list RPAR // 递归支持带前缀的嵌套结构 | direct_abstract_declarator LBRA assignment_expression RBRA | direct_abstract_declarator LPAR parameter_type_list RPAR ;
修改完成后重新编译Bison文法,两个shift/reduce冲突会同时消失,原有所有合法的声明、类型名语法都可以正常解析。
内容的提问来源于stack exchange,提问作者Riomare
相关产品推荐
相关产品推荐

