3个版本

使用旧的Rust 2015

0.11.3 2017年3月1日
0.11.2 2017年2月27日
0.11.1 2017年2月27日
0.11.0 2017年2月19日

1587进程宏中排名

Download history 28800/week @ 2024-03-03 27594/week @ 2024-03-10 29457/week @ 2024-03-17 29934/week @ 2024-03-24 28007/week @ 2024-03-31 25525/week @ 2024-04-07 27599/week @ 2024-04-14 24118/week @ 2024-04-21 22212/week @ 2024-04-28 22707/week @ 2024-05-05 22727/week @ 2024-05-12 22195/week @ 2024-05-19 21469/week @ 2024-05-26 21948/week @ 2024-06-02 23279/week @ 2024-06-09 21708/week @ 2024-06-16

89,328每月下载量
162个crate中使用了(直接使用5个)

MIT/Apache

62KB
736

Rust源代码的Nom解析器

Build Status Latest Version Rust Documentation

无需Syntex依赖项解析Rust源代码,适用于与Macros 1.1一起使用。

专为快速编译时间设计。

  • syn的编译时间(从头开始包括所有依赖项):6秒
  • syntex/quasi/aster堆栈的编译时间:60+秒

如果你在使用Macros 1.1时遇到问题,即使问题与syn无关,我也很乐意提供帮助。请在此存储库中提交工单。

与Macros 1.1一起使用

[dependencies]
syn = "0.11"
quote = "0.3"

[lib]
proc-macro = true
extern crate proc_macro;
use proc_macro::TokenStream;

extern crate syn;

#[macro_use]
extern crate quote;

#[proc_macro_derive(MyMacro)]
pub fn my_macro(input: TokenStream) -> TokenStream {
    let source = input.to_string();

    // Parse the string representation into a syntax tree
    let ast = syn::parse_derive_input(&source).unwrap();

    // Build the output, possibly using quasi-quotation
    let expanded = quote! {
        // ...
    };

    // Parse back to a token stream and return it
    expanded.parse().unwrap()
}

完整示例

假设我们有一个以下简单的特质,它返回结构体中的字段数量

trait NumFields {
    fn num_fields() -> usize;
}

基于synquote的完整的Macros 1.1实现如下所示

extern crate proc_macro;
use proc_macro::TokenStream;

extern crate syn;

#[macro_use]
extern crate quote;

#[proc_macro_derive(NumFields)]
pub fn num_fields(input: TokenStream) -> TokenStream {
    let source = input.to_string();

    // Parse the string representation into a syntax tree
    let ast = syn::parse_derive_input(&source).unwrap();

    // Build the output
    let expanded = expand_num_fields(&ast);

    // Return the generated impl as a TokenStream
    expanded.parse().unwrap()
}

fn expand_num_fields(ast: &syn::DeriveInput) -> quote::Tokens {
    let n = match ast.body {
        syn::Body::Struct(ref data) => data.fields().len(),
        syn::Body::Enum(_) => panic!("#[derive(NumFields)] can only be used with structs"),
    };

    // Used in the quasi-quotation below as `#name`
    let name = &ast.ident;

    // Helper is provided for handling complex generic types correctly and effortlessly
    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

    quote! {
        // The generated impl
        impl #impl_generics ::mycrate::NumFields for #name #ty_generics #where_clause {
            fn num_fields() -> usize {
                #n
            }
        }
    }
}

测试

Macros 1.1有一个限制,即你的进程宏crate必须只导出proc_macro_derive函数,而且proc_macro_derive进程宏不能在定义它们的crate中使用。这些限制可能在将来被取消,但到目前为止,它们使得编写测试比其他类型的代码要复杂一些。

特别是,您无法按照代码行的方式编写测试函数,例如:#[test] fn it_works() { ... }。相反,您可以将测试放在一个tests 目录中,或者完全在另一个crate中。

此外,如果您的过程宏实现了特定的trait,那么该trait必须在过程宏之外单独的crate中定义。

作为一个具体的例子,假设您的过程宏crate名为my_derive,并且它实现了名为my_crate::MyTrait的trait。您的过程宏单元测试可以放在my_derive/tests/test.rs中,或者放入一个单独的crate my_tests/tests/test.rs中。无论哪种方式,测试代码可能如下所示

#[macro_use]
extern crate my_derive;

extern crate my_crate;
use my_crate::MyTrait;

#[test]
fn it_works() {
    #[derive(MyTrait)]
    struct S { /* ... */ }

    /* test the thing */
}

调试

在开发过程宏时,查看生成的代码可能会有所帮助。使用cargo rustc -- -Zunstable-options --pretty=expandedcargo expand子命令。

要显示使用您的过程宏的crate的展开代码,请在该crate中运行cargo expand。要显示您的测试用例之一的展开代码,请运行cargo expand --test the_test_case,其中最后一个参数是不带.rs扩展名的测试文件名。

Brandon W Maister的这篇文档更详细地讨论了调试:[调试Rust的新自定义Derive系统](https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/)

可选功能

Syn将很多功能放在可选功能后面,以优化最常见的用例的编译时间。以下是可用的功能及其对编译时间的影响。依赖项包含在编译时间中。

功能 编译时间 功能
(无) 3秒 Rust结构体、枚举和类型的AST表示的数据结构。
解析 6秒 解析包含结构体和枚举的Rust源代码到AST。
打印 4秒 将结构体和枚举的AST打印为Rust源代码。
解析,打印 6秒 这是默认选项。解析和打印Rust结构体和枚举。通常您想要为实现Macros 1.1自定义Derive实现此选项。
完整 4秒 表示所有可能的Rust代码的完整AST的数据结构。
完整,解析 9秒 将任何有效的Rust源代码解析到AST。
完整,打印 6秒 将AST转换为Rust源代码。
完整,解析,打印 11秒 解析和打印任何Rust语法。

许可证

根据以下许可证之一授权

由您选择。

贡献

除非您明确声明,否则根据Apache-2.0许可证定义,您提交的任何有意包含在本软件包中的贡献将以上述方式双许可,不附加任何额外条款或条件。

依赖项

~60KB