LALRPOP语法解析失败求助:特定表达式无法正常解析
Lalrpop语法解析问题解决方案
问题根源
你遇到的解析失败问题,核心是对Lalrpop的#[precedence]属性用法理解偏差。Lalrpop的优先级规则与Yacc/Bison差异较大:Yacc是给token设置优先级,而Lalrpop是给产生式设置优先级,且强制要求同一非终结符的所有产生式必须统一设置优先级,这容易导致解析器在归约高优先级产生式后,无法识别后续低优先级运算符的合法语法结构。
解决方案:用非终结符分层替代优先级属性
更直观且符合Yacc/Bison使用习惯的方式是通过非终结符分层明确表达式优先级,避免依赖容易混淆的#[precedence]属性。重构后的语法如下:
use crate::ast::Expr; grammar; Id: String = <id:r"[a-z]+"> => id.to_owned(); // 处理加法表达式(右结合),优先级低于PrimaryExpr pub ExprTy: Expr = { #[assoc(side="right")] ExprTy "+" PrimaryExpr => Expr::Plus{ lhs: Box::new(ExprTy), rhs: Box::new(PrimaryExpr) }, // 基础表达式直接提升为ExprTy PrimaryExpr => PrimaryExpr, }; // 处理高优先级表达式:函数调用、条件表达式、标识符 PrimaryExpr: Expr = { <method_name: Id> "(" ")" => Expr::Dispatch{method_name}, "if" <pred_expr: ExprTy> "then" <then_expr: ExprTy> "else" <else_expr: ExprTy> "fi" => Expr::Cond{ pred_expr: Box::new(pred_expr), then_expr: Box::new(then_expr), else_expr: Box::new(else_expr) }, <id: Id> => Expr::Object{id}, };
方案说明
分层逻辑:
PrimaryExpr:包含最高优先级的表达式类型(函数调用、if条件表达式、标识符),确保这些结构可以作为加法的操作数。ExprTy:专门处理加法运算,通过左递归实现右结合(符合你原有的#[assoc(side="right")]需求),同时允许PrimaryExpr直接升级为ExprTy。
解决所有测试用例:
g() + y:解析为(g()) + y,g()作为PrimaryExpr被识别为加法左操作数,合法。if x then y else z fi + w:条件表达式作为PrimaryExpr,可作为加法左操作数,合法。if x + y then a else b fi:x + y是合法的ExprTy,可作为条件表达式的谓词,合法。x + y:正常解析为加法表达式,符合预期。
内容的提问来源于stack exchange,提问作者tarski
相关产品推荐
相关产品推荐

