10
10
11
11
use ast:: { self , TokenTree } ;
12
12
use codemap:: { Span , DUMMY_SP } ;
13
- use ext:: base:: { ExtCtxt , MacResult , SyntaxExtension } ;
13
+ use ext:: base:: { DummyResult , ExtCtxt , MacResult , SyntaxExtension } ;
14
14
use ext:: base:: { NormalTT , TTMacroExpander } ;
15
15
use ext:: tt:: macro_parser:: { Success , Error , Failure } ;
16
- use ext:: tt:: macro_parser:: { NamedMatch , MatchedSeq , MatchedNonterminal } ;
16
+ use ext:: tt:: macro_parser:: { MatchedSeq , MatchedNonterminal } ;
17
17
use ext:: tt:: macro_parser:: parse;
18
18
use parse:: lexer:: new_tt_reader;
19
19
use parse:: parser:: Parser ;
@@ -129,16 +129,20 @@ impl<'a> MacResult for ParserAnyMacro<'a> {
129
129
struct MacroRulesMacroExpander {
130
130
name : ast:: Ident ,
131
131
imported_from : Option < ast:: Ident > ,
132
- lhses : Vec < Rc < NamedMatch > > ,
133
- rhses : Vec < Rc < NamedMatch > > ,
132
+ lhses : Vec < TokenTree > ,
133
+ rhses : Vec < TokenTree > ,
134
+ valid : bool ,
134
135
}
135
136
136
137
impl TTMacroExpander for MacroRulesMacroExpander {
137
138
fn expand < ' cx > ( & self ,
138
139
cx : & ' cx mut ExtCtxt ,
139
140
sp : Span ,
140
- arg : & [ ast :: TokenTree ] )
141
+ arg : & [ TokenTree ] )
141
142
-> Box < MacResult +' cx > {
143
+ if !self . valid {
144
+ return DummyResult :: any ( sp) ;
145
+ }
142
146
generic_extension ( cx,
143
147
sp,
144
148
self . name ,
@@ -154,9 +158,9 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
154
158
sp : Span ,
155
159
name : ast:: Ident ,
156
160
imported_from : Option < ast:: Ident > ,
157
- arg : & [ ast :: TokenTree ] ,
158
- lhses : & [ Rc < NamedMatch > ] ,
159
- rhses : & [ Rc < NamedMatch > ] )
161
+ arg : & [ TokenTree ] ,
162
+ lhses : & [ TokenTree ] ,
163
+ rhses : & [ TokenTree ] )
160
164
-> Box < MacResult +' cx > {
161
165
if cx. trace_macros ( ) {
162
166
println ! ( "{}! {{ {} }}" ,
@@ -169,25 +173,17 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
169
173
let mut best_fail_msg = "internal error: ran no matchers" . to_string ( ) ;
170
174
171
175
for ( i, lhs) in lhses. iter ( ) . enumerate ( ) { // try each arm's matchers
172
- match * * lhs {
173
- MatchedNonterminal ( NtTT ( ref lhs_tt) ) => {
174
- let lhs_tt = match * * lhs_tt {
175
- TokenTree :: Delimited ( _, ref delim) => & delim. tts [ ..] ,
176
- _ => panic ! ( cx. span_fatal( sp, "malformed macro lhs" ) )
177
- } ;
178
-
179
- match TokenTree :: parse ( cx, lhs_tt, arg) {
180
- Success ( named_matches) => {
181
- let rhs = match * rhses[ i] {
182
- // okay, what's your transcriber?
183
- MatchedNonterminal ( NtTT ( ref tt) ) => {
184
- match * * tt {
185
- // ignore delimiters
186
- TokenTree :: Delimited ( _, ref delimed) => delimed. tts . clone ( ) ,
187
- _ => panic ! ( cx. span_fatal( sp, "macro rhs must be delimited" ) ) ,
188
- }
189
- } ,
190
- _ => cx. span_bug ( sp, "bad thing in rhs" )
176
+ let lhs_tt = match * lhs {
177
+ TokenTree :: Delimited ( _, ref delim) => & delim. tts [ ..] ,
178
+ _ => cx. span_bug ( sp, "malformed macro lhs" )
179
+ } ;
180
+
181
+ match TokenTree :: parse ( cx, lhs_tt, arg) {
182
+ Success ( named_matches) => {
183
+ let rhs = match rhses[ i] {
184
+ // ignore delimiters
185
+ TokenTree :: Delimited ( _, ref delimed) => delimed. tts . clone ( ) ,
186
+ _ => cx. span_bug ( sp, "malformed macro rhs" ) ,
191
187
} ;
192
188
// rhs has holes ( `$id` and `$(...)` that need filled)
193
189
let trncbr = new_tt_reader ( & cx. parse_sess ( ) . span_diagnostic ,
@@ -207,17 +203,14 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
207
203
site_span : sp,
208
204
macro_ident : name
209
205
} )
210
- }
211
- Failure ( sp, ref msg) => if sp. lo >= best_fail_spot. lo {
206
+ }
207
+ Failure ( sp, ref msg) => if sp. lo >= best_fail_spot. lo {
212
208
best_fail_spot = sp;
213
209
best_fail_msg = ( * msg) . clone ( ) ;
214
- } ,
215
- Error ( err_sp, ref msg) => {
210
+ } ,
211
+ Error ( err_sp, ref msg) => {
216
212
panic ! ( cx. span_fatal( err_sp. substitute_dummy( sp) , & msg[ ..] ) )
217
- }
218
213
}
219
- }
220
- _ => cx. bug ( "non-matcher found in parsed lhses" )
221
214
}
222
215
}
223
216
@@ -282,9 +275,16 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
282
275
}
283
276
} ;
284
277
278
+ let mut valid = true ;
279
+
285
280
// Extract the arguments:
286
281
let lhses = match * * argument_map. get ( & lhs_nm. name ) . unwrap ( ) {
287
- MatchedSeq ( ref s, _) => /* FIXME (#2543) */ ( * s) . clone ( ) ,
282
+ MatchedSeq ( ref s, _) => {
283
+ s. iter ( ) . map ( |m| match * * m {
284
+ MatchedNonterminal ( NtTT ( ref tt) ) => ( * * tt) . clone ( ) ,
285
+ _ => cx. span_bug ( def. span , "wrong-structured lhs" )
286
+ } ) . collect ( )
287
+ }
288
288
_ => cx. span_bug ( def. span , "wrong-structured lhs" )
289
289
} ;
290
290
@@ -293,41 +293,55 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
293
293
}
294
294
295
295
let rhses = match * * argument_map. get ( & rhs_nm. name ) . unwrap ( ) {
296
- MatchedSeq ( ref s, _) => /* FIXME (#2543) */ ( * s) . clone ( ) ,
296
+ MatchedSeq ( ref s, _) => {
297
+ s. iter ( ) . map ( |m| match * * m {
298
+ MatchedNonterminal ( NtTT ( ref tt) ) => ( * * tt) . clone ( ) ,
299
+ _ => cx. span_bug ( def. span , "wrong-structured rhs" )
300
+ } ) . collect ( )
301
+ }
297
302
_ => cx. span_bug ( def. span , "wrong-structured rhs" )
298
303
} ;
299
304
305
+ for rhs in & rhses {
306
+ valid &= check_rhs ( cx, rhs) ;
307
+ }
308
+
300
309
let exp: Box < _ > = Box :: new ( MacroRulesMacroExpander {
301
310
name : def. ident ,
302
311
imported_from : def. imported_from ,
303
312
lhses : lhses,
304
313
rhses : rhses,
314
+ valid : valid,
305
315
} ) ;
306
316
307
317
NormalTT ( exp, Some ( def. span ) , def. allow_internal_unstable )
308
318
}
309
319
310
- fn check_lhs_nt_follows ( cx : & mut ExtCtxt , lhs : & NamedMatch , sp : Span ) {
311
- // lhs is going to be like MatchedNonterminal(NtTT( TokenTree::Delimited(...)) ), where the
320
+ fn check_lhs_nt_follows ( cx : & mut ExtCtxt , lhs : & TokenTree , sp : Span ) {
321
+ // lhs is going to be like TokenTree::Delimited(...), where the
312
322
// entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
313
323
match lhs {
314
- & MatchedNonterminal ( NtTT ( ref inner) ) => match & * * inner {
315
- & TokenTree :: Delimited ( _, ref tts) => {
316
- check_matcher ( cx, tts. tts . iter ( ) , & Eof ) ;
317
- } ,
318
- tt @ & TokenTree :: Sequence ( ..) => {
319
- check_matcher ( cx, Some ( tt) . into_iter ( ) , & Eof ) ;
320
- } ,
321
- _ => cx. span_err ( sp, "Invalid macro matcher; matchers must be contained \
322
- in balanced delimiters or a repetition indicator")
324
+ & TokenTree :: Delimited ( _, ref tts) => {
325
+ check_matcher ( cx, tts. tts . iter ( ) , & Eof ) ;
323
326
} ,
324
- _ => cx. span_bug ( sp, "wrong-structured lhs for follow check (didn't find a \
325
- MatchedNonterminal)")
327
+ tt @ & TokenTree :: Sequence ( ..) => {
328
+ check_matcher ( cx, Some ( tt) . into_iter ( ) , & Eof ) ;
329
+ } ,
330
+ _ => cx. span_err ( sp, "Invalid macro matcher; matchers must be contained \
331
+ in balanced delimiters or a repetition indicator")
326
332
} ;
327
333
// we don't abort on errors on rejection, the driver will do that for us
328
334
// after parsing/expansion. we can report every error in every macro this way.
329
335
}
330
336
337
+ fn check_rhs ( cx : & mut ExtCtxt , rhs : & TokenTree ) -> bool {
338
+ match * rhs {
339
+ TokenTree :: Delimited ( ..) => return true ,
340
+ _ => cx. span_err ( rhs. get_span ( ) , "macro rhs must be delimited" )
341
+ }
342
+ false
343
+ }
344
+
331
345
// returns the last token that was checked, for TokenTree::Sequence. this gets used later on.
332
346
fn check_matcher < ' a , I > ( cx : & mut ExtCtxt , matcher : I , follow : & Token )
333
347
-> Option < ( Span , Token ) > where I : Iterator < Item =& ' a TokenTree > {
0 commit comments