首页 syn 的高级封装库 parsel
文章
取消

syn 的高级封装库 parsel

使用 syn 库解析语法树时,常常人工编写 Parse trait 的实现。

最近发现一个基于 synquote 两个库,具有良好设计和封装的高级库 parsel,它具有以下亮点:

  • 通过自定义类型和 #[derive(Parse, ToTokens)] 的方式,无需重复编写 input.parse() 这种“显而易见”的啰嗦代码
  • 无缝使用 synquote
  • 通过类型描述 repetition 和连续标记,见下表
类型含义
Many连续的、无分隔符(或者说空白分隔的)一列标记
Any任意多的标记
Either两种标记中的一种
Maybe相当于 syn 对 Option 的处理(parsel 不处理 Option
Separated不含末尾符号的 Punctuated

例子:使用 parsel 重写我的 async_closure! 声明宏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#![feature(trivial_bounds)]
use parsel::{
    ast::{Brace, Ident, Maybe, Punctuated},
    parse_quote,
    syn::{
        token::{Async, Colon, Comma, Eq, Semi},
        Expr, ExprClosure, Type,
    },
    Parse, ToTokens,
};

fn main() {
    let _: AsyncClosure = parse_quote!(async || -> usize { f().await });
    let _: AsyncClosure = parse_quote!({}; async || -> usize { f().await });
    let _: AsyncClosure = parse_quote!({
        v: &'a [u8] = &v,
    }; async || -> usize { f(v).await });
}

#[derive(PartialEq, Eq, Debug, Parse, ToTokens)]
struct AsyncClosure {
    captures: Maybe<Captures>,
    _async: Async,
    closure: ExprClosure,
}
#[derive(PartialEq, Eq, Debug, Parse, ToTokens)]
struct Capture {
    val: Ident,
    _colon: Colon,
    ty: Type,
    _eq: Eq,
    expr: Expr,
    _comma: Comma,
}
#[derive(PartialEq, Eq, Debug, Parse, ToTokens)]
struct Captures {
    captures: Brace<Punctuated<Capture, Comma>>,
    semi: Semi,
}

这比声明宏好在:

  • 无捕获时,不再需要写 {}; (声明宏也能做到,但肯定没有结构化的类型清晰)
  • 利用过程宏,可以做更多复杂的事情
本文由作者按照 CC BY 4.0 进行授权

Rust 自定义测试:组合型参数

LazyLock 未稳定的难点