Yacc/bison解析语法报错:IF分支遇到意外endif,期望接收分号
问题原因
报错的核心是未消除的移进/归约冲突:因作业要求不能使用优先级声明,当前语法规则存在二义性,Bison默认的移进策略和预期的IF语句匹配逻辑不符。解析完ELSE分支带分号的statement_后,Bison会错误判定外层语句已经结束,等待接收分号,不会继续移位匹配后续的ENDIF标记。
解决步骤
1. 排查冲突
运行以下命令生成Bison状态分析文件,确认冲突具体位置:
bison -Wconflicts-rr -Wconflicts-sr -v parser.y
生成的parser.output文件会明确标注所有移进/归约、归约/归约冲突,必须全部解决这些冲突才能保证语法解析符合预期。
2. 调整语法规则消除二义性
通过显式拆分「不带分号的基础语句」和「带分号的语句单元」消除IF语句的歧义,调整后的参考规则如下:
// 不带分号的基础语句:包括表达式、IF复合语句 statement: expression | IF expression THEN statement_with_semicolon ELSE statement_with_semicolon ENDIF ; // 带分号的语句单元:用于块内的单个语句项 statement_with_semicolon: statement ';' | error ';' ; // 表达式部分保持不变,左递归规则已经天然实现运算优先级,不需要额外优先级声明 expression: expression ANDOP relation | relation ; relation: relation RELOP term | term; term: term ADDOP factor | factor ; factor: factor MULOP primary | primary ; primary: '(' expression ')' | INT_LITERAL | IDENTIFIER ;
如果你的语法中包含begin/end复合块规则,同步调整为匹配statement_with_semicolon序列即可:
compound_stmt: BEGIN statement_list END ; statement_list: statement_with_semicolon | statement_list statement_with_semicolon ;
额外排查点
确认Flex词法规则中,所有关键字(IF、THEN、ELSE、ENDIF等)的匹配规则写在IDENTIFIER规则之前,避免关键字被错误识别为标识符。
内容的提问来源于stack exchange,提问作者ganondork
相关产品推荐
相关产品推荐

