https://github.com/optimalstrategy/ast2str
A derive macro for printing ASTs
https://github.com/optimalstrategy/ast2str
Last synced: 4 months ago
JSON representation
A derive macro for printing ASTs
- Host: GitHub
- URL: https://github.com/optimalstrategy/ast2str
- Owner: optimalstrategy
- License: mit
- Created: 2021-04-24T12:22:00.000Z (about 5 years ago)
- Default Branch: main
- Last Pushed: 2022-08-23T02:46:41.000Z (almost 4 years ago)
- Last Synced: 2025-04-08T12:17:33.027Z (over 1 year ago)
- Language: Rust
- Size: 61.5 KB
- Stars: 3
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# ast2str
[![crates.io][crate logo]][crate]
[![Documentation][doc logo]][doc]
[![Build Status][ci logo]][ci]
A proc macro for pretty-printing ASTs and other recursive data structures.
# Basic Usage
Refer to the snippet below for a basic usage example, and see the [integration test](./tests/ast.rs) and these two repos ([#1.1](https://github.com/ves-lang/ves/blob/master/ves-parser/src/ast/mod.rs) + [#1.2](https://github.com/ves-lang/ves/blob/master/ves-parser/tests/t32_fn_if_expr_regression.test), [#2.1](https://github.com/langjam/jam0001/blob/main/dank/src/ast.rs)) for larger samples.
```rust
// Import the macro
use ast2str::AstToStr;
type Span = std::ops::Range;
// Annotate some structs and enums as desired
#[derive(AstToStr)]
struct Label {
#[quoted]
name: &'static str,
#[default = "Unresolved"]
location: Option,
}
#[derive(AstToStr)]
enum Expr {
Binary {
left: Box,
#[quoted]
operator: &'static str,
right: Box
},
Literal(#[rename = "value"] i32, #[skip] Span),
List { items: Vec },
Label(#[forward] Label),
Optional {
#[skip_if = "Option::is_none"]
value: Option<&'static str>
}
}
let expr = Expr::Binary {
left: Box::new(Expr::Literal(5, Span::default())),
operator: "+",
right: Box::new(Expr::List { items: vec![
Expr::Label(Label { name: "x", location: Some(0) }),
Expr::Label(Label { name: "y", location: Some(1) }),
Expr::Label(Label { name: "z", location: None }),
Expr::Optional { value: None },
Expr::Optional { value: Some("a string") },
]})
};
assert_eq!(expr.ast_to_str(), r#"
Expr::Binary
├─left: Expr::Literal
│ ╰─value: 5
├─operator: `+`
╰─right: Expr::List
╰─items=↓
├─Label
│ ├─name: `x`
│ ╰─location: 0
├─Label
│ ├─name: `y`
│ ╰─location: 1
├─Label
│ ├─name: `z`
│ ╰─location: Unresolved
├─Expr::Optional
╰─Expr::Optional
╰─value: "a string"
"#.trim());
// The symbols used to draw the tree can be configured using the [`Symbols`] trait:
assert_eq!(expr.ast_to_str_impl(&ast2str::TestSymbols), r#"
Expr::Binary
left: Expr::Literal
value: 5
operator: `+`
right: Expr::List
items=
Label
name: `x`
location: 0
Label
name: `y`
location: 1
Label
name: `z`
location: Unresolved
Expr::Optional
Expr::Optional
value: "a string"
"#.trim());
```
# Available Attributes
| Attribute | |
|--------------|--------------------------------------------------------------------------|
| None | Format the value with [`AstToStr`] |
| `#[forward]` | Skip all other fields and return the [`AstToStr`] of the annotated field |
| `#[skip]` | Skip the annotated field |
| `#[display]` | Format the annotated field with [`Display`] instead of [`AstToStr`] |
| `#[debug]` | Format the annotated field with [`Debug`] instead of [`AstToStr`] |
| `#[quoted]` | Like `#[display]` but also wraps the value with backticks |
| `#[list]` | Format the annotated field by executing AstToStr on every element of `(&field).into_iter()` |
| `#[list(name_or_closure)` | Format the annotated field by applying the callback on every element of `(&field).into_iter()` |
| `#[callback(name_or_closure)]` | Apply the given function or closure to `&field` and return the result |
| `#[delegate = "getter"]` | Call `self.getter()` and format the result as a field |
| `#[default = "value"]` | Only applies to `Option` types. If the value is `Some(T)`, format &T with AstToStr. Otherwise, return the value of `default` |
| `#[skip_if = "my_condition_fn"]` | Skip the annotated field if the specified function returns `true` |
[crate]: https://crates.io/crates/ast2str
[crate logo]: https://img.shields.io/crates/v/ast2str.svg
[doc]: https://docs.rs/ast2str
[doc logo]: https://docs.rs/ast2str/badge.svg
[ci]: https://github.com/optimalstrategy/ast2str/actions
[ci logo]: https://github.com/optimalstrategy/ast2str/actions/workflows/rust.yml/badge.svg