diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index 370990e21f..3c717e5f9e 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs @@ -33,7 +33,7 @@ pub(super) enum ItemFlavor { pub(super) const ITEM_RECOVERY_SET: TokenSet = token_set![ FN_KW, STRUCT_KW, ENUM_KW, IMPL_KW, TRAIT_KW, CONST_KW, STATIC_KW, LET_KW, MOD_KW, PUB_KW, - CRATE_KW, USE_KW + CRATE_KW, USE_KW, MACRO_KW ]; pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) { @@ -249,6 +249,11 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> { // } adt::struct_def(p, m); } + // test pub_macro_def + // pub macro m($:ident) {} + T![macro] => { + macro_def(p, m); + } IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => { // test union_items // union Foo {} @@ -379,6 +384,29 @@ pub(crate) fn mod_item_list(p: &mut Parser) { m.complete(p, ITEM_LIST); } +// test macro_def +// macro m { ($i:ident) => {} } +// macro m($i:ident) {} +fn macro_def(p: &mut Parser, m: Marker) { + p.expect(T![macro]); + p.expect(IDENT); + if p.at(T!['{']) { + token_tree(p); + } else if !p.at(T!['(']) { + p.error("unmatched `(`"); + } else { + let m = p.start(); + token_tree(p); + match p.current() { + T!['{'] | T!['['] | T!['('] => token_tree(p), + _ => p.error("expected `{`, `[`, `(`"), + } + m.complete(p, TOKEN_TREE); + } + + m.complete(p, MACRO_DEF); +} + fn macro_call(p: &mut Parser) -> BlockLike { assert!(paths::is_use_path_start(p)); paths::use_path(p); diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index fe0fcdb33f..afe4ce51a9 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs @@ -100,6 +100,7 @@ pub enum SyntaxKind { TRY_KW, BOX_KW, AWAIT_KW, + MACRO_KW, AUTO_KW, DEFAULT_KW, EXISTENTIAL_KW, @@ -136,6 +137,7 @@ pub enum SyntaxKind { TYPE_ALIAS_DEF, MACRO_CALL, TOKEN_TREE, + MACRO_DEF, PAREN_TYPE, TUPLE_TYPE, NEVER_TYPE, @@ -251,7 +253,7 @@ impl SyntaxKind { | SUPER_KW | IN_KW | WHERE_KW | FOR_KW | LOOP_KW | WHILE_KW | CONTINUE_KW | BREAK_KW | IF_KW | ELSE_KW | MATCH_KW | CONST_KW | STATIC_KW | MUT_KW | UNSAFE_KW | TYPE_KW | REF_KW | LET_KW | MOVE_KW | RETURN_KW | TRY_KW | BOX_KW | AWAIT_KW - | AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW => true, + | MACRO_KW | AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW => true, _ => false, } } @@ -314,6 +316,7 @@ impl SyntaxKind { "try" => TRY_KW, "box" => BOX_KW, "await" => AWAIT_KW, + "macro" => MACRO_KW, _ => return None, }; Some(kw) @@ -628,6 +631,9 @@ macro_rules! T { ( await ) => { $crate::SyntaxKind::AWAIT_KW }; + ( macro ) => { + $crate::SyntaxKind::MACRO_KW + }; ( auto ) => { $crate::SyntaxKind::AUTO_KW }; diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index a228fa9d6e..3f1cd0b903 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -94,7 +94,8 @@ Grammar( "return", "try", "box", - "await" + "await", + "macro" ], contextual_keywords: [ "auto", @@ -140,6 +141,7 @@ Grammar( "TYPE_ALIAS_DEF", "MACRO_CALL", "TOKEN_TREE", + "MACRO_DEF", "PAREN_TYPE", "TUPLE_TYPE", diff --git a/crates/ra_syntax/test_data/parser/err/0028_macro_2.0.txt b/crates/ra_syntax/test_data/parser/err/0028_macro_2.0.txt deleted file mode 100644 index c5be73a5a0..0000000000 --- a/crates/ra_syntax/test_data/parser/err/0028_macro_2.0.txt +++ /dev/null @@ -1,328 +0,0 @@ -SOURCE_FILE@[0; 349) - MACRO_CALL@[0; 41) - PATH@[0; 5) - PATH_SEGMENT@[0; 5) - NAME_REF@[0; 5) - IDENT@[0; 5) "macro" - WHITESPACE@[5; 6) " " - NAME@[6; 21) - IDENT@[6; 21) "parse_use_trees" - TOKEN_TREE@[21; 41) - L_PAREN@[21; 22) "(" - DOLLAR@[22; 23) "$" - TOKEN_TREE@[23; 32) - L_PAREN@[23; 24) "(" - DOLLAR@[24; 25) "$" - IDENT@[25; 26) "s" - COLON@[26; 27) ":" - IDENT@[27; 31) "expr" - R_PAREN@[31; 32) ")" - COMMA@[32; 33) "," - STAR@[33; 34) "*" - WHITESPACE@[34; 35) " " - DOLLAR@[35; 36) "$" - TOKEN_TREE@[36; 39) - L_PAREN@[36; 37) "(" - COMMA@[37; 38) "," - R_PAREN@[38; 39) ")" - STAR@[39; 40) "*" - R_PAREN@[40; 41) ")" - WHITESPACE@[41; 42) " " - ERROR@[42; 93) - L_CURLY@[42; 43) "{" - WHITESPACE@[43; 48) "\n " - MACRO_CALL@[48; 91) - PATH@[48; 51) - PATH_SEGMENT@[48; 51) - NAME_REF@[48; 51) - IDENT@[48; 51) "vec" - EXCL@[51; 52) "!" - TOKEN_TREE@[52; 91) - L_BRACK@[52; 53) "[" - WHITESPACE@[53; 62) "\n " - DOLLAR@[62; 63) "$" - TOKEN_TREE@[63; 84) - L_PAREN@[63; 64) "(" - IDENT@[64; 78) "parse_use_tree" - TOKEN_TREE@[78; 82) - L_PAREN@[78; 79) "(" - DOLLAR@[79; 80) "$" - IDENT@[80; 81) "s" - R_PAREN@[81; 82) ")" - COMMA@[82; 83) "," - R_PAREN@[83; 84) ")" - STAR@[84; 85) "*" - WHITESPACE@[85; 90) "\n " - R_BRACK@[90; 91) "]" - WHITESPACE@[91; 92) "\n" - R_CURLY@[92; 93) "}" - WHITESPACE@[93; 95) "\n\n" - FN_DEF@[95; 348) - ATTR@[95; 102) - POUND@[95; 96) "#" - L_BRACK@[96; 97) "[" - PATH@[97; 101) - PATH_SEGMENT@[97; 101) - NAME_REF@[97; 101) - IDENT@[97; 101) "test" - R_BRACK@[101; 102) "]" - WHITESPACE@[102; 103) "\n" - FN_KW@[103; 105) "fn" - WHITESPACE@[105; 106) " " - NAME@[106; 125) - IDENT@[106; 125) "test_use_tree_merge" - PARAM_LIST@[125; 127) - L_PAREN@[125; 126) "(" - R_PAREN@[126; 127) ")" - WHITESPACE@[127; 128) " " - BLOCK_EXPR@[128; 348) - BLOCK@[128; 348) - L_CURLY@[128; 129) "{" - WHITESPACE@[129; 134) "\n " - EXPR_STMT@[134; 139) - PATH_EXPR@[134; 139) - PATH@[134; 139) - PATH_SEGMENT@[134; 139) - NAME_REF@[134; 139) - IDENT@[134; 139) "macro" - WHITESPACE@[139; 140) " " - EXPR_STMT@[140; 154) - CALL_EXPR@[140; 154) - PATH_EXPR@[140; 150) - PATH@[140; 150) - PATH_SEGMENT@[140; 150) - NAME_REF@[140; 150) - IDENT@[140; 150) "test_merge" - ARG_LIST@[150; 154) - L_PAREN@[150; 151) "(" - ARRAY_EXPR@[151; 154) - L_BRACK@[151; 152) "[" - ERROR@[152; 153) - DOLLAR@[152; 153) "$" - PAREN_EXPR@[153; 154) - L_PAREN@[153; 154) "(" - EXPR_STMT@[154; 155) - ERROR@[154; 155) - DOLLAR@[154; 155) "$" - EXPR_STMT@[155; 160) - PATH_EXPR@[155; 160) - PATH@[155; 160) - PATH_SEGMENT@[155; 160) - NAME_REF@[155; 160) - IDENT@[155; 160) "input" - EXPR_STMT@[160; 161) - ERROR@[160; 161) - COLON@[160; 161) ":" - EXPR_STMT@[161; 165) - PATH_EXPR@[161; 165) - PATH@[161; 165) - PATH_SEGMENT@[161; 165) - NAME_REF@[161; 165) - IDENT@[161; 165) "expr" - EXPR_STMT@[165; 166) - ERROR@[165; 166) - R_PAREN@[165; 166) ")" - EXPR_STMT@[166; 167) - ERROR@[166; 167) - COMMA@[166; 167) "," - EXPR_STMT@[167; 170) - PREFIX_EXPR@[167; 170) - STAR@[167; 168) "*" - WHITESPACE@[168; 169) " " - ERROR@[169; 170) - DOLLAR@[169; 170) "$" - EXPR_STMT@[170; 171) - PAREN_EXPR@[170; 171) - L_PAREN@[170; 171) "(" - EXPR_STMT@[171; 172) - ERROR@[171; 172) - COMMA@[171; 172) "," - EXPR_STMT@[172; 173) - ERROR@[172; 173) - R_PAREN@[172; 173) ")" - EXPR_STMT@[173; 175) - PREFIX_EXPR@[173; 175) - STAR@[173; 174) "*" - ERROR@[174; 175) - R_BRACK@[174; 175) "]" - EXPR_STMT@[175; 176) - ERROR@[175; 176) - COMMA@[175; 176) "," - WHITESPACE@[176; 177) " " - EXPR_STMT@[177; 180) - ARRAY_EXPR@[177; 180) - L_BRACK@[177; 178) "[" - ERROR@[178; 179) - DOLLAR@[178; 179) "$" - PAREN_EXPR@[179; 180) - L_PAREN@[179; 180) "(" - EXPR_STMT@[180; 181) - ERROR@[180; 181) - DOLLAR@[180; 181) "$" - EXPR_STMT@[181; 187) - PATH_EXPR@[181; 187) - PATH@[181; 187) - PATH_SEGMENT@[181; 187) - NAME_REF@[181; 187) - IDENT@[181; 187) "output" - EXPR_STMT@[187; 188) - ERROR@[187; 188) - COLON@[187; 188) ":" - EXPR_STMT@[188; 192) - PATH_EXPR@[188; 192) - PATH@[188; 192) - PATH_SEGMENT@[188; 192) - NAME_REF@[188; 192) - IDENT@[188; 192) "expr" - EXPR_STMT@[192; 193) - ERROR@[192; 193) - R_PAREN@[192; 193) ")" - EXPR_STMT@[193; 194) - ERROR@[193; 194) - COMMA@[193; 194) "," - EXPR_STMT@[194; 197) - PREFIX_EXPR@[194; 197) - STAR@[194; 195) "*" - WHITESPACE@[195; 196) " " - ERROR@[196; 197) - DOLLAR@[196; 197) "$" - EXPR_STMT@[197; 198) - PAREN_EXPR@[197; 198) - L_PAREN@[197; 198) "(" - EXPR_STMT@[198; 199) - ERROR@[198; 199) - COMMA@[198; 199) "," - EXPR_STMT@[199; 200) - ERROR@[199; 200) - R_PAREN@[199; 200) ")" - EXPR_STMT@[200; 202) - PREFIX_EXPR@[200; 202) - STAR@[200; 201) "*" - ERROR@[201; 202) - R_BRACK@[201; 202) "]" - EXPR_STMT@[202; 203) - ERROR@[202; 203) - R_PAREN@[202; 203) ")" - WHITESPACE@[203; 204) " " - BLOCK_EXPR@[204; 346) - BLOCK@[204; 346) - L_CURLY@[204; 205) "{" - WHITESPACE@[205; 214) "\n " - EXPR_STMT@[214; 340) - MACRO_CALL@[214; 339) - PATH@[214; 223) - PATH_SEGMENT@[214; 223) - NAME_REF@[214; 223) - IDENT@[214; 223) "assert_eq" - EXCL@[223; 224) "!" - TOKEN_TREE@[224; 339) - L_PAREN@[224; 225) "(" - WHITESPACE@[225; 238) "\n " - IDENT@[238; 253) "merge_use_trees" - TOKEN_TREE@[253; 284) - L_PAREN@[253; 254) "(" - IDENT@[254; 269) "parse_use_trees" - EXCL@[269; 270) "!" - TOKEN_TREE@[270; 283) - L_PAREN@[270; 271) "(" - DOLLAR@[271; 272) "$" - TOKEN_TREE@[272; 281) - L_PAREN@[272; 273) "(" - DOLLAR@[273; 274) "$" - IDENT@[274; 279) "input" - COMMA@[279; 280) "," - R_PAREN@[280; 281) ")" - STAR@[281; 282) "*" - R_PAREN@[282; 283) ")" - R_PAREN@[283; 284) ")" - COMMA@[284; 285) "," - WHITESPACE@[285; 298) "\n " - IDENT@[298; 313) "parse_use_trees" - EXCL@[313; 314) "!" - TOKEN_TREE@[314; 328) - L_PAREN@[314; 315) "(" - DOLLAR@[315; 316) "$" - TOKEN_TREE@[316; 326) - L_PAREN@[316; 317) "(" - DOLLAR@[317; 318) "$" - IDENT@[318; 324) "output" - COMMA@[324; 325) "," - R_PAREN@[325; 326) ")" - STAR@[326; 327) "*" - R_PAREN@[327; 328) ")" - COMMA@[328; 329) "," - WHITESPACE@[329; 338) "\n " - R_PAREN@[338; 339) ")" - SEMI@[339; 340) ";" - WHITESPACE@[340; 345) "\n " - R_CURLY@[345; 346) "}" - WHITESPACE@[346; 347) "\n" - R_CURLY@[347; 348) "}" - WHITESPACE@[348; 349) "\n" -error 5: expected EXCL -error 41: expected SEMI -error 42: expected an item -error 139: expected SEMI -error 152: expected expression -error 153: expected COMMA -error 154: expected expression -error 154: expected R_PAREN -error 154: expected COMMA -error 154: expected expression -error 154: expected R_BRACK -error 154: expected COMMA -error 154: expected SEMI -error 154: expected expression -error 155: expected SEMI -error 160: expected SEMI -error 160: expected expression -error 161: expected SEMI -error 165: expected SEMI -error 165: expected expression -error 166: expected SEMI -error 166: expected expression -error 167: expected SEMI -error 169: expected expression -error 170: expected SEMI -error 171: expected expression -error 171: expected R_PAREN -error 171: expected SEMI -error 171: expected expression -error 172: expected SEMI -error 172: expected expression -error 173: expected SEMI -error 174: expected expression -error 175: expected SEMI -error 175: expected expression -error 176: expected SEMI -error 178: expected expression -error 179: expected COMMA -error 180: expected expression -error 180: expected R_PAREN -error 180: expected COMMA -error 180: expected expression -error 180: expected R_BRACK -error 180: expected SEMI -error 180: expected expression -error 181: expected SEMI -error 187: expected SEMI -error 187: expected expression -error 188: expected SEMI -error 192: expected SEMI -error 192: expected expression -error 193: expected SEMI -error 193: expected expression -error 194: expected SEMI -error 196: expected expression -error 197: expected SEMI -error 198: expected expression -error 198: expected R_PAREN -error 198: expected SEMI -error 198: expected expression -error 199: expected SEMI -error 199: expected expression -error 200: expected SEMI -error 201: expected expression -error 202: expected SEMI -error 202: expected expression -error 203: expected SEMI diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.rs b/crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.rs new file mode 100644 index 0000000000..319a4e2aad --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.rs @@ -0,0 +1,2 @@ +macro m { ($i:ident) => {} } +macro m($i:ident) {} diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.txt b/crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.txt new file mode 100644 index 0000000000..af1122bfa4 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.txt @@ -0,0 +1,43 @@ +SOURCE_FILE@[0; 50) + MACRO_DEF@[0; 28) + MACRO_KW@[0; 5) "macro" + WHITESPACE@[5; 6) " " + IDENT@[6; 7) "m" + WHITESPACE@[7; 8) " " + TOKEN_TREE@[8; 28) + L_CURLY@[8; 9) "{" + WHITESPACE@[9; 10) " " + TOKEN_TREE@[10; 20) + L_PAREN@[10; 11) "(" + DOLLAR@[11; 12) "$" + IDENT@[12; 13) "i" + COLON@[13; 14) ":" + IDENT@[14; 19) "ident" + R_PAREN@[19; 20) ")" + WHITESPACE@[20; 21) " " + EQ@[21; 22) "=" + R_ANGLE@[22; 23) ">" + WHITESPACE@[23; 24) " " + TOKEN_TREE@[24; 26) + L_CURLY@[24; 25) "{" + R_CURLY@[25; 26) "}" + WHITESPACE@[26; 27) " " + R_CURLY@[27; 28) "}" + WHITESPACE@[28; 29) "\n" + MACRO_DEF@[29; 49) + MACRO_KW@[29; 34) "macro" + WHITESPACE@[34; 35) " " + IDENT@[35; 36) "m" + TOKEN_TREE@[36; 49) + TOKEN_TREE@[36; 46) + L_PAREN@[36; 37) "(" + DOLLAR@[37; 38) "$" + IDENT@[38; 39) "i" + COLON@[39; 40) ":" + IDENT@[40; 45) "ident" + R_PAREN@[45; 46) ")" + WHITESPACE@[46; 47) " " + TOKEN_TREE@[47; 49) + L_CURLY@[47; 48) "{" + R_CURLY@[48; 49) "}" + WHITESPACE@[49; 50) "\n" diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.rs b/crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.rs new file mode 100644 index 0000000000..3b2be597fd --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.rs @@ -0,0 +1 @@ +pub macro m($:ident) {} diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.txt b/crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.txt new file mode 100644 index 0000000000..985f61f89e --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.txt @@ -0,0 +1,20 @@ +SOURCE_FILE@[0; 24) + MACRO_DEF@[0; 23) + VISIBILITY@[0; 3) + PUB_KW@[0; 3) "pub" + WHITESPACE@[3; 4) " " + MACRO_KW@[4; 9) "macro" + WHITESPACE@[9; 10) " " + IDENT@[10; 11) "m" + TOKEN_TREE@[11; 23) + TOKEN_TREE@[11; 20) + L_PAREN@[11; 12) "(" + DOLLAR@[12; 13) "$" + COLON@[13; 14) ":" + IDENT@[14; 19) "ident" + R_PAREN@[19; 20) ")" + WHITESPACE@[20; 21) " " + TOKEN_TREE@[21; 23) + L_CURLY@[21; 22) "{" + R_CURLY@[22; 23) "}" + WHITESPACE@[23; 24) "\n" diff --git a/crates/ra_syntax/test_data/parser/err/0028_macro_2.0.rs b/crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.rs similarity index 100% rename from crates/ra_syntax/test_data/parser/err/0028_macro_2.0.rs rename to crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.rs diff --git a/crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.txt b/crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.txt new file mode 100644 index 0000000000..158af85f55 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.txt @@ -0,0 +1,174 @@ +SOURCE_FILE@[0; 349) + MACRO_DEF@[0; 93) + MACRO_KW@[0; 5) "macro" + WHITESPACE@[5; 6) " " + IDENT@[6; 21) "parse_use_trees" + TOKEN_TREE@[21; 93) + TOKEN_TREE@[21; 41) + L_PAREN@[21; 22) "(" + DOLLAR@[22; 23) "$" + TOKEN_TREE@[23; 32) + L_PAREN@[23; 24) "(" + DOLLAR@[24; 25) "$" + IDENT@[25; 26) "s" + COLON@[26; 27) ":" + IDENT@[27; 31) "expr" + R_PAREN@[31; 32) ")" + COMMA@[32; 33) "," + STAR@[33; 34) "*" + WHITESPACE@[34; 35) " " + DOLLAR@[35; 36) "$" + TOKEN_TREE@[36; 39) + L_PAREN@[36; 37) "(" + COMMA@[37; 38) "," + R_PAREN@[38; 39) ")" + STAR@[39; 40) "*" + R_PAREN@[40; 41) ")" + WHITESPACE@[41; 42) " " + TOKEN_TREE@[42; 93) + L_CURLY@[42; 43) "{" + WHITESPACE@[43; 48) "\n " + IDENT@[48; 51) "vec" + EXCL@[51; 52) "!" + TOKEN_TREE@[52; 91) + L_BRACK@[52; 53) "[" + WHITESPACE@[53; 62) "\n " + DOLLAR@[62; 63) "$" + TOKEN_TREE@[63; 84) + L_PAREN@[63; 64) "(" + IDENT@[64; 78) "parse_use_tree" + TOKEN_TREE@[78; 82) + L_PAREN@[78; 79) "(" + DOLLAR@[79; 80) "$" + IDENT@[80; 81) "s" + R_PAREN@[81; 82) ")" + COMMA@[82; 83) "," + R_PAREN@[83; 84) ")" + STAR@[84; 85) "*" + WHITESPACE@[85; 90) "\n " + R_BRACK@[90; 91) "]" + WHITESPACE@[91; 92) "\n" + R_CURLY@[92; 93) "}" + WHITESPACE@[93; 95) "\n\n" + FN_DEF@[95; 348) + ATTR@[95; 102) + POUND@[95; 96) "#" + L_BRACK@[96; 97) "[" + PATH@[97; 101) + PATH_SEGMENT@[97; 101) + NAME_REF@[97; 101) + IDENT@[97; 101) "test" + R_BRACK@[101; 102) "]" + WHITESPACE@[102; 103) "\n" + FN_KW@[103; 105) "fn" + WHITESPACE@[105; 106) " " + NAME@[106; 125) + IDENT@[106; 125) "test_use_tree_merge" + PARAM_LIST@[125; 127) + L_PAREN@[125; 126) "(" + R_PAREN@[126; 127) ")" + WHITESPACE@[127; 128) " " + BLOCK_EXPR@[128; 348) + BLOCK@[128; 348) + L_CURLY@[128; 129) "{" + WHITESPACE@[129; 134) "\n " + MACRO_DEF@[134; 346) + MACRO_KW@[134; 139) "macro" + WHITESPACE@[139; 140) " " + IDENT@[140; 150) "test_merge" + TOKEN_TREE@[150; 346) + TOKEN_TREE@[150; 203) + L_PAREN@[150; 151) "(" + TOKEN_TREE@[151; 175) + L_BRACK@[151; 152) "[" + DOLLAR@[152; 153) "$" + TOKEN_TREE@[153; 166) + L_PAREN@[153; 154) "(" + DOLLAR@[154; 155) "$" + IDENT@[155; 160) "input" + COLON@[160; 161) ":" + IDENT@[161; 165) "expr" + R_PAREN@[165; 166) ")" + COMMA@[166; 167) "," + STAR@[167; 168) "*" + WHITESPACE@[168; 169) " " + DOLLAR@[169; 170) "$" + TOKEN_TREE@[170; 173) + L_PAREN@[170; 171) "(" + COMMA@[171; 172) "," + R_PAREN@[172; 173) ")" + STAR@[173; 174) "*" + R_BRACK@[174; 175) "]" + COMMA@[175; 176) "," + WHITESPACE@[176; 177) " " + TOKEN_TREE@[177; 202) + L_BRACK@[177; 178) "[" + DOLLAR@[178; 179) "$" + TOKEN_TREE@[179; 193) + L_PAREN@[179; 180) "(" + DOLLAR@[180; 181) "$" + IDENT@[181; 187) "output" + COLON@[187; 188) ":" + IDENT@[188; 192) "expr" + R_PAREN@[192; 193) ")" + COMMA@[193; 194) "," + STAR@[194; 195) "*" + WHITESPACE@[195; 196) " " + DOLLAR@[196; 197) "$" + TOKEN_TREE@[197; 200) + L_PAREN@[197; 198) "(" + COMMA@[198; 199) "," + R_PAREN@[199; 200) ")" + STAR@[200; 201) "*" + R_BRACK@[201; 202) "]" + R_PAREN@[202; 203) ")" + WHITESPACE@[203; 204) " " + TOKEN_TREE@[204; 346) + L_CURLY@[204; 205) "{" + WHITESPACE@[205; 214) "\n " + IDENT@[214; 223) "assert_eq" + EXCL@[223; 224) "!" + TOKEN_TREE@[224; 339) + L_PAREN@[224; 225) "(" + WHITESPACE@[225; 238) "\n " + IDENT@[238; 253) "merge_use_trees" + TOKEN_TREE@[253; 284) + L_PAREN@[253; 254) "(" + IDENT@[254; 269) "parse_use_trees" + EXCL@[269; 270) "!" + TOKEN_TREE@[270; 283) + L_PAREN@[270; 271) "(" + DOLLAR@[271; 272) "$" + TOKEN_TREE@[272; 281) + L_PAREN@[272; 273) "(" + DOLLAR@[273; 274) "$" + IDENT@[274; 279) "input" + COMMA@[279; 280) "," + R_PAREN@[280; 281) ")" + STAR@[281; 282) "*" + R_PAREN@[282; 283) ")" + R_PAREN@[283; 284) ")" + COMMA@[284; 285) "," + WHITESPACE@[285; 298) "\n " + IDENT@[298; 313) "parse_use_trees" + EXCL@[313; 314) "!" + TOKEN_TREE@[314; 328) + L_PAREN@[314; 315) "(" + DOLLAR@[315; 316) "$" + TOKEN_TREE@[316; 326) + L_PAREN@[316; 317) "(" + DOLLAR@[317; 318) "$" + IDENT@[318; 324) "output" + COMMA@[324; 325) "," + R_PAREN@[325; 326) ")" + STAR@[326; 327) "*" + R_PAREN@[327; 328) ")" + COMMA@[328; 329) "," + WHITESPACE@[329; 338) "\n " + R_PAREN@[338; 339) ")" + SEMI@[339; 340) ";" + WHITESPACE@[340; 345) "\n " + R_CURLY@[345; 346) "}" + WHITESPACE@[346; 347) "\n" + R_CURLY@[347; 348) "}" + WHITESPACE@[348; 349) "\n"