macro_rules! assert_parse_tree {
($src:expr, $($tree:tt)+) => { ... };
(@seq $parser:ident, Warn ( $code:expr ) $($rest:tt)*) => { ... };
(@seq $parser:ident, Error ( $code:expr ) $($rest:tt)*) => { ... };
(@seq $parser:ident, $kind:ident [ $($children:tt)+ ] $($rest:tt)*) => { ... };
(@seq $parser:ident, $kind:ident ( $text:expr ) $($rest:tt)*) => { ... };
(@seq $parser:ident, $kind:ident $($rest:tt)*) => { ... };
(@seq $parser:ident, ...) => { ... };
(@seq $parser:ident,) => { ... };
}
Expand description
Macro to assert the structure and content of the parsed syntax tree from source code.
§Purpose
assert_parse_tree!
allows you to declaratively specify the expected abstract syntax tree (AST)
shape and tokens produced by your parser for a given source code snippet. It recursively
matches nodes by their kinds (SyntaxKind
) and token text, verifying both the hierarchical
structure and token lexemes precisely.
This macro is primarily useful in parser/unit tests where you want to:
- Assert nodes and their nested children are present in expected order.
- Assert leaf tokens have expected text content.
- Assert presence of parser errors and warnings at specific nodes.
§Syntax Overview
ⓘ
assert_parse_tree!(
"source code string",
RootNodeKind [ // Node with children
ChildNodeKind1 ( "token_text" ) // Leaf node with exact text
ChildNodeKind2 [ // Nested node with children
...
]
Warn(WARNING_CODE) // Warning node with an error code enum or const
Error(ERROR_CODE) // Error node with an error code enum or const
... // Ellipsis to skip remaining children in this subtree
]
);
- Root node: The first argument is the source code string to parse.
- Nodes with children: Use
KindName [ ... ]
whereKindName
is a variant of yourSyntaxKind
enum. - Leaf tokens: Use
KindName("token_text")
where the string is the exact matched source token text. - Warnings and errors: Use
Warn(WARNING_CODE)
andError(ERROR_CODE)
where the code is a known error/warning enum or constant. - Ellipsis (
...
): Use to ignore remaining children in a node subtree (useful to reduce test verbosity).
§Notes
KindName
must be a variant of yourSyntaxKind
enum (without theSyntaxKind::
prefix).- Leaf nodes must specify the exact token text as a string literal.
Warn
andError
are reserved special nodes recognized by the macro for diagnostics.- The macro performs strict ordering checks: children must appear in exact order as specified.
§Example: Simple function call
compose_syntax::test_utils::assert_parse_tree!(
"f(a, b: c)",
FuncCall [
Ident("f")
Args [
LeftParen("(")
Ident("a")
Comma(",")
Named [ Ident("b") Colon(":") Ident("c") ]
RightParen(")")
]
]
);
§Example: Error recovery with warnings and errors
compose_syntax::test_utils::assert_parse_tree!(
r#"
f(a, b, c
1 + 2
"#,
FuncCall [
Ident("f")
Args [
Error(compose_error_codes::E0001_UNCLOSED_DELIMITER)
Ident("a")
Comma(",")
Ident("b")
Comma(",")
Ident("c")
Error(compose_error_codes::E0009_ARGS_MISSING_COMMAS)
Binary [
Int("1")
Plus("+")
Int("2")
]
]
]
);
§Example: Skipping subtree content
compose_syntax::test_utils::assert_parse_tree!(
"{ ref mut a => a }",
Lambda [
LeftBrace("{")
Params [
Param [
Ref("ref")
Mut("mut")
Ident("a")
]
]
...
]
);
§Common mistakes
- Forgetting to provide the exact token text string for leaf nodes results in a compile error.
- Using
Warn
orError
asSyntaxKind
variants inside children nodes causes errors; they must use the special macro arms.
§See also
SyntaxKind
enum variants — the node/kind names used in this macro.- Parser error codes for
Warn
andError
nodes. NodesTester
struct for underlying test traversal and assertions.