@@ -51,6 +51,8 @@ impl MetaTemplate {
5151#[ derive( Clone , Debug , PartialEq , Eq ) ]
5252pub ( crate ) enum Op {
5353 Var { name : SmolStr , kind : Option < SmolStr > , id : tt:: TokenId } ,
54+ Ignore { name : SmolStr , id : tt:: TokenId } ,
55+ Index { depth : u32 } ,
5456 Repeat { tokens : MetaTemplate , kind : RepeatKind , separator : Option < Separator > } ,
5557 Leaf ( tt:: Leaf ) ,
5658 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
113115 Some ( it) => it,
114116 } ;
115117 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+ } ,
121142 tt:: TokenTree :: Leaf ( leaf) => match leaf {
122143 tt:: Leaf :: Ident ( ident) if ident. text == "crate" => {
123144 // 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
209230 }
210231 Err ( ParseError :: InvalidRepeat )
211232}
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