1 个不稳定版本
0.1.0 | 2024 年 7 月 13 日 |
---|
#77 在 解析工具
120 每月下载量
21KB
456 行
Pratt-Gen
一个使用内联宏的递归下降解析生成库。
Json
例如,要解析 JSON 文件,你可以编写以下代码,并使用 parse<Json>
来解析格式化的 JSON 字符串。就这么简单。
use pratt_gen::*;
#[derive(Clone, Copy, ParserImpl, Space)]
pub enum Json<'a> {
#[parse("{0}")]
Float(f64),
#[parse("{0}")]
Int(i64),
#[parse("{0}")]
Str(&'a str),
#[parse("{{ {0} }}")]
Obj(&'a Obj<'a>),
#[parse("[ {0} ]")]
Arr(&'a Arr<'a>),
}
#[derive(Clone, Copy, ParserImpl, Space)]
pub enum Obj<'a> {
#[parse("{0} : {1} , {2}")]
Next(Ident<'a>, Json<'a>, &'a Obj<'a>),
#[parse("{0} : {1}")]
Just(Ident<'a>, Json<'a>),
#[parse("")]
Null(),
}
#[derive(Clone, Copy, ParserImpl, Space)]
pub enum Arr<'a> {
#[parse("{0} , {1}")]
Next(Json<'a>, &'a Arr<'a>),
#[parse("{0}")]
Just(Json<'a>),
#[parse("")]
Null(),
}
格式字符串很简单。你可以将其视为 Rust 打印格式字符串的反向。
// printing
println!("{0} + {1}", "a", "b");
// when we match {0} to something and {1} to something.
// we fill it as Add({0}, {1})
#[parse("{0} + {1}", precedence=4)]
Add(&'a Expr<'a>, &'a Expr<'a>),
优先级
要处理具有左递归和优先级的二进制表达式,你可以这样做
use pratt_gen::*;
#[derive(Debug, Clone, Copy, ParserImpl, Space)]
pub enum Expr<'a> {
#[parse("{0:2} + {1:1}", precedence=2)]
Add(&'a Expr<'a>, &'a Expr<'a>),
#[parse("{0:4} + {1:3}", precedence=4)]
Mul(&'a Expr<'a>, &'a Expr<'a>),
#[parse("{0}")]
Number(i64),
}
precedence=...
为此模式赋予优先级,并在洞后放置一个数字 {...:n}
,这意味着我们只允许在该洞中有优先级 <n
的规则。
因此 Mul
只允许左侧有 Number
。
陷阱
递归下降解析器的一个坏处是它只支持右结合,所以 a - b - c
被解析为 a - (b - c)
,这并不是我们通常所想的。但你可以编写一个转换来移除它或实现 add/sub 作为迭代器。
依赖
~4.5–6.5MB
~86K SLoC