12个版本

0.3.2 2022年3月24日
0.3.0 2020年1月20日
0.2.4 2019年5月1日
0.2.3 2019年2月21日
0.0.4 2016年9月10日

#69 in 解析工具


2 个crate中使用

MIT 许可证

155KB
1K SLoC

文档

Earlgrey是一个crate,用于构建能够理解上下文无关语法的解析器。

如何使用

解析阶段

  • 首先,您需要使用 GrammarBuilder 定义终端和规则来定义语法。
  • 然后为该语法构建一个 EarleyParser 并在某个输入上调用 parse

在某个输入上调用解析器返回一个不透明的类型(Earley项的列表),它编码了所有可能的树。如果语法是无歧义的,这应该表示一棵树。

评估结果

您需要一个 EarleyForest,它将遍历所有结果解析树并对它们进行操作。

  • 为此,您提供一个函数,该函数给定一个终端产生一个AST节点。
  • 然后您定义语义操作来评估如何解释语法中的每个规则。

示例

一个玩具解析器,可以理解求和。

fn main() {
    // Gramar:  S -> S + N | N;  N -> [0-9];
    let g = earlgrey::GrammarBuilder::default()
      .nonterm("S")
      .nonterm("N")
      .terminal("[+]", |c| c == "+")
      .terminal("[0-9]", |n| "1234567890".contains(n))
      .rule("S", &["S", "[+]", "N"])
      .rule("S", &["N"])
      .rule("N", &["[0-9]"])
      .into_grammar("S")
      .unwrap();

    // Parse some sum
    let input = "1 + 2 + 3".split_whitespace();
    let trees = earlgrey::EarleyParser::new(g)
        .parse(input)
        .unwrap();

    // Evaluate the results
    // Describe what to do when we find a Terminal
    let mut ev = earlgrey::EarleyForest::new(
        |symbol, token| match symbol {
            "[0-9]" => token.parse().unwrap(),
            _ => 0.0,
        });

    // Describe how to execute grammar rules
    ev.action("S -> S [+] N", |n| n[0] + n[2]);
    ev.action("S -> N", |n| n[0]);
    ev.action("N -> [0-9]", |n| n[0]);

    println!("{}", ev.eval(&trees).unwrap());
}

Earley算法的参考资料

无运行时依赖