{"id":17119135,"url":"https://github.com/mtshiba/ruast","last_synced_at":"2025-09-11T13:41:51.642Z","repository":{"id":178869493,"uuid":"660857528","full_name":"mtshiba/ruast","owner":"mtshiba","description":"Printable \u0026 modifiable Rust AST library","archived":false,"fork":false,"pushed_at":"2025-04-04T17:25:26.000Z","size":128,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-04T17:27:05.963Z","etag":null,"topics":["ast","compiler","library","rust"],"latest_commit_sha":null,"homepage":"https://docs.rs/ruast/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mtshiba.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"mtshiba","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2023-07-01T03:32:42.000Z","updated_at":"2025-04-04T17:25:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"07dd263a-d8a3-49ca-87ab-c2225466f1df","html_url":"https://github.com/mtshiba/ruast","commit_stats":null,"previous_names":["mtshiba/ruast"],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtshiba%2Fruast","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtshiba%2Fruast/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtshiba%2Fruast/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtshiba%2Fruast/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mtshiba","download_url":"https://codeload.github.com/mtshiba/ruast/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248657825,"owners_count":21140842,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ast","compiler","library","rust"],"created_at":"2024-10-14T17:56:21.842Z","updated_at":"2025-09-11T13:41:51.629Z","avatar_url":"https://github.com/mtshiba.png","language":"Rust","funding_links":["https://github.com/sponsors/mtshiba"],"categories":[],"sub_categories":[],"readme":"# `ruast`\n\nThis crate provides a printable \u0026 modifiable Rust AST.\n\n## Features\n\n* [x] Indentation-aware pretty-printing\n* [x] Operator precedence-aware pretty-printing\n\n## Basic usage\n\n### Hello world\n\n```rust\nuse ruast::*;\n\nlet mut krate = Crate::new();\nlet def = Fn::main(\n    None,\n    Block::from(\n        Path::single(\"println\")\n            .mac_call(vec![Token::lit(\"Hello, world!\")])\n            .semi(),\n    ),\n);\nkrate.add_item(def);\nprintln!(\"{krate}\");\n// krate.dump(\"test.rs\")?;\n// krate.compile(\"test.rs\", CompileOptions::default())?;\nkrate.try_remove_item_by_id(\"main\");\nassert!(krate.is_empty());\n```\n\nThis is equivalent to:\n\n```rust\nuse ruast::*;\n\nlet mut krate = Crate::new();\nkrate.add_item(Fn {\n    is_unsafe: false,\n    is_const: false,\n    is_async: false,\n    abi: None,\n    ident: \"main\".to_string(),\n    generics: vec![],\n    fn_decl: FnDecl::new(vec![], None),\n    body: Some(Block::from(Stmt::Semi(Semi::new(Expr::new(MacCall {\n        path: Path::single(\"println\"),\n        args: DelimArgs::from(vec![Token::lit(\"Hello, world!\")]),\n    }))))),\n});\nprintln!(\"{krate}\");\n// krate.dump(\"test.rs\")?;\n// krate.compile(\"test.rs\", CompileOptions::default())?;\nkrate.try_remove_item_by_id(\"main\");\nassert!(krate.is_empty());\n```\n\n```rust\n\u003e cargo run --example hello\n\nfn main() {\n    println!(\"Hello, world!\");\n}\n```\n\n### Operations\n\n```rust\nuse ruast::*;\n\nlet lhs = Lit::int(\"1\");\nlet rhs = Lit::int(\"2\");\nlet add = lhs.clone().add(rhs.clone());\nassert_snapshot!(add, @\"1 + 2\");\n\nlet add_add = add.clone().add(Lit::int(\"3\"));\nassert_snapshot!(add_add, @\"1 + 2 + 3\");\n\nlet mul_add = add.mul(Lit::int(\"3\"));\nassert_snapshot!(mul_add, @\"(1 + 2) * 3\");\n\nlet mul = lhs.clone().mul(rhs.clone());\nlet add_mul = mul.add(Lit::int(\"3\"));\nassert_snapshot!(add_mul, @\"1 * 2 + 3\");\n\nlet add = lhs.neg().add(rhs.neg());\nassert_snapshot!(add, @\"-1 + -2\");\n```\n\n### Building struct, enum, trait and impl\n\nThe source code is available in the [`examples`](https://github.com/mtshiba/ruast/tree/main/examples) directory.\n\n```rust\nuse ruast::*;\n\nlet mut krate = Crate::new();\nlet def = StructDef::empty(\"Foo\")\n    .with_field(FieldDef::inherited(\"foo\", Type::u32()))\n    .with_field(FieldDef::inherited(\"bar\", Type::u32()));\nkrate.add_item(def);\nlet imp = Impl::empty(\"Foo\")\n    .with_item(Fn::empty_method(\"test\", Pat::ref_self()));\nkrate.add_item(imp);\nprintln!(\"{krate}\");\n```\n\n```rust\nuse ruast::*;\n\nlet mut krate = Crate::new();\nlet def = EnumDef::empty(\"Foo\")\n    .with_variant(Variant::empty(\"Bar\"))\n    .with_variant(Variant::tuple(\"Baz\", vec![FieldDef::anonymous(Type::u32())]));\nkrate.add_item(def);\nlet imp = Impl::empty(\"Foo\")\n    .with_item(Fn::empty_method(\"test\", Pat::ref_self()));\nkrate.add_item(imp);\nprintln!(\"{krate}\");\n```\n\n```rust\nuse ruast::*;\n\nlet mut krate = Crate::new();\n\nlet partial_eq = Type::simple_path(\"PartialEq\");\nlet trait_def = TraitDef::new(\"Eq\", vec![], vec![partial_eq], vec![]);\nkrate.add_item(trait_def);\nlet arg_t = GenericArg::Type(Type::simple_path(\"T\"));\nlet eq_bound = GenericBound::Trait(PolyTraitRef::simple(\"Eq\"));\nlet eq = Type::simple_path(\"Eq\");\nlet param_t = GenericParam::new(\"T\", vec![eq_bound]);\nlet self_ty = Type::poly_path(\"Vec\", vec![arg_t]);\nlet imp = Impl::trait_impl(vec![param_t], self_ty, eq, None, vec![]);\nkrate.add_item(imp);\nprintln!(\"{krate}\");\n```\n\n### Convert to `proc_macro2::TokenStream`\n\nBy enabling a feature `tokenize`, you can convert `ruast` ASTs to `proc_macro2::TokenStream`.\n\nYou can build ASTs systematically without using `syn` or `quote` macros.\n\n```rust\nuse ruast::*;\n\nlet mut krate = Crate::new();\nlet def = Fn::main(\n    None,\n    Block::from(Path::single(\"println\").mac_call(vec![Token::lit(\"Hello, world!\")])),\n);\nkrate.add_item(def);\nlet tokens = krate.to_token_stream();\nprintln!(\"{krate}\");\nprintln!(\"{tokens}\");\n```\n\nYou can also find examples on how to create a proc macro using this crate in [`examples/proc_macro_example`](https://github.com/mtshiba/ruast/tree/main/examples/proc_macro_example).\n\n## Feature flags\n\n* `tokenize`: Enables conversion to `proc_macro2::TokenStream`.\n* `checked-ident`: Enables `check_ident`, `Identifier`, etc.\n\n## Why this is needed?\n\n[The Rust project](https://github.com/rust-lang/rust) has a submodule called [`rustc_ast`](https://github.com/rust-lang/rust/tree/master/compiler/rustc_ast) that defines an AST, but it is not published on crates.io and requires a huge build of `rust` itself. Also, `rustc_ast` is not designed for third parties to build ASTs by hand.\n\nThere is a [`codegen`](https://github.com/carllerche/codegen) crate for Rust code generation, but this crate has not been maintained for some time and only supports basic syntax elements.\n\nThere is also a [`syn`](https://github.com/dtolnay/syn) crate that can parse `proc_macro::TokenStream` into an AST, but its AST elements don't implement `Display` trait and are not designed for direct construction \u0026 modification.\n\n## Goals\n\nThe goal of this project is to provide a simple and portable Rust AST building/Rust code generation library.\n\n## Non-goals\n\nThis library is not directly related to the Rust compiler AST, and ASTs built with this library cannot be directly given as input to the compiler.\n\n## License\n\nThis project is licensed under either of [Apache license version 2.0](./LICENSE-APACHE) or [MIT license](./LICENSE-MIT) at your option.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtshiba%2Fruast","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmtshiba%2Fruast","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtshiba%2Fruast/lists"}