#parser-generator #compiler #parser #json-parser #parser-tools

鸽子实现

生成递归下降和优先级爬升解析器。(额外实现)

1 个不稳定版本

0.2.0 2024年8月3日

1248开发工具

Download history 91/week @ 2024-07-29 21/week @ 2024-08-05

112 每月下载量

MIT/Apache

20KB
372

鸽子

一个使用内联宏的递归下降解析器生成库。

Json

例如,要解析一个 json 文件,你可以编写以下代码,并使用 parse<Json> 来解析一个 json 格式的字符串。就是这样。

use pigeon::*;

#[derive(Clone, Copy, ParseImpl, 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>),
    #[parse("null")]
    Null(),
    #[parse("{0}")]
    Bool(Bool),
}

#[derive(Clone, Copy, ParesrImpl, Space)]
pub enum Bool {
    #[parse("true")]
    True(),
    #[parse("false")]
    False(),
}

#[derive(Clone, Copy, ParseImpl, 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, ParseImpl, 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 pigeon::*;

#[derive(Debug, Clone, Copy, ParseImpl, 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),这并不是我们通常所想的。但你可以编写一个转换来消除它,或者将加法/减法实现为迭代器。

依赖关系

~3.5–5.5MB
~99K SLoC