5 个版本

0.0.5 2023年11月4日
0.0.4 2023年10月22日
0.0.3 2023年8月8日
0.0.2 2023年7月5日
0.0.1 2023年7月5日

#1080解析器实现

Download history 2/week @ 2024-05-24 20/week @ 2024-07-05 69/week @ 2024-07-26

89 每月下载量

MIT/Apache

165KB
5.5K SLoC

ruast

此包提供可打印并可修改的 Rust AST。

基本用法

Hello world

use ruast::*;

let mut krate = Crate::new();
let def = Fn::main(
    None,
    Block::from(Path::single("println").mac_call(vec![Token::lit("Hello, world!")])),
);
krate.add_item(def);
println!("{krate}");
krate.dump("test.rs")?;
krate.remove_item_by_id("main");
assert!(krate.is_empty());

这相当于

use ruast::*;

let mut krate = Crate::new();
krate.add_item(Fn {
    ident: "main".to_string(),
    generics: vec![],
    fn_decl: FnDecl::new(vec![], None),
    body: Some(Block::from(
        Stmt::Expr(Expr::new(MacCall {
            path: Path::single("println!"),
            args: DelimArgs::from(vec![Token::lit("Hello, world!")]),
        })),
    )),
});
println!("{krate}");
krate.dump("test.rs")?;
krate.remove_item_by_id("main");
assert!(krate.is_empty());

构建结构体、枚举和 impl

use ruast::*;

let mut krate = Crate::new();
let def = StructDef::empty("Foo")
    .with_field(FieldDef::inherited("foo", Type::from("u32")))
    .with_field(FieldDef::inherited("bar", Type::from("u32")));
krate.add_item(def);
let imp = Impl::empty("Foo")
    .with_item(Fn::empty_method("test", Pat::ref_self()));
krate.add_item(imp);
println!("{krate}");
use ruast::*;

let mut krate = Crate::new();
let def = EnumDef::empty("Foo")
    .with_variant(Variant::empty("Bar"))
    .with_variant(Variant::tuple("Baz", vec![FieldDef::anonymous("u32")]));
krate.add_item(def);
let imp = Impl::empty("Foo")
    .with_item(Fn::empty_method("test", Pat::ref_self()));
krate.add_item(imp);
println!("{krate}");

转换为 proc_macro2::TokenStream

通过启用功能 tokenize,您可以转换 ruast AST 到 proc_macro2::TokenStream

您可以在不使用 synquote 宏的情况下系统地构建 AST。

use ruast::*;

let mut krate = Crate::new();
let def = Fn::main(
    None,
    Block::from(Path::single("println").mac_call(vec![Token::lit("Hello, world!")])),
);
krate.add_item(def);
let tokens = krate.to_token_stream();
println!("{krate}");
println!("{tokens}");

为什么需要这个?

Rust 项目 有一个名为 rustc_ast 的子模块,该子模块定义了一个 AST,但它没有在 crates.io 上发布,并且需要构建一个巨大的 rust 自身。此外,rustc_ast 不是为第三方手动构建 AST 而设计的。

有一个 codegen 包用于 Rust 代码生成,但这个包已经有一段时间没有维护,并且仅支持基本语法元素。

还有一个 syn 包可以将 proc_macro::TokenStream 解析为 AST,但它的 AST 元素没有实现 Display 特性,并且不是为直接构建和修改而设计的。

目标

本项目目标是提供一个简单且易于携带的 Rust AST 构建/Rust 代码生成库。

非目标

此库与 Rust 编译器 AST 没有直接关系,并且使用此库构建的 AST 不能直接作为编译器的输入。

许可证

本项目许可受 Apache 许可证 2.0 版MIT 许可证 之一约束,由您选择。

依赖关系