syntree/
macros.rs

1/// Helper macro for building a tree in place.
2///
3/// # Examples
4///
5/// ```
6/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
7/// enum Syntax {
8///     Root,
9///     Number,
10///     Lit,
11///     Whitespace,
12/// }
13///
14/// let mut tree = syntree::Builder::new();
15///
16/// tree.open(Syntax::Root)?;
17///
18/// tree.open(Syntax::Number)?;
19/// tree.token(Syntax::Lit, 1)?;
20/// tree.close()?;
21///
22/// tree.token(Syntax::Whitespace, 3)?;
23///
24/// tree.open(Syntax::Number)?;
25/// tree.token(Syntax::Lit, 2)?;
26/// tree.token_empty(Syntax::Lit)?;
27/// tree.close()?;
28///
29/// tree.close()?;
30///
31/// let tree = tree.build()?;
32///
33/// let expected = syntree::tree! {
34///     Syntax::Root => {
35///         Syntax::Number => {
36///             (Syntax::Lit, 1)
37///         },
38///         (Syntax::Whitespace, 3),
39///         Syntax::Number => {
40///             (Syntax::Lit, 2),
41///             Syntax::Lit
42///         }
43///     }
44/// };
45///
46/// assert_eq!(expected, tree);
47/// # Ok::<_,  Box<dyn core::error::Error>>(())
48/// ```
49#[macro_export]
50macro_rules! tree {
51    (@o $b:ident,) => {};
52
53    (@o $b:ident, ($expr:expr, ($start:expr, $end:expr)) $(,)?) => {{
54        $b.token_with($expr, $crate::Span::new($start, $end))?;
55    }};
56
57    (@o $b:ident, ($expr:expr, $len:expr) $(,)?) => {{
58        $b.token($expr, $len)?;
59    }};
60
61    (@o $b:ident, ($expr:expr, ($start:expr, $end:expr)), $($rest:tt)*) => {{
62        $b.token_with($expr, $crate::Span::new($start, $end))?;
63        $crate::tree!(@o $b, $($rest)*);
64    }};
65
66    (@o $b:ident, ($expr:expr, $len:expr), $($rest:tt)*) => {{
67        $b.token($expr, $len)?;
68        $crate::tree!(@o $b, $($rest)*);
69    }};
70
71    (@o $b:ident, $expr:expr $(,)?) => {{
72        $b.token_empty($expr)?;
73    }};
74
75    (@o $b:ident, $expr:expr, $($rest:tt)*) => {{
76        $b.token_empty($expr)?;
77        $crate::tree!(@o $b, $($rest)*);
78    }};
79
80    (@o $b:ident, ($expr:expr, ($start:expr, $end:expr)) => { $($tt:tt)* } $(,)?) => {{
81        $b.open_with($expr, $crate::Span::new($start, $end))?;
82        $crate::tree!(@o $b, $($tt)*);
83        $b.close()?;
84    }};
85
86    (@o $b:ident, $expr:expr => { $($tt:tt)* } $(,)?) => {{
87        $b.open($expr)?;
88        $crate::tree!(@o $b, $($tt)*);
89        $b.close()?;
90    }};
91
92    (@o $b:ident, ($expr:expr, ($start:expr, $end:expr)) => { $($tt:tt)* }, $($rest:tt)*) => {{
93        $b.open_with($expr, $crate::Span::new($start, $end))?;
94        $crate::tree!(@o $b, $($tt)*);
95        $b.close()?;
96        $crate::tree!(@o $b, $($rest)*);
97    }};
98
99    (@o $b:ident, $expr:expr => { $($tt:tt)* }, $($rest:tt)*) => {{
100        $b.open($expr)?;
101        $crate::tree!(@o $b, $($tt)*);
102        $b.close()?;
103        $crate::tree!(@o $b, $($rest)*);
104    }};
105
106    ($($tt:tt)*) => {{
107        let mut b = $crate::Builder::new();
108        $crate::tree!(@o b, $($tt)*);
109        b.build()?
110    }};
111}
112
113/// Helper macro for building a tree in place with a custom span.
114///
115/// # Examples
116///
117/// ```
118/// use syntree::{Empty, EmptyVec, Tree, TreeIndex};
119///
120/// syntree::flavor! {
121///     struct FlavorEmpty {
122///         type Index = Empty;
123///         type Indexes = EmptyVec<TreeIndex<Self>>;
124///     }
125/// };
126///
127/// let tree: Tree<_, FlavorEmpty> = syntree::tree_with! {
128///     "root" => {
129///         "child" => {
130///             "token"
131///         },
132///         "child2"
133///     }
134/// };
135///
136/// let expected: Tree<_, FlavorEmpty> = syntree::tree_with! {
137///     "root" => {
138///         "child" => {
139///             ("token", Empty)
140///         },
141///         "child2"
142///     }
143/// };
144///
145/// assert_eq!(tree, expected);
146/// # Ok::<_,  Box<dyn core::error::Error>>(())
147/// ```
148#[macro_export]
149macro_rules! tree_with {
150    ($($tt:tt)*) => {{
151        let mut b = $crate::Builder::new_with();
152        $crate::tree!(@o b, $($tt)*);
153        b.build()?
154    }};
155}