13个版本 (4个重大更新)
0.5.6 | 2020年4月13日 |
---|---|
0.5.5 | 2020年4月13日 |
0.5.3 | 2020年3月23日 |
0.5.1 | 2020年1月16日 |
0.1.2 | 2020年1月1日 |
#2089 in 开发工具
每月 30 次下载
25KB
457 行
Sexpy
从Rust类型定义中自动推导s表达式解析器。这个库旨在用于简单编程语言定义,并允许您对语言的解析进行一些控制。
文档
查看文档了解如何使用此库。
lib.rs
:
Sexpy从Rust类型定义中自动推导s表达式解析器。目标是能够从AST定义中进行,只需最少的注解。这适用于需要具有信息性解析错误消息和可读性语法(即非JSON)但不想编写完整解析器的原型编程语言。
为类型生成的默认解析器
为了了解如何使用此库,让我们看看为不同类型自动生成的解析器。
生成的默认解析器匹配“头部模式”。这些匹配一个关键字后面跟着一系列参数。例如,foo <string> <u32>
是一个头部模式,头部为foo
,它接受一个字符串参数和一个无符号32位整数作为第二个参数。这匹配foo cactus 20
但不匹配foo big cactus
。
结构体
为struct
类型生成的默认解析器使用结构体名称的小写版本作为头部,并将字段类型作为参数。它解析括号、方括号或花括号包围的头部模式。
例如,考虑以下内容
#[derive(Sexpy)]
struct Port {
name: String,
width: u64
}
这生成了一个解析器,用于处理以下形式的模式:(端口 <字符串> <u64>)
。例如,(端口 foo 10)
被解析为Port { name: ""foo"".to_string(), width: 10 }
和port foo 10
,而(端口 10 foo)
则无法解析。
枚举
对于枚举,为枚举中的每个情况生成一个解析器。默认情况下,每个解析器使用枚举名作为头部,将变体参数作为模式参数。每个解析器匹配括号、方括号或花括号包围的模式。
例如,考虑以下枚举定义
#[derive(Sexpy)]
enum Plant {
PalmTree(String, u64), // parses pattern: (plant <string> <u64>)
SageBush { height: u64 }, // parses pattern: (plant <u64>)
BarrelCactus // parses pattern: (plant)
}
这将在注释中生成三个解析器。如果有两个变体有相同的参数,会发生什么?
#[derive(Sexpy)]
enum Plant {
Palm(String, u64), // parses pattern: (plant <string> <u64>)
Cactus(String, u64) // parses pattern: (plant <string> <u64>)
}
默认情况下,cactus
变体将永远不会被解析。原因是无法区分Palm
变体子解析器和Cactus
变体子解析器;它们接受相同的参数!有几种处理方法,但最简单的方法是强制变体子解析器使用头部。您可以使用#[sexpy(head = ""<str>"")]
选项来完成此操作。
#[derive(Sexpy)]
enum Plant {
#[sexpy(head = "palm")]
Palm(String, u64), // parses pattern: (plant palm <string> <u64>)
#[sexpy(head = "cactus")]
Cactus(String, u64) // parses pattern: (plant cactus <string> <u64>)
}
注意事项
可能有两个解析器解析相同的模式。目前,Sexpy
没有做任何检测和防止这种行为。解决这些冲突的责任在于程序员。解析选项应使解决这些冲突变得容易。
选项
您可以通过指定一些属性来修改派生解析器匹配的模式。以下是一些在类型级别工作的属性,即
#[derive(Sexpy)]
#[sexpy(...)] // <-----
enum Plant { ... }
// or
#[derive(Sexpy)]
#[sexpy(...)] // <-----
struct Plant { ... }
所有属性都以逗号分隔的列表指定,如下所示:#[sexpy(attr = val, attr, ...)]
参数的形式为<attr> = <val>
。例如,当提供一个字符串参数的头部时,它看起来像head = ""custom-name""
。布尔参数看起来像surround = true
。
属性 | 参数 | 效果 |
---|---|---|
nohead |
none | 忽略头部,只从参数生成模式 |
head |
string | 使用自定义字符串作为头部,而不是小写类型名称 |
包围 |
bool | 当为true时,匹配被括号、方括号或花括号包围的模式(默认为true) |
nosurround |
none | 快捷方式为surround = false |
以下为变体级别的属性。它们看起来像
#[derive(Sexpy)]
enum Plant {
#[sexpy(head = "palm")] // <-----
Palm(String, u64),
...
}
属性 | 参数 | 效果 |
---|---|---|
head |
string | 使用自定义字符串作为头部,而不是小写类型名称 |
包围 |
bool | 当为true时,匹配被括号、方括号或花括号包围的模式(默认为false) |
!
依赖关系
~2.5MB
~55K SLoC