lalrpop产生式语法规则如何定义优先级?
lalrpop产生式语法规则如何定义优先级?
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
在 LALRPOP 中,定义优先级是通过 precedence!
块 + %prec
指令来实现的,类似于 yacc/bison 的方式,但也有一些 Rust 风格的特色。
✅ 方法一:使用 precedence!
块定义优先级(推荐)
LALRPOP 提供了 precedence!
宏语法,允许你为表达式定义多个子规则,并指定优先级从上到下(上面优先级低,下面优先级高)。
示例:定义加减乘除的优先级和结合性
Expr: i32 = {
<l:Expr> "+" <r:Expr> => l + r,
<l:Expr> "-" <r:Expr> => l - r,
<l:Expr> "*" <r:Expr> => l * r,
<l:Expr> "/" <r:Expr> => l / r,
Num,
};
Num: i32 = {
<n:r#"[0-9]+"#> => n.parse().unwrap()
};
上面的定义中,运算符没有优先级和结合性,会导致冲突。
我们应该使用 precedence!
:
Expr: i32 = {
precedence!{
L {
<l:Expr> "+" <r:Expr> => l + r,
<l:Expr> "-" <r:Expr> => l - r,
}
L {
<l:Expr> "*" <r:Expr> => l * r,
<l:Expr> "/" <r:Expr> => l / r,
}
--
Num,
}
};
Num: i32 = {
<n:r#"[0-9]+"#> => n.parse().unwrap()
};
✅ 说明:
-
precedence!
从上到下,优先级 越低。 -
每一组可以用
L
,R
, 或N
指定结合性:L
左结合(如加减)R
右结合(如赋值、幂)N
非结合(不能重复出现)
✅ 方法二:使用 %prec
显式指定优先级(不常用)
你也可以在规则后使用 %prec
显式指定优先级标记,但 LALRPOP 不内建支持 %left/%right 等声明,所以此方式常与更底层的语义动作配合使用,不推荐新用户使用。
🧠 实际建议
- 优先使用
precedence!
宏。 - 避免在一个规则中直接嵌套多个运算符,会造成 shift/reduce 冲突。
- 如果你是从 yacc/bison 迁移过来,
precedence!
是 LALRPOP 提供的现代化替代方案。
如需我帮你为实际的 MDX 表达式或其他语法编写 precedence!
示例,请贴出规则我来示范。