Skip to main content

Crate vacro_parser

Crate vacro_parser 

Source
Expand description

§Vacro Parser

Vacro 的声明式解析内核

§简介

Vacro Parser 是 Vacro 框架的核心声明式解析引擎。它提供了一种类似 macro_rules! 的 DSL,用于简化 Rust 过程宏中基于 syn 的解析逻辑。

它允许你声明式地定义 AST 结构和解析逻辑,消除了繁琐的 input.parse()? 调用。

§核心功能

§1. define!:定义解析结构体

使用 define! 定义一个结构体,它会自动实现 syn::parse::Parse

// 定义一个名为 MyFn 的结构体,它会自动实现 Parse trait
define!(MyFn:
    fn
    #(?: <#(generic*[,]: GenericParam)>)
    #(name: Ident)
    ( #(args*[,]: FnArg) )
    #(?: -> #(ret: Type))
);

fn parse_my_fn(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
    // 使用方式
    let my_fn: MyFn = parse_quote!(input);
    println!("Function name: {}", my_fn.name);
    proc_macro2::TokenStream::new()
}

§2. bind!:即时流解析

在现有的命令式逻辑中,使用 bind! 快速消费一段 TokenStream

// 即时解析函数签名模式
bind!(
    let captured = (input ->
        fn #(name: Ident) #(?: -> #(ret: Type))
    )?;
);

// 直接访问捕获的字段
println!("Name: {}", captured.name);
if let Some(ret_type) = captured.ret {
    // ...
}

§语法参考

语法描述解析结果类型示例
literal匹配并消费确切的 Token!fn, ->, struct
#(x: T)具名捕获: 捕获类型 T 到字段 xT#(name: Ident)
#(x?: T)具名可选: 尝试解析,失败则跳过Option<T>#(ret?: Type)
#(x*[sep]: T)具名迭代: 按分隔符解析Punctuated<T, sep>#(args*[,]: FnArg)
#(T)匿名捕获: 验证 T 存在但不捕获!#(Ident)
#(?: T)匿名可选: 仅作验证!#(?: Ident)
#(*[sep]: T)匿名迭代: 仅作验证!#(*[,]: Ident)

§多态捕获 (Enum Parsing)

Vacro 支持解析“多态”结构,即输入流中的某个位置可能是多种类型之一。

define!(MyPoly:
    #(data: MyEnum {
        Ident,                            // 1. 简写:匹配 Ident,生成 MyEnum::Ident(Ident)
        syn::Type,                        // 2. 简写:匹配 Type,生成 MyEnum::Type(syn::Type)
        Integer: syn::LitInt,             // 3. 别名:匹配 LitInt,生成 MyEnum::Integer(LitInt)
        Function: fn #(name: Ident),      // 4. 模式:生成 MyEnum::Function { name: Ident }
        Tuple: (#(@: Ident), #(@: Expr)), // 5. 模式:生成 MyEnum::Tuple(Ident, Expr)
    })
);

§更友好的提示 (v0.1.6)

你可以使用vacro-reporthelp!宏为内容提供更友好的提示,若你使用了vacro,只需要开启reportfeature即可。

vacro_parser = { version = "0.1.8" }
vacro_report = { version = "0.1.3", features = ["parser"] }

# vacro = { version = "0.2.3", features = ["parser", "report"] }
use vacro_parser::define;
use vacro_report::help;

help!(Bool:
    LitBool {
        error: "此处需要一个bool字面量,接收到的是:{input}",
        help: "尝试`true`或`false`",
        example: (true | false) // example 字段是要展示的示例字段,在生成错误信息与使用示例时使用;它接受一段TokenStream,并且将直接展示你传入的内容
    }
);

define!(MyRoles: {
    #(roles*[,]: #(pair: #(name: syn::Ident): #(enable: Bool)))
});

§Vacro Parser

The Declarative Parsing Kernel for Vacro

§Introduction

Vacro Parser is the core declarative parsing engine of the Vacro framework. It provides a macro_rules!-like DSL to simplify the writing of syn-based parsers for Rust Procedural Macros.

It allows you to define AST structures and parsing logic declaratively, eliminating the boilerplate of imperative input.parse()? calls.

§Core Features

§1. define!: Define Parsing Structs

Use define! to define a struct that automatically implements syn::parse::Parse.

// Define a struct named MyFn, it automatically implements the Parse trait
define!(MyFn:
    fn
    #(?: <#(generic*[,]: GenericParam)>)
    #(name: Ident)
    ( #(args*[,]: FnArg) )
    #(?: -> #(ret: Type))
);

fn parse_my_fn(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
    // Usage
    let my_fn: MyFn = parse_quote!(input);
    println!("Function name: {}", my_fn.name);
    proc_macro2::TokenStream::new()
}

§2. bind!: On-the-fly Parsing

Use bind! to consume a portion of a TokenStream within existing imperative logic.

// Parse a function signature pattern on the fly
bind!(
    let captured = (input ->
        fn #(name: Ident) #(?: -> #(ret: Type))
    )?;
);

// Access captured fields directly
println!("Name: {}", captured.name);
if let Some(ret_type) = captured.ret {
    // ...
}

§Syntax Reference

SyntaxDescriptionResult TypeExample
literalMatches and consumes exact tokens!fn, ->, struct
#(x: T)Named Capture: Captures type T into field xT#(name: Ident)
#(x?: T)Named Optional: Attempts to parse; skips if failedOption<T>#(ret?: Type)
#(x*[sep]: T)Named Iter: Parses by separatorPunctuated<T, sep>#(args*[,]: FnArg)
#(T)Anonymous Match: Validates T exists but doesn’t capture!#(Ident)
#(?: T)Anonymous Optional: Validation only!#(?: Ident)
#(*[sep]: T)Anonymous Iter: Validation only!#(*[,]: Ident)

§Polymorphic Capture (Enum Parsing)

Vacro supports parsing “polymorphic” structures, where a position in the input stream can be one of multiple types.

define!(MyPoly:
    #(data: MyEnum {
        Ident,                            // 1. Shorthand: Match Ident, produces MyEnum::Ident(Ident)
        syn::Type,                        // 2. Shorthand: Match Type, produces MyEnum::Type(syn::Type)
        Integer: syn::LitInt,             // 3. Alias: Match LitInt, produces MyEnum::Integer(LitInt)
        Function: fn #(name: Ident),      // 4. Pattern: Produces MyEnum::Function { name: Ident }
        Tuple: (#(@: Ident), #(@: Expr)), // 5. Pattern: Produces MyEnum::Tuple(Ident, Expr)
    })
);

§More user-friendly prompts (v0.1.6)

You can use the help! macro of vacro-report to provide more helpful suggestions for the content. If you are using vacro, you only need to enable the report feature.

vacro_parser = { version = "0.1.8" }
vacro_report = { version = "0.1.3", features = ["parser"] }

# vacro = { version = "0.2.3", features = ["parser", "report"] }
use vacro_parser::define;
use vacro_report::help;

help!(Bool:
    LitBool {
        error: "A boolean literal is required here; the received value is: {input}",
        help: "Try `true` or `false`",
        example: (true | false) // The example field is the sample field to be displayed, used when generating error messages and usage examples; it accepts a TokenStream and will directly display the content you pass in.
    }
);

define!(MyRoles: {
    #(roles*[,]: #(pair: #(name: syn::Ident): #(enable: Bool)))
});

Macros§

bind
即时解析宏:在现有的解析逻辑中快速消费 TokenStream On-the-fly parsing macro: Quickly consume a TokenStream within existing parsing logic
define
结构体定义宏:定义一个新的 AST 节点并自动实现 syn::parse::Parse Struct definition macro: Define a new AST node and implement syn::parse::Parse automatically