13 个版本

0.0.13 2024 年 8 月 6 日
0.0.12 2024 年 5 月 15 日
0.0.11 2024 年 4 月 23 日
0.0.9 2024 年 3 月 15 日
0.0.4 2024 年 2 月 24 日

#211Rust 模式

Download history 45/week @ 2024-05-03 626/week @ 2024-05-10 6836/week @ 2024-05-17 1381/week @ 2024-05-24 901/week @ 2024-05-31 552/week @ 2024-06-07 399/week @ 2024-06-14 290/week @ 2024-06-21 328/week @ 2024-06-28 276/week @ 2024-07-05 179/week @ 2024-07-12 164/week @ 2024-07-19 185/week @ 2024-07-26 361/week @ 2024-08-02 341/week @ 2024-08-09 228/week @ 2024-08-16

4,937 每月下载量
5 个crate中使用 (3 直接使用)

MIT 许可证

12KB
216

最简单的解析库 (TSPL)

TSPL 是在 Rust 中工作的最简单的解析库。

概念

在像 Haskell 这样的纯函数式语言中,解析器可以表示为一个函数

Parser<A> ::= String -> Reply<A, Error>

这允许我们为 Parser<A> 实现一个 Monad 实例,让我们可以使用 do-notation 来为我们的自定义类型创建简单而优雅的解析器。遗憾的是,Rust 没有等效的功能。然而,我们可以通过以下方式轻松地模拟它

  1. 使用结构和 impl 来内部管理游标状态。

  2. 返回一个 Result,这允许我们使用 Rust 的 ? 来模拟 monadic 块。

这个库仅仅暴露了一些函数来实现解析器,没有其他功能。

示例

作为一个例子,让我们使用 TSPL 创建一个 λ-Term 解析器。

  1. 实现你想要创建解析器的类型。
enum Term {
  Lam { name: String, body: Box<Term> },
  App { func: Box<Term>, argm: Box<Term> },
  Var { name: String },
}
  1. 定义你的语法。我们将使用以下
<term> ::= <lam> | <app> | <var>
<lam>  ::= "λ" <name> " " <term>
<app>  ::= "(" <term> " " <term> ")"
<var>  ::= alphanumeric_string
  1. 使用 new_parser()! 宏创建一个新的解析器。
TSPL::new_parser!(TermParser);
  1. 使用你的语法创建一个 impl TermParser
impl<'i> TermParser<'i> {
  fn parse(&mut self) -> Result<Term, String> {
    self.skip_trivia();
    match self.peek_one() {
      Some('λ') => {
        self.consume("λ")?;
        let name = self.parse_name()?;
        let body = Box::new(self.parse()?);
        Ok(Term::Lam { name, body })
      }
      Some('(') => {
        self.consume("(")?;
        let func = Box::new(self.parse()?);
        let argm = Box::new(self.parse()?);
        self.consume(")")?;
        Ok(Term::App { func, argm })
      }
      _ => {
        let name = self.parse_name()?;
        Ok(Term::Var { name })
      }
    }
  }
}
  1. 使用你的解析器!
fn main() {
  let mut parser = TermParser::new("λx(λy(x y) λz z)");
  match parser.parse() {
    Ok(term) => println!("{:?}", term),
    Err(err) => eprintln!("{}", err),
  }
}

完整的示例可以在 ./examples/lambda_term.rs 中找到。运行它

cargo run --example lambda_term

致谢

此设计基于 T6 为 HVM-Core 的新解析器,比旧的 HOPA 方法干净得多。

依赖关系

~16KB