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
16
use ext:: tt:: macro_parser:: { MatchedSeq , MatchedNonterminal } ;
@@ -131,6 +131,7 @@ struct MacroRulesMacroExpander {
131
131
imported_from : Option < ast:: Ident > ,
132
132
lhses : Vec < TokenTree > ,
133
133
rhses : Vec < TokenTree > ,
134
+ valid : bool ,
134
135
}
135
136
136
137
impl TTMacroExpander for MacroRulesMacroExpander {
@@ -139,6 +140,9 @@ impl TTMacroExpander for MacroRulesMacroExpander {
139
140
sp : Span ,
140
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 ,
@@ -171,15 +175,15 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
171
175
for ( i, lhs) in lhses. iter ( ) . enumerate ( ) { // try each arm's matchers
172
176
let lhs_tt = match * lhs {
173
177
TokenTree :: Delimited ( _, ref delim) => & delim. tts [ ..] ,
174
- _ => panic ! ( cx. span_fatal ( sp, "malformed macro lhs" ) )
178
+ _ => cx. span_bug ( sp, "malformed macro lhs" )
175
179
} ;
176
180
177
181
match TokenTree :: parse ( cx, lhs_tt, arg) {
178
182
Success ( named_matches) => {
179
183
let rhs = match rhses[ i] {
180
184
// ignore delimiters
181
185
TokenTree :: Delimited ( _, ref delimed) => delimed. tts . clone ( ) ,
182
- _ => panic ! ( cx. span_fatal ( sp, "macro rhs must be delimited" ) ) ,
186
+ _ => cx. span_bug ( sp, "malformed macro rhs" ) ,
183
187
} ;
184
188
// rhs has holes ( `$id` and `$(...)` that need filled)
185
189
let trncbr = new_tt_reader ( & cx. parse_sess ( ) . span_diagnostic ,
@@ -271,6 +275,8 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
271
275
}
272
276
} ;
273
277
278
+ let mut valid = true ;
279
+
274
280
// Extract the arguments:
275
281
let lhses = match * * argument_map. get ( & lhs_nm. name ) . unwrap ( ) {
276
282
MatchedSeq ( ref s, _) => {
@@ -296,11 +302,16 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
296
302
_ => cx. span_bug ( def. span , "wrong-structured rhs" )
297
303
} ;
298
304
305
+ for rhs in & rhses {
306
+ valid &= check_rhs ( cx, rhs) ;
307
+ }
308
+
299
309
let exp: Box < _ > = Box :: new ( MacroRulesMacroExpander {
300
310
name : def. ident ,
301
311
imported_from : def. imported_from ,
302
312
lhses : lhses,
303
313
rhses : rhses,
314
+ valid : valid,
304
315
} ) ;
305
316
306
317
NormalTT ( exp, Some ( def. span ) , def. allow_internal_unstable )
@@ -323,6 +334,14 @@ fn check_lhs_nt_follows(cx: &mut ExtCtxt, lhs: &TokenTree, sp: Span) {
323
334
// after parsing/expansion. we can report every error in every macro this way.
324
335
}
325
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
+
326
345
// returns the last token that was checked, for TokenTree::Sequence. this gets used later on.
327
346
fn check_matcher < ' a , I > ( cx : & mut ExtCtxt , matcher : I , follow : & Token )
328
347
-> Option < ( Span , Token ) > where I : Iterator < Item =& ' a TokenTree > {
0 commit comments