@@ -21,22 +21,47 @@ use ext::tt::macro_parser::{parse, parse_or_else, success, failure};
21
21
use parse:: lexer:: { new_tt_reader, reader} ;
22
22
use parse:: parser:: Parser ;
23
23
use 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 } ;
25
25
use print;
26
26
27
27
struct ParserAnyMacro {
28
28
parser : @Parser ,
29
29
}
30
30
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
+
31
50
impl AnyMacro for ParserAnyMacro {
32
51
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
34
55
}
35
56
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
37
60
}
38
61
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
40
65
}
41
66
}
42
67
@@ -185,79 +210,6 @@ pub fn add_new_extension(cx: @ExtCtxt,
185
210
_ => cx. span_bug ( sp, "wrong-structured rhs" )
186
211
} ;
187
212
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
-
261
213
let exp = @MacroRulesSyntaxExpanderTTFun {
262
214
name : name,
263
215
lhses : lhses,
0 commit comments