1010
1111use ast:: { self , TokenTree } ;
1212use codemap:: { Span , DUMMY_SP } ;
13- use ext:: base:: { ExtCtxt , MacResult , SyntaxExtension } ;
13+ use ext:: base:: { DummyResult , ExtCtxt , MacResult , SyntaxExtension } ;
1414use ext:: base:: { NormalTT , TTMacroExpander } ;
1515use ext:: tt:: macro_parser:: { Success , Error , Failure } ;
16- use ext:: tt:: macro_parser:: { NamedMatch , MatchedSeq , MatchedNonterminal } ;
16+ use ext:: tt:: macro_parser:: { MatchedSeq , MatchedNonterminal } ;
1717use ext:: tt:: macro_parser:: parse;
1818use parse:: lexer:: new_tt_reader;
1919use parse:: parser:: Parser ;
@@ -129,16 +129,20 @@ impl<'a> MacResult for ParserAnyMacro<'a> {
129129struct MacroRulesMacroExpander {
130130 name : ast:: Ident ,
131131 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 ,
134135}
135136
136137impl TTMacroExpander for MacroRulesMacroExpander {
137138 fn expand < ' cx > ( & self ,
138139 cx : & ' cx mut ExtCtxt ,
139140 sp : Span ,
140- arg : & [ ast :: TokenTree ] )
141+ arg : & [ TokenTree ] )
141142 -> Box < MacResult +' cx > {
143+ if !self . valid {
144+ return DummyResult :: any ( sp) ;
145+ }
142146 generic_extension ( cx,
143147 sp,
144148 self . name ,
@@ -154,9 +158,9 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
154158 sp : Span ,
155159 name : ast:: Ident ,
156160 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 ] )
160164 -> Box < MacResult +' cx > {
161165 if cx. trace_macros ( ) {
162166 println ! ( "{}! {{ {} }}" ,
@@ -169,25 +173,17 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
169173 let mut best_fail_msg = "internal error: ran no matchers" . to_string ( ) ;
170174
171175 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" ) ,
191187 } ;
192188 // rhs has holes ( `$id` and `$(...)` that need filled)
193189 let trncbr = new_tt_reader ( & cx. parse_sess ( ) . span_diagnostic ,
@@ -207,17 +203,14 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
207203 site_span : sp,
208204 macro_ident : name
209205 } )
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 {
212208 best_fail_spot = sp;
213209 best_fail_msg = ( * msg) . clone ( ) ;
214- } ,
215- Error ( err_sp, ref msg) => {
210+ } ,
211+ Error ( err_sp, ref msg) => {
216212 panic ! ( cx. span_fatal( err_sp. substitute_dummy( sp) , & msg[ ..] ) )
217- }
218213 }
219- }
220- _ => cx. bug ( "non-matcher found in parsed lhses" )
221214 }
222215 }
223216
@@ -282,9 +275,16 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
282275 }
283276 } ;
284277
278+ let mut valid = true ;
279+
285280 // Extract the arguments:
286281 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+ }
288288 _ => cx. span_bug ( def. span , "wrong-structured lhs" )
289289 } ;
290290
@@ -293,41 +293,55 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
293293 }
294294
295295 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+ }
297302 _ => cx. span_bug ( def. span , "wrong-structured rhs" )
298303 } ;
299304
305+ for rhs in & rhses {
306+ valid &= check_rhs ( cx, rhs) ;
307+ }
308+
300309 let exp: Box < _ > = Box :: new ( MacroRulesMacroExpander {
301310 name : def. ident ,
302311 imported_from : def. imported_from ,
303312 lhses : lhses,
304313 rhses : rhses,
314+ valid : valid,
305315 } ) ;
306316
307317 NormalTT ( exp, Some ( def. span ) , def. allow_internal_unstable )
308318}
309319
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
312322 // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
313323 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 ) ;
323326 } ,
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")
326332 } ;
327333 // we don't abort on errors on rejection, the driver will do that for us
328334 // after parsing/expansion. we can report every error in every macro this way.
329335}
330336
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+
331345// returns the last token that was checked, for TokenTree::Sequence. this gets used later on.
332346fn check_matcher < ' a , I > ( cx : & mut ExtCtxt , matcher : I , follow : & Token )
333347-> Option < ( Span , Token ) > where I : Iterator < Item =& ' a TokenTree > {
0 commit comments