3个版本
0.1.2 | 2023年2月1日 |
---|---|
0.1.1 | 2023年2月1日 |
0.1.0 | 2023年2月1日 |
2443 在 Rust模式
26 每月下载次数
12KB
239 行
regex-bnf
一种基于宏的BNF风格解析器,用于简化语法定义。
这种方法在您需要解析复杂语法而无需先进行标记化时很有用,例如,当标记可能包含空格和新行,并且周围有复杂规则时。
以下是一个简单的CSV解析器示例
use regex_bnf::*;
bnf! {
Value = <!Eof> <!NewLine> val:r"([^,\r\n]|\\,)*" <?Comma>;
Line = <!Eof> values:<[Value]> <LineEnd>;
Document = lines:<[Line]^>;
Comma = ",";
NewLine = r"[\r\n]+";
Eof = ^;
enum LineEnd = [NewLine | Eof];
}
上述宏为每个标记创建一个结构体(Value
、Line
、Document
等)和一个枚举类型为LineEnd
。每个结构和枚举都包含一个解析函数,该函数接受一个StringParser并返回一个包含(解析值, 剩余字符串)
或错误的Result。
注意
此实现完全确定,可能存在死锁,包括无限循环和栈溢出。为了调试它,请按声明顺序线性读取每个结构。因此,在上面的CSV示例中,LineEnd
将首先尝试解析NewLine
,然后是Eof
。如果解析失败,则返回错误。
性能
解析器性能非常高,因为它具有零非确定性行为,并且除了可选的boxed标记之外,不执行任何其他分配。所有解析的字符串都作为切片引用,包括其位置(索引、行号、列号)。
语法
有两种类型的声明
- 标签:是一系列标记,包括文字、正则表达式或其他标记类型,它们线性解析。
- 枚举:是一系列标签,每个标签都尝试解析。如果返回错误,则尝试下一个。如果所有标签都失败,则返回错误。
在标签声明中,您可以使用<标记>
为标记添加标签,以便在生成的结构体中为其提供字段名,否则将省略。
以下是所有可能的标记类型
- 字符串文字:
""
- 正则表达式:
r""
- 标签:
<Tag>
(内联),<*Tag>
(boxed,以避免无限大小的结构体) - 可选标签:
<?标签>
- 重复标签:
<[标签]*>
(零次或多次),<[标签]+>
(一次或多次),<[标签]^>
(直到字符串结束) - 非标签:
<!标签>
(如果标签解析成功则失败)
依赖项
约3-4.5MB
约88K SLoC