9
9
// except according to those terms.
10
10
11
11
use ast:: { Block , Crate , Ident , Mac_ , PatKind } ;
12
- use ast:: { MacStmtStyle , StmtKind , ItemKind } ;
12
+ use ast:: { Name , MacStmtStyle , StmtKind , ItemKind } ;
13
13
use ast;
14
14
use ext:: hygiene:: Mark ;
15
15
use ext:: placeholders:: { placeholder, PlaceholderExpander } ;
@@ -21,9 +21,9 @@ use ext::base::*;
21
21
use feature_gate:: { self , Features } ;
22
22
use fold;
23
23
use fold:: * ;
24
- use parse:: { ParseSess , lexer} ;
24
+ use parse:: { ParseSess , PResult , lexer} ;
25
25
use parse:: parser:: Parser ;
26
- use parse:: token:: { intern, keywords} ;
26
+ use parse:: token:: { self , intern, keywords} ;
27
27
use print:: pprust;
28
28
use ptr:: P ;
29
29
use tokenstream:: { TokenTree , TokenStream } ;
@@ -38,12 +38,12 @@ macro_rules! expansions {
38
38
( $( $kind: ident: $ty: ty [ $( $vec: ident, $ty_elt: ty) * ] , $kind_name: expr, . $make: ident,
39
39
$( . $fold: ident) * $( lift . $fold_elt: ident) * ,
40
40
$( . $visit: ident) * $( lift . $visit_elt: ident) * ; ) * ) => {
41
- #[ derive( Copy , Clone ) ]
41
+ #[ derive( Copy , Clone , PartialEq , Eq ) ]
42
42
pub enum ExpansionKind { OptExpr , $( $kind, ) * }
43
43
pub enum Expansion { OptExpr ( Option <P <ast:: Expr >>) , $( $kind( $ty) , ) * }
44
44
45
45
impl ExpansionKind {
46
- fn name( self ) -> & ' static str {
46
+ pub fn name( self ) -> & ' static str {
47
47
match self {
48
48
ExpansionKind :: OptExpr => "expression" ,
49
49
$( ExpansionKind :: $kind => $kind_name, ) *
@@ -106,6 +106,12 @@ macro_rules! expansions {
106
106
self . expand( Expansion :: $kind( SmallVector :: one( node) ) ) . $make( )
107
107
} ) * ) *
108
108
}
109
+
110
+ impl <' a> MacResult for :: ext:: tt:: macro_rules:: ParserAnyMacro <' a> {
111
+ $( fn $make( self : Box <:: ext:: tt:: macro_rules:: ParserAnyMacro <' a>>) -> Option <$ty> {
112
+ Some ( self . make( ExpansionKind :: $kind) . $make( ) )
113
+ } ) *
114
+ }
109
115
}
110
116
}
111
117
@@ -293,10 +299,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
293
299
} ;
294
300
295
301
attr:: mark_used ( & attr) ;
302
+ let name = intern ( & attr. name ( ) ) ;
296
303
self . cx . bt_push ( ExpnInfo {
297
304
call_site : attr. span ,
298
305
callee : NameAndSpan {
299
- format : MacroAttribute ( intern ( & attr . name ( ) ) ) ,
306
+ format : MacroAttribute ( name) ,
300
307
span : Some ( attr. span ) ,
301
308
allow_internal_unstable : false ,
302
309
}
@@ -319,14 +326,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
319
326
let item_toks = TokenStream :: from_tts ( tts_for_item ( & item, & self . cx . parse_sess ) ) ;
320
327
321
328
let tok_result = mac. expand ( self . cx , attr. span , attr_toks, item_toks) ;
322
- let parser = self . cx . new_parser_from_tts ( & tok_result. to_tts ( ) ) ;
323
- let result = Box :: new ( TokResult { parser : parser, span : attr. span } ) ;
324
-
325
- kind. make_from ( result) . unwrap_or_else ( || {
326
- let msg = format ! ( "macro could not be expanded into {} position" , kind. name( ) ) ;
327
- self . cx . span_err ( attr. span , & msg) ;
328
- kind. dummy ( attr. span )
329
- } )
329
+ self . parse_expansion ( tok_result, kind, name, attr. span )
330
330
}
331
331
_ => unreachable ! ( ) ,
332
332
}
@@ -423,14 +423,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
423
423
} ,
424
424
} ) ;
425
425
426
-
427
- let tok_result = expandfun. expand ( self . cx ,
428
- span,
429
- TokenStream :: from_tts ( marked_tts) ) ;
430
- let parser = self . cx . new_parser_from_tts ( & tok_result. to_tts ( ) ) ;
431
- let result = Box :: new ( TokResult { parser : parser, span : span } ) ;
432
- // FIXME better span info.
433
- kind. make_from ( result) . map ( |i| i. fold_with ( & mut ChangeSpan { span : span } ) )
426
+ let toks = TokenStream :: from_tts ( marked_tts) ;
427
+ let tok_result = expandfun. expand ( self . cx , span, toks) ;
428
+ Some ( self . parse_expansion ( tok_result, kind, extname, span) )
434
429
}
435
430
} ;
436
431
@@ -448,6 +443,75 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
448
443
expn_id : Some ( self . cx . backtrace ( ) ) ,
449
444
} )
450
445
}
446
+
447
+ fn parse_expansion ( & mut self , toks : TokenStream , kind : ExpansionKind , name : Name , span : Span )
448
+ -> Expansion {
449
+ let mut parser = self . cx . new_parser_from_tts ( & toks. to_tts ( ) ) ;
450
+ let expansion = match parser. parse_expansion ( kind, false ) {
451
+ Ok ( expansion) => expansion,
452
+ Err ( mut err) => {
453
+ err. emit ( ) ;
454
+ return kind. dummy ( span) ;
455
+ }
456
+ } ;
457
+ parser. ensure_complete_parse ( name, kind. name ( ) , span) ;
458
+ // FIXME better span info
459
+ expansion. fold_with ( & mut ChangeSpan { span : span } )
460
+ }
461
+ }
462
+
463
+ impl < ' a > Parser < ' a > {
464
+ pub fn parse_expansion ( & mut self , kind : ExpansionKind , macro_legacy_warnings : bool )
465
+ -> PResult < ' a , Expansion > {
466
+ Ok ( match kind {
467
+ ExpansionKind :: Items => {
468
+ let mut items = SmallVector :: zero ( ) ;
469
+ while let Some ( item) = self . parse_item ( ) ? {
470
+ items. push ( item) ;
471
+ }
472
+ Expansion :: Items ( items)
473
+ }
474
+ ExpansionKind :: TraitItems => {
475
+ let mut items = SmallVector :: zero ( ) ;
476
+ while self . token != token:: Eof {
477
+ items. push ( self . parse_trait_item ( ) ?) ;
478
+ }
479
+ Expansion :: TraitItems ( items)
480
+ }
481
+ ExpansionKind :: ImplItems => {
482
+ let mut items = SmallVector :: zero ( ) ;
483
+ while self . token != token:: Eof {
484
+ items. push ( self . parse_impl_item ( ) ?) ;
485
+ }
486
+ Expansion :: ImplItems ( items)
487
+ }
488
+ ExpansionKind :: Stmts => {
489
+ let mut stmts = SmallVector :: zero ( ) ;
490
+ while self . token != token:: Eof {
491
+ if let Some ( stmt) = self . parse_full_stmt ( macro_legacy_warnings) ? {
492
+ stmts. push ( stmt) ;
493
+ }
494
+ }
495
+ Expansion :: Stmts ( stmts)
496
+ }
497
+ ExpansionKind :: Expr => Expansion :: Expr ( self . parse_expr ( ) ?) ,
498
+ ExpansionKind :: OptExpr => Expansion :: OptExpr ( Some ( self . parse_expr ( ) ?) ) ,
499
+ ExpansionKind :: Ty => Expansion :: Ty ( self . parse_ty ( ) ?) ,
500
+ ExpansionKind :: Pat => Expansion :: Pat ( self . parse_pat ( ) ?) ,
501
+ } )
502
+ }
503
+
504
+ pub fn ensure_complete_parse ( & mut self , macro_name : ast:: Name , kind_name : & str , span : Span ) {
505
+ if self . token != token:: Eof {
506
+ let msg = format ! ( "macro expansion ignores token `{}` and any following" ,
507
+ self . this_token_to_string( ) ) ;
508
+ let mut err = self . diagnostic ( ) . struct_span_err ( self . span , & msg) ;
509
+ let msg = format ! ( "caused by the macro expansion here; the usage \
510
+ of `{}!` is likely invalid in {} context",
511
+ macro_name, kind_name) ;
512
+ err. span_note ( span, & msg) . emit ( ) ;
513
+ }
514
+ }
451
515
}
452
516
453
517
struct InvocationCollector < ' a , ' b : ' a > {
0 commit comments