@@ -51,6 +51,8 @@ impl MetaTemplate {
51
51
#[ derive( Clone , Debug , PartialEq , Eq ) ]
52
52
pub ( crate ) enum Op {
53
53
Var { name : SmolStr , kind : Option < SmolStr > , id : tt:: TokenId } ,
54
+ Ignore { name : SmolStr , id : tt:: TokenId } ,
55
+ Index { depth : u32 } ,
54
56
Repeat { tokens : MetaTemplate , kind : RepeatKind , separator : Option < Separator > } ,
55
57
Leaf ( tt:: Leaf ) ,
56
58
Subtree { tokens : MetaTemplate , delimiter : Option < tt:: Delimiter > } ,
@@ -113,11 +115,30 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
113
115
Some ( it) => it,
114
116
} ;
115
117
match second {
116
- tt:: TokenTree :: Subtree ( subtree) => {
117
- let ( separator, kind) = parse_repeat ( src) ?;
118
- let tokens = MetaTemplate :: parse ( subtree, mode) ?;
119
- Op :: Repeat { tokens, separator, kind }
120
- }
118
+ tt:: TokenTree :: Subtree ( subtree) => match subtree. delimiter_kind ( ) {
119
+ Some ( tt:: DelimiterKind :: Parenthesis ) => {
120
+ let ( separator, kind) = parse_repeat ( src) ?;
121
+ let tokens = MetaTemplate :: parse ( subtree, mode) ?;
122
+ Op :: Repeat { tokens, separator, kind }
123
+ }
124
+ Some ( tt:: DelimiterKind :: Brace ) => match mode {
125
+ Mode :: Template => {
126
+ parse_metavar_expr ( & mut TtIter :: new ( subtree) ) . map_err ( |( ) | {
127
+ ParseError :: unexpected ( "invalid metavariable expression" )
128
+ } ) ?
129
+ }
130
+ Mode :: Pattern => {
131
+ return Err ( ParseError :: unexpected (
132
+ "`${}` metavariable expressions are not allowed in matchers" ,
133
+ ) )
134
+ }
135
+ } ,
136
+ _ => {
137
+ return Err ( ParseError :: expected (
138
+ "expected `$()` repetition or `${}` expression" ,
139
+ ) )
140
+ }
141
+ } ,
121
142
tt:: TokenTree :: Leaf ( leaf) => match leaf {
122
143
tt:: Leaf :: Ident ( ident) if ident. text == "crate" => {
123
144
// We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path.
@@ -209,3 +230,32 @@ fn parse_repeat(src: &mut TtIter) -> Result<(Option<Separator>, RepeatKind), Par
209
230
}
210
231
Err ( ParseError :: InvalidRepeat )
211
232
}
233
+
234
+ fn parse_metavar_expr ( src : & mut TtIter ) -> Result < Op , ( ) > {
235
+ let func = src. expect_ident ( ) ?;
236
+ let args = src. expect_subtree ( ) ?;
237
+
238
+ if args. delimiter_kind ( ) != Some ( tt:: DelimiterKind :: Parenthesis ) {
239
+ return Err ( ( ) ) ;
240
+ }
241
+
242
+ let mut args = TtIter :: new ( args) ;
243
+
244
+ let op = match & * func. text {
245
+ "ignore" => {
246
+ let ident = args. expect_ident ( ) ?;
247
+ Op :: Ignore { name : ident. text . clone ( ) , id : ident. id }
248
+ }
249
+ "index" => {
250
+ let depth = if args. len ( ) == 0 { 0 } else { args. expect_u32_literal ( ) ? } ;
251
+ Op :: Index { depth }
252
+ }
253
+ _ => return Err ( ( ) ) ,
254
+ } ;
255
+
256
+ if args. next ( ) . is_some ( ) {
257
+ return Err ( ( ) ) ;
258
+ }
259
+
260
+ Ok ( op)
261
+ }
0 commit comments