@@ -47,46 +47,7 @@ impl MetaVarExpr {
4747 check_trailing_token ( & mut iter, psess) ?;
4848 let mut iter = args. iter ( ) ;
4949 let rslt = match ident. as_str ( ) {
50- "concat" => {
51- let mut result = Vec :: new ( ) ;
52- loop {
53- let is_var = try_eat_dollar ( & mut iter) ;
54- let token = parse_token ( & mut iter, psess, outer_span) ?;
55- let element = if is_var {
56- MetaVarExprConcatElem :: Var ( parse_ident_from_token ( psess, token) ?)
57- } else if let TokenKind :: Literal ( Lit {
58- kind : token:: LitKind :: Str ,
59- symbol,
60- suffix : None ,
61- } ) = token. kind
62- {
63- MetaVarExprConcatElem :: Literal ( symbol)
64- } else {
65- match parse_ident_from_token ( psess, token) {
66- Err ( err) => {
67- err. cancel ( ) ;
68- return Err ( psess
69- . dcx ( )
70- . struct_span_err ( token. span , UNSUPPORTED_CONCAT_ELEM_ERR ) ) ;
71- }
72- Ok ( elem) => MetaVarExprConcatElem :: Ident ( elem) ,
73- }
74- } ;
75- result. push ( element) ;
76- if iter. peek ( ) . is_none ( ) {
77- break ;
78- }
79- if !try_eat_comma ( & mut iter) {
80- return Err ( psess. dcx ( ) . struct_span_err ( outer_span, "expected comma" ) ) ;
81- }
82- }
83- if result. len ( ) < 2 {
84- return Err ( psess
85- . dcx ( )
86- . struct_span_err ( ident. span , "`concat` must have at least two elements" ) ) ;
87- }
88- MetaVarExpr :: Concat ( result. into ( ) )
89- }
50+ "concat" => parse_concat ( & mut iter, psess, outer_span, ident. span ) ?,
9051 "count" => parse_count ( & mut iter, psess, ident. span ) ?,
9152 "ignore" => {
9253 eat_dollar ( & mut iter, psess, ident. span ) ?;
@@ -126,6 +87,22 @@ impl MetaVarExpr {
12687 }
12788}
12889
90+ // Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}`
91+ fn check_trailing_token < ' psess > (
92+ iter : & mut TokenStreamIter < ' _ > ,
93+ psess : & ' psess ParseSess ,
94+ ) -> PResult < ' psess , ( ) > {
95+ if let Some ( tt) = iter. next ( ) {
96+ let mut diag = psess
97+ . dcx ( )
98+ . struct_span_err ( tt. span ( ) , format ! ( "unexpected token: {}" , pprust:: tt_to_string( tt) ) ) ;
99+ diag. span_note ( tt. span ( ) , "meta-variable expression must not have trailing tokens" ) ;
100+ Err ( diag)
101+ } else {
102+ Ok ( ( ) )
103+ }
104+ }
105+
129106/// Indicates what is placed in a `concat` parameter. For example, literals
130107/// (`${concat("foo", "bar")}`) or adhoc identifiers (`${concat(foo, bar)}`).
131108#[ derive( Debug , Decodable , Encodable , PartialEq ) ]
@@ -140,20 +117,48 @@ pub(crate) enum MetaVarExprConcatElem {
140117 Var ( Ident ) ,
141118}
142119
143- // Checks if there are any remaining tokens. For example, `${ignore( ident ... a b c ...)}`
144- fn check_trailing_token < ' psess > (
120+ /// Parse a meta-variable `concat` expression: `concat($metavar, ident, ...)`.
121+ fn parse_concat < ' psess > (
145122 iter : & mut TokenStreamIter < ' _ > ,
146123 psess : & ' psess ParseSess ,
147- ) -> PResult < ' psess , ( ) > {
148- if let Some ( tt) = iter. next ( ) {
149- let mut diag = psess
124+ outer_span : Span ,
125+ expr_ident_span : Span ,
126+ ) -> PResult < ' psess , MetaVarExpr > {
127+ let mut result = Vec :: new ( ) ;
128+ loop {
129+ let is_var = try_eat_dollar ( iter) ;
130+ let token = parse_token ( iter, psess, outer_span) ?;
131+ let element = if is_var {
132+ MetaVarExprConcatElem :: Var ( parse_ident_from_token ( psess, token) ?)
133+ } else if let TokenKind :: Literal ( Lit { kind : token:: LitKind :: Str , symbol, suffix : None } ) =
134+ token. kind
135+ {
136+ MetaVarExprConcatElem :: Literal ( symbol)
137+ } else {
138+ match parse_ident_from_token ( psess, token) {
139+ Err ( err) => {
140+ err. cancel ( ) ;
141+ return Err ( psess
142+ . dcx ( )
143+ . struct_span_err ( token. span , UNSUPPORTED_CONCAT_ELEM_ERR ) ) ;
144+ }
145+ Ok ( elem) => MetaVarExprConcatElem :: Ident ( elem) ,
146+ }
147+ } ;
148+ result. push ( element) ;
149+ if iter. peek ( ) . is_none ( ) {
150+ break ;
151+ }
152+ if !try_eat_comma ( iter) {
153+ return Err ( psess. dcx ( ) . struct_span_err ( outer_span, "expected comma" ) ) ;
154+ }
155+ }
156+ if result. len ( ) < 2 {
157+ return Err ( psess
150158 . dcx ( )
151- . struct_span_err ( tt. span ( ) , format ! ( "unexpected token: {}" , pprust:: tt_to_string( tt) ) ) ;
152- diag. span_note ( tt. span ( ) , "meta-variable expression must not have trailing tokens" ) ;
153- Err ( diag)
154- } else {
155- Ok ( ( ) )
159+ . struct_span_err ( expr_ident_span, "`concat` must have at least two elements" ) ) ;
156160 }
161+ Ok ( MetaVarExpr :: Concat ( result. into ( ) ) )
157162}
158163
159164/// Parse a meta-variable `count` expression: `count(ident[, depth])`
0 commit comments