vacro_parser/lib.rs
1#![warn(missing_docs)]
2
3//!<div class="doc-cn">
4//!
5#![doc = include_str!("docs/zh_cn.md")]
6//!
7//!</div>
8//!
9//! <div class="doc-en">
10//!
11#![doc = include_str!("docs/en.md")]
12//!
13//!</div>
14
15pub(crate) mod ast;
16pub(crate) mod codegen;
17mod impls;
18pub(crate) mod syntax;
19pub(crate) mod transform;
20
21use proc_macro::TokenStream;
22use vacro_doc_i18n::doc_i18n;
23
24use crate::impls::{bind_impl, define_impl};
25
26#[doc_i18n]
27/// <div class="doc-cn"> 即时解析宏:在现有的解析逻辑中快速消费 `TokenStream` </div>
28/// <div class="doc-en"> On-the-fly parsing macro: Quickly consume a `TokenStream` within existing parsing logic </div>
29///
30/// <div class="doc-cn">
31///
32/// `bind!` 宏模拟了一个 `let` 绑定语句。其中的核心部分 `(<input> -> <pattern>)` 会被展开为一个表达式,
33/// 其求值结果为 `syn::Result<Output>`。
34///
35/// 这意味着你可以像处理普通 `Result` 一样处理它,例如在后面直接接 `?` 操作符、`.unwrap()` 或者 `.map(...)`。
36///
37/// # 语法
38///
39/// ```text
40/// vacro::bind!(let <绑定模式> = (<输入流> -> <Vacro模式>) <后续操作>);
41/// ```
42///
43/// * **绑定模式**: 标准 Rust 模式,用于接收解析成功后的内容(如变量名 `res` 或元组 `(a, b)`)。
44/// * **输入流**: 实现了 `Into<TokenStream>` 的变量。
45/// * **Vacro模式**: 描述语法的模式。
46/// * **后续操作**: 针对 `Result` 的操作,如 `?;`、`.unwrap();` 等。
47///
48/// # 捕获规则
49///
50/// * **具名捕获** (`#(name: Type)`): 宏会生成一个包含这些字段的临时结构体 `Output`。
51/// * **行内捕获** (`#(@: Type)`): 宏会返回一个元组(或单个值),按照定义的顺序包含捕获的内容。
52///
53/// # 示例
54///
55/// ```rust
56/// # use syn::{Ident, Type, Token, Result};
57/// # use vacro::bind;
58/// # use proc_macro2::TokenStream;
59/// fn parser(input: TokenStream) -> Result<()> {
60/// // 场景 1: 配合 `?` 使用 (推荐)
61/// // 表达式 `(input -> ...)` 返回 Result,后面接 `?` 传播错误
62/// let input1 = input.clone();
63/// bind!(
64/// let func = (input1 -> fn #(name: Ident))?;
65/// );
66/// println!("Function: {}", func.name);
67///
68/// // 场景 2: 配合 `unwrap` 使用
69/// // 如果你确定这里一定能解析成功
70/// let input2 = input.clone();
71/// bind!(
72/// let (arrow, ty) = (input2 -> #(@: Token![->]) #(@: Type)).unwrap();
73/// );
74///
75/// // 场景 3: 手动处理 Result
76/// let input3 = input.clone();
77/// bind!(
78/// let result = (input3 -> #(kw: Token![mod]));
79/// );
80/// if let Ok(output) = result {
81/// // ...
82/// }
83///
84/// Ok(())
85/// }
86/// ```
87/// </div>
88/// <div class="doc-en">
89///
90/// The `bind!` macro mimics a `let` binding statement. The core expression `(<input> -> <pattern>)`
91/// expands to a block that evaluates to `syn::Result<Output>`.
92///
93/// This means you can treat it like any other `Result` expression, appending `?`, `.unwrap()`,
94/// or `.map(...)` directly after it.
95///
96/// # Syntax
97///
98/// ```text
99/// vacro::bind!(let <binding> = (<input> -> <pattern>) <operations>);
100/// ```
101///
102/// * **binding**: Standard Rust pattern to receive the parsed content (e.g., `res` or `(a, b)`).
103/// * **input**: A variable implementing `Into<TokenStream>`.
104/// * **pattern**: The Vacro pattern description.
105/// * **operations**: Operations on the `Result`, such as `?;`, `.unwrap();`, etc.
106///
107/// # Capture Rules
108///
109/// * **Named Capture** (`#(name: Type)`): Generates a temporary `Output` struct containing these fields.
110/// * **Inline Capture** (`#(@: Type)`): Returns a tuple (or single value) containing captured items in order.
111///
112/// # Example
113///
114/// ```rust
115/// # use syn::{Ident, Type, Token, Result};
116/// # use vacro::bind;
117/// # use quote::ToTokens;
118/// # use proc_macro2::TokenStream;
119/// fn parser(input: TokenStream) -> Result<()> {
120/// // Case 1: Using with `?` (Recommended)
121/// // The expression `(input -> ...)` returns Result, `?` propagates error
122/// let input1 = input.clone();
123/// bind!(
124/// let func = (input1 -> fn #(name: Ident))?;
125/// );
126/// println!("Function: {}", func.name);
127///
128/// // Case 2: Using with `unwrap`
129/// // If you are sure parsing will succeed
130/// let input2 = input.clone();
131/// bind!(
132/// let (arrow, ty) = (input2 -> #(@: Token![->]) #(@: Type)).unwrap();
133/// );
134///
135/// // Case 3: Manually handling Result
136/// let input3 = input.clone();
137/// bind!(
138/// let result = (input3 -> #(kw: Token![mod]));
139/// );
140/// if let Ok(output) = result {
141/// // ...
142/// }
143///
144/// Ok(())
145/// }
146/// ```
147/// </div>
148#[proc_macro]
149pub fn bind(input: TokenStream) -> TokenStream {
150 bind_impl(input)
151}
152#[doc_i18n]
153/// <div class="doc-cn"> 结构体定义宏:定义一个新的 AST 节点并自动实现 `syn::parse::Parse` </div>
154/// <div class="doc-en"> Struct definition macro: Define a new AST node and implement `syn::parse::Parse` automatically </div>
155///
156/// <div class="doc-cn">
157///
158///
159/// `define!` 宏用于创建可复用的语法结构。它会根据提供的模式生成一个结构体,
160/// 并生成相应的解析逻辑,使其可以直接通过 `syn::parse_macro_input!` 或 `input.parse()` 使用。
161///
162/// # 语法
163///
164/// ```text
165/// vacro::define!(StructName: <Pattern>);
166/// ```
167///
168/// 宏会自动生成:
169/// 1. `struct StructName { ... }`:包含所有**具名捕获**的字段。
170/// 2. `impl syn::parse::Parse for StructName { ... }`:包含解析逻辑。
171///
172/// # 注意事项
173///
174/// * `define!` 中通常使用**具名捕获** (`#(name: Type)`) 来生成结构体字段。
175///
176/// # 示例
177///
178/// ```rust
179/// # use syn::{Ident, Type, Token, parse::Parse, parse::ParseStream, Result};
180/// # use vacro::define;
181/// # use quote::quote;
182/// # use proc_macro2::TokenStream;
183/// // 定义一个简单的常量定义结构
184/// // const NAME: Type = Value;
185/// define!(MyConst:
186/// const
187/// #(name: Ident)
188/// :
189/// #(ty: Type)
190/// =
191/// #(value: syn::Expr)
192/// ;
193/// );
194///
195/// fn parser(input: ParseStream) -> Result<()> {
196/// // MyConst 自动实现了 Parse trait
197/// let MyConst { name, ty, value } = input.parse()?;
198/// println!("Const {} has type {}, value: {}", name, quote!(#ty), quote!(#value));
199/// Ok(())
200/// }
201/// ```
202/// </div>
203/// <div class="doc-en">
204///
205/// The `define!` macro is used to create reusable syntax structures. It generates a struct
206/// based on the provided pattern and implements the parsing logic, making it usable
207/// directly via `syn::parse_macro_input!` or `input.parse()`.
208///
209/// # Syntax
210///
211/// ```text
212/// vacro::define!(StructName: <Pattern>);
213/// ```
214///
215/// The macro automatically generates:
216/// 1. `struct StructName { ... }`: Containing all **named captured** fields.
217/// 2. `impl syn::parse::Parse for StructName { ... }`: Containing the parsing logic.
218///
219/// # Notes
220///
221/// * `define!` typically uses **Named Captures** (`#(name: Type)`) to generate struct fields.
222///
223/// # Example
224///
225/// ```rust
226/// # use syn::{Ident, Type, Token, parse::Parse, parse::ParseStream, Result};
227/// # use vacro::define;
228/// # use quote::quote;
229/// # use proc_macro2::TokenStream;
230/// // Define a simple constant definition structure
231/// // const NAME: Type = Value;
232/// define!(MyConst:
233/// const
234/// #(name: Ident)
235/// :
236/// #(ty: Type)
237/// =
238/// #(value: syn::Expr)
239/// ;
240/// );
241///
242/// fn parser(input: ParseStream) -> Result<()> {
243/// // MyConst automatically implements the Parse trait
244/// let MyConst { name, ty, value } = input.parse()?;
245/// println!("Const {} has type {}, value: {}", name, quote!(#ty), quote!(#value));
246/// Ok(())
247/// }
248///
249/// ```
250/// </div>
251#[proc_macro]
252pub fn define(input: TokenStream) -> TokenStream {
253 define_impl(input)
254}