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! 示例,请贴出规则我来示范。

posted on 2025-06-01 16:32  及途又八  阅读(22)  评论(0)    收藏  举报

导航