@@ -21,22 +21,47 @@ use ext::tt::macro_parser::{parse, parse_or_else, success, failure};
2121use parse:: lexer:: { new_tt_reader, reader} ;
2222use parse:: parser:: Parser ;
2323use parse:: token:: { get_ident_interner, special_idents, gensym_ident, ident_to_str} ;
24- use parse:: token:: { FAT_ARROW , SEMI , nt_matchers, nt_tt} ;
24+ use parse:: token:: { FAT_ARROW , SEMI , nt_matchers, nt_tt, EOF } ;
2525use print;
2626
2727struct ParserAnyMacro {
2828 parser : @Parser ,
2929}
3030
31+ impl ParserAnyMacro {
32+ /// Make sure we don't have any tokens left to parse, so we don't
33+ /// silently drop anything. `allow_semi` is so that "optional"
34+ /// semilons at the end of normal expressions aren't complained
35+ /// about e.g. the semicolon in `macro_rules! kapow( () => {
36+ /// fail!(); } )` doesn't get picked up by .parse_expr(), but it's
37+ /// allowed to be there.
38+ fn ensure_complete_parse ( & self , allow_semi : bool ) {
39+ if allow_semi && * self . parser . token == SEMI {
40+ self . parser . bump ( )
41+ }
42+ if * self . parser . token != EOF {
43+ let msg = format ! ( "macro expansion ignores token `{}` and any following" ,
44+ self . parser. this_token_to_str( ) ) ;
45+ self . parser . span_err ( * self . parser . span , msg) ;
46+ }
47+ }
48+ }
49+
3150impl AnyMacro for ParserAnyMacro {
3251 fn make_expr ( & self ) -> @ast:: Expr {
33- self . parser . parse_expr ( )
52+ let ret = self . parser . parse_expr ( ) ;
53+ self . ensure_complete_parse ( true ) ;
54+ ret
3455 }
3556 fn make_item ( & self ) -> Option < @ast:: item > {
36- self . parser . parse_item ( ~[ ] ) // no attrs
57+ let ret = self . parser . parse_item ( ~[ ] ) ; // no attrs
58+ self . ensure_complete_parse ( false ) ;
59+ ret
3760 }
3861 fn make_stmt ( & self ) -> @ast:: Stmt {
39- self . parser . parse_stmt ( ~[ ] ) // no attrs
62+ let ret = self . parser . parse_stmt ( ~[ ] ) ; // no attrs
63+ self . ensure_complete_parse ( true ) ;
64+ ret
4065 }
4166}
4267
@@ -185,79 +210,6 @@ pub fn add_new_extension(cx: @ExtCtxt,
185210 _ => cx. span_bug ( sp, "wrong-structured rhs" )
186211 } ;
187212
188- // Given `lhses` and `rhses`, this is the new macro we create
189- fn generic_extension ( cx : @ExtCtxt ,
190- sp : Span ,
191- name : Ident ,
192- arg : & [ ast:: token_tree ] ,
193- lhses : & [ @named_match ] ,
194- rhses : & [ @named_match ] )
195- -> MacResult {
196- if cx. trace_macros ( ) {
197- println ! ( "{}! \\ { {} \\ }" ,
198- cx. str_of( name) ,
199- print:: pprust:: tt_to_str(
200- & ast:: tt_delim( @mut arg. to_owned( ) ) ,
201- get_ident_interner( ) ) ) ;
202- }
203-
204- // Which arm's failure should we report? (the one furthest along)
205- let mut best_fail_spot = dummy_sp ( ) ;
206- let mut best_fail_msg = ~"internal error: ran no matchers";
207-
208- let s_d = cx. parse_sess ( ) . span_diagnostic ;
209-
210- for ( i, lhs) in lhses. iter ( ) . enumerate ( ) { // try each arm's matchers
211- match * lhs {
212- @matched_nonterminal( nt_matchers( ref mtcs) ) => {
213- // `none` is because we're not interpolating
214- let arg_rdr = new_tt_reader (
215- s_d,
216- None ,
217- arg. to_owned ( )
218- ) as @mut reader ;
219- match parse ( cx. parse_sess ( ) , cx. cfg ( ) , arg_rdr, * mtcs) {
220- success( named_matches) => {
221- let rhs = match rhses[ i] {
222- // okay, what's your transcriber?
223- @matched_nonterminal( nt_tt( @ref tt) ) => {
224- match ( * tt) {
225- // cut off delimiters; don't parse 'em
226- tt_delim( ref tts) => {
227- ( * tts) . slice ( 1 u, ( * tts) . len ( ) -1 u) . to_owned ( )
228- }
229- _ => cx. span_fatal (
230- sp, "macro rhs must be delimited" )
231- }
232- } ,
233- _ => cx. span_bug ( sp, "bad thing in rhs" )
234- } ;
235- // rhs has holes ( `$id` and `$(...)` that need filled)
236- let trncbr = new_tt_reader ( s_d, Some ( named_matches) ,
237- rhs) ;
238- let p = @Parser ( cx. parse_sess ( ) ,
239- cx. cfg ( ) ,
240- trncbr as @mut reader ) ;
241-
242- // Let the context choose how to interpret the result.
243- // Weird, but useful for X-macros.
244- return MRAny ( @ParserAnyMacro {
245- parser : p
246- } as @AnyMacro ) ;
247- }
248- failure( sp, ref msg) => if sp. lo >= best_fail_spot. lo {
249- best_fail_spot = sp;
250- best_fail_msg = ( * msg) . clone ( ) ;
251- } ,
252- error( sp, ref msg) => cx. span_fatal ( sp, ( * msg) )
253- }
254- }
255- _ => cx. bug ( "non-matcher found in parsed lhses" )
256- }
257- }
258- cx. span_fatal ( best_fail_spot, best_fail_msg) ;
259- }
260-
261213 let exp = @MacroRulesSyntaxExpanderTTFun {
262214 name : name,
263215 lhses : lhses,
0 commit comments