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 日 |
#211 在 Rust 模式
4,937 每月下载量
在 5 个crate中使用 (3 直接使用)
12KB
216 行
最简单的解析库 (TSPL)
TSPL 是在 Rust 中工作的最简单的解析库。
概念
在像 Haskell 这样的纯函数式语言中,解析器可以表示为一个函数
Parser<A> ::= String -> Reply<A, Error>
这允许我们为 Parser<A>
实现一个 Monad 实例,让我们可以使用 do-notation
来为我们的自定义类型创建简单而优雅的解析器。遗憾的是,Rust 没有等效的功能。然而,我们可以通过以下方式轻松地模拟它
-
使用结构和
impl
来内部管理游标状态。 -
返回一个
Result
,这允许我们使用 Rust 的?
来模拟 monadic 块。
这个库仅仅暴露了一些函数来实现解析器,没有其他功能。
示例
作为一个例子,让我们使用 TSPL 创建一个 λ-Term 解析器。
- 实现你想要创建解析器的类型。
enum Term {
Lam { name: String, body: Box<Term> },
App { func: Box<Term>, argm: Box<Term> },
Var { name: String },
}
- 定义你的语法。我们将使用以下
<term> ::= <lam> | <app> | <var>
<lam> ::= "λ" <name> " " <term>
<app> ::= "(" <term> " " <term> ")"
<var> ::= alphanumeric_string
- 使用
new_parser()!
宏创建一个新的解析器。
TSPL::new_parser!(TermParser);
- 使用你的语法创建一个
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 })
}
}
}
}
- 使用你的解析器!
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
致谢
依赖关系
~16KB