不使用assoc指令解决Bison中悬空else问题时存在shift/reduce冲突
冲突根源
你当前的文法拆分逻辑存在漏洞:OpenStatement的第一条产生式中使用了未做开放/闭合拆分的Statement作为then后的子句,导致解析到if 表达式 then 闭合语句结构后遇到else时,解析器存在两个合法路径:
- 将前面的
ClosedStatement归约为ConditionStmt,匹配无else的if分支 - 移入
else,继续匹配带else的if分支
这就是你遇到的shift/reduce冲突的来源。
修改方案
调整产生式的层级约束,强制无else的if分支的then后只能跟开放语句,确保if 表达式 then 闭合语句结构不会被判定为完整的无else分支,必须等待后续的else移入,从规则层面消除冲突。修改后的完整文法规则如下:
// 顶层语句节点,对应你原有的ConditionStmt Statement : ClosedStatement { $$ = $1; } | OpenStatement { $$ = $1; } ; OpenStatement // 核心修改:原来的Statement替换为OpenStatement,无else的if分支的then后只能是开放语句 : "if" SimpleExpression "then" OpenStatement {$$ = ast::action::MakeStatement<ast::Branch>({$2, $4}, @1, ast::BranchType::kIf); } | "if" SimpleExpression "then" ClosedStatement "else" OpenStatement {$$ = ast::action::MakeStatement<ast::Branch>({$2, $4, $6}, @1, ast::BranchType::kIf); } | "while" SimpleExpression "do" OpenStatement { $$ = ast::action::MakeStatement<ast::Iterator>({$2, $4}, @1, ast::IteratorType::kWhile); } ; ClosedStatement : "if" SimpleExpression "then" ClosedStatement "else" ClosedStatement { \ $$ = ast::action::MakeStatement<ast::Branch>({$2, $4, $6}, @1, ast::BranchType::kIf); \ } | "while" SimpleExpression "do" ClosedStatement { $$ = ast::action::MakeStatement<ast::Iterator>({$2, $4}, @1, ast::IteratorType::kWhile); } | NonIfStatement ;
如果你的文法顶层已经用了其他名称对应语句节点,直接把原来的ConditionStmt下的OpenStatement第一条产生式的Statement替换为OpenStatement即可生效,不需要额外调整其他规则。
内容的提问来源于stack exchange,提问作者Carl Dent
相关产品推荐
相关产品推荐

