A modular Rust syntax toolkit for tokenization, parsing, formatting, diagnostics, and quasi-quoting.
Rust
27
273 commits
updated Sep 26, 2026
Rust syntax tools for procedural macros: tokens, typed syntax trees, templates, formatting, and diagnostics.
[!WARNING] Moxy is under active development.
APIs, behavior, and documentation may change frequently and without notice. Moxy is not yet considered stable or production-ready.
cargo add moxy --features template,fmt
use moxy::ast::Item;
let name = "Widget";
let tokens = moxy::template! {
pub struct {{ name }};
};
let item: Item = moxy::parse!(tokens).unwrap();
assert_eq!(item.as_struct().unwrap().ident.text(), "Widget");
assert_eq!(moxy::fmt!(&item).unwrap(), "pub struct Widget;");
Default features are token and ast.
| Feature | Default | Enables |
|---|---|---|
token | yes | Token streams, spans, parsing, and token construction |
ast | yes | Typed Rust syntax trees; implies token |
template | no | template! and paste!; implies token |
fmt | no | AST formatting with fmt!; implies ast |
diagnostic | no | Span-aware error, warning, note, and help diagnostics |
build | no | Cargo build-script and rustc-version helpers |
derive | no | #[derive(ToTokens)] and its supporting pipeline |
serde | no | Serialization for supported token, AST, and formatting types |
proc-macro2 | no | Conversions between moxy and proc_macro2 tokens |
full | no | Every feature above |
Choose only the layers you need:
cargo add moxy --no-default-features --features token,ast
The token feature is the foundation, similar in role to proc-macro2.
use moxy::Token;
use moxy::token::ident;
let name = ident!(Generated, "_", Item);
let comma: Token![,] = Default::default();
assert_eq!(name.to_string(), "Generated_Item");
assert_eq!(comma.as_str(), ",");
The ast feature provides typed entry points such as Item, Expr, and
Type, following the same parse-at-the-level-you-need style as syn.
use moxy::ast::{Expr, Item, Type};
let item: Item = moxy::parse!("pub struct User { id: u64 }").unwrap();
let ty: Type = moxy::parse!("Option<Result<T, E>>").unwrap();
let expr: Expr = moxy::parse!("items.next()?").unwrap();
assert!(item.is_struct());
assert!(ty.is_path());
assert!(expr.is_unary());
The template feature builds token streams with interpolation and control
flow in the style of quote!.
let fields = ["id", "name"];
let tokens = moxy::template! {
struct User {
@for (field in fields) {
{{ field }}: String,
}
}
};
assert!(tokens.to_string().contains("struct User"));
paste! creates identifiers at expansion time:
moxy::paste! {
fn {{ read_ value }}() -> u32 { 7 }
}
assert_eq!(read_value(), 7);
The fmt feature formats parsed syntax trees with configurable width,
indentation, and newlines.
use moxy::ast::Item;
use moxy::fmt::{FmtConfig, Indent};
let item: Item = moxy::parse!("struct User { id: u64, name: String }").unwrap();
let config = FmtConfig::default().with_indent(Indent::space(2));
let output = moxy::fmt!(&item, config).unwrap();
assert_eq!(output, "struct User {\n id: u64,\n name: String,\n}");
The diagnostic feature builds span-aware diagnostics with a stable
compile_error! fallback.
let tokens = moxy::error!(
"missing template",
[moxy::help!("add #[template { ... }]")],
)
.emit();
assert!(tokens.to_string().contains("compile_error"));
Enable build as a build dependency for typed Cargo directives and rustc
version checks.
cargo add moxy --build --no-default-features --features build
// build.rs
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut config = moxy::build::rustc::Config::read()?;
config
.min_version("1.85.0")
.check_cfg("cfg(nightly)")
.rerun_if_changed("build.rs");
if config.version().channel.is_nightly() {
config.cfg("nightly");
}
config.emit();
Ok(())
}
Enable derive to implement ToTokens from an inline template.
cargo add moxy --features derive
use moxy::token::ToTokenStream;
#[derive(moxy::ToTokens)]
#[moxy(template { const VALUE: &str = {{ self.value }}; })]
struct Generated {
value: String,
}
let tokens = Generated { value: "seven".into() }.to_token_stream();
assert!(tokens.to_string().contains("VALUE"));
Add #[moxy(debug)] beside #[moxy(template { ... })] to print the parsed
declaration and generated implementation as compiler notes.
serde adds serialization for supported token, AST, and formatter types.
proc-macro2 adds token conversions for interoperability with the wider
procedural-macro ecosystem.
Rust
99.9%
A modular Rust syntax toolkit for tokenization, parsing, formatting, diagnostics, and quasi-quoting.
Rust
27
273 commits
updated Sep 26, 2026
Rust syntax tools for procedural macros: tokens, typed syntax trees, templates, formatting, and diagnostics.
[!WARNING] Moxy is under active development.
APIs, behavior, and documentation may change frequently and without notice. Moxy is not yet considered stable or production-ready.
cargo add moxy --features template,fmt
use moxy::ast::Item;
let name = "Widget";
let tokens = moxy::template! {
pub struct {{ name }};
};
let item: Item = moxy::parse!(tokens).unwrap();
assert_eq!(item.as_struct().unwrap().ident.text(), "Widget");
assert_eq!(moxy::fmt!(&item).unwrap(), "pub struct Widget;");
Default features are token and ast.
| Feature | Default | Enables |
|---|---|---|
token | yes | Token streams, spans, parsing, and token construction |
ast | yes | Typed Rust syntax trees; implies token |
template | no | template! and paste!; implies token |
fmt | no | AST formatting with fmt!; implies ast |
diagnostic | no | Span-aware error, warning, note, and help diagnostics |
build | no | Cargo build-script and rustc-version helpers |
derive | no | #[derive(ToTokens)] and its supporting pipeline |
serde | no | Serialization for supported token, AST, and formatting types |
proc-macro2 | no | Conversions between moxy and proc_macro2 tokens |
full | no | Every feature above |
Choose only the layers you need:
cargo add moxy --no-default-features --features token,ast
The token feature is the foundation, similar in role to proc-macro2.
use moxy::Token;
use moxy::token::ident;
let name = ident!(Generated, "_", Item);
let comma: Token![,] = Default::default();
assert_eq!(name.to_string(), "Generated_Item");
assert_eq!(comma.as_str(), ",");
The ast feature provides typed entry points such as Item, Expr, and
Type, following the same parse-at-the-level-you-need style as syn.
use moxy::ast::{Expr, Item, Type};
let item: Item = moxy::parse!("pub struct User { id: u64 }").unwrap();
let ty: Type = moxy::parse!("Option<Result<T, E>>").unwrap();
let expr: Expr = moxy::parse!("items.next()?").unwrap();
assert!(item.is_struct());
assert!(ty.is_path());
assert!(expr.is_unary());
The template feature builds token streams with interpolation and control
flow in the style of quote!.
let fields = ["id", "name"];
let tokens = moxy::template! {
struct User {
@for (field in fields) {
{{ field }}: String,
}
}
};
assert!(tokens.to_string().contains("struct User"));
paste! creates identifiers at expansion time:
moxy::paste! {
fn {{ read_ value }}() -> u32 { 7 }
}
assert_eq!(read_value(), 7);
The fmt feature formats parsed syntax trees with configurable width,
indentation, and newlines.
use moxy::ast::Item;
use moxy::fmt::{FmtConfig, Indent};
let item: Item = moxy::parse!("struct User { id: u64, name: String }").unwrap();
let config = FmtConfig::default().with_indent(Indent::space(2));
let output = moxy::fmt!(&item, config).unwrap();
assert_eq!(output, "struct User {\n id: u64,\n name: String,\n}");
The diagnostic feature builds span-aware diagnostics with a stable
compile_error! fallback.
let tokens = moxy::error!(
"missing template",
[moxy::help!("add #[template { ... }]")],
)
.emit();
assert!(tokens.to_string().contains("compile_error"));
Enable build as a build dependency for typed Cargo directives and rustc
version checks.
cargo add moxy --build --no-default-features --features build
// build.rs
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut config = moxy::build::rustc::Config::read()?;
config
.min_version("1.85.0")
.check_cfg("cfg(nightly)")
.rerun_if_changed("build.rs");
if config.version().channel.is_nightly() {
config.cfg("nightly");
}
config.emit();
Ok(())
}
Enable derive to implement ToTokens from an inline template.
cargo add moxy --features derive
use moxy::token::ToTokenStream;
#[derive(moxy::ToTokens)]
#[moxy(template { const VALUE: &str = {{ self.value }}; })]
struct Generated {
value: String,
}
let tokens = Generated { value: "seven".into() }.to_token_stream();
assert!(tokens.to_string().contains("VALUE"));
Add #[moxy(debug)] beside #[moxy(template { ... })] to print the parsed
declaration and generated implementation as compiler notes.
serde adds serialization for supported token, AST, and formatter types.
proc-macro2 adds token conversions for interoperability with the wider
procedural-macro ecosystem.
Rust
99.9%