1- // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+ // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
22// file at the top-level directory of this distribution and at
33// http://rust-lang.org/COPYRIGHT.
44//
@@ -401,7 +401,7 @@ pub fn expand_quote_tokens<'cx>(cx: &'cx mut ExtCtxt,
401401 tts : & [ ast:: TokenTree ] )
402402 -> Box < base:: MacResult +' cx > {
403403 let ( cx_expr, expr) = expand_tts ( cx, sp, tts) ;
404- let expanded = expand_wrapper ( cx, sp, cx_expr, expr) ;
404+ let expanded = expand_wrapper ( cx, sp, cx_expr, expr, & [ & [ "syntax" , "ext" , "quote" , "rt" ] ] ) ;
405405 base:: MacEager :: expr ( expanded)
406406}
407407
@@ -465,6 +465,32 @@ pub fn expand_quote_stmt(cx: &mut ExtCtxt,
465465 base:: MacEager :: expr ( expanded)
466466}
467467
468+ pub fn expand_quote_attr ( cx : & mut ExtCtxt ,
469+ sp : Span ,
470+ tts : & [ ast:: TokenTree ] )
471+ -> Box < base:: MacResult +' static > {
472+ let expanded = expand_parse_call ( cx, sp, "parse_attribute" ,
473+ vec ! ( cx. expr_bool( sp, true ) ) , tts) ;
474+
475+ base:: MacEager :: expr ( expanded)
476+ }
477+
478+ pub fn expand_quote_matcher ( cx : & mut ExtCtxt ,
479+ sp : Span ,
480+ tts : & [ ast:: TokenTree ] )
481+ -> Box < base:: MacResult +' static > {
482+ let ( cx_expr, tts) = parse_arguments_to_quote ( cx, tts) ;
483+ let mut vector = mk_stmts_let ( cx, sp) ;
484+ vector. extend ( statements_mk_tts ( cx, & tts[ ..] , true ) . into_iter ( ) ) ;
485+ let block = cx. expr_block (
486+ cx. block_all ( sp,
487+ vector,
488+ Some ( cx. expr_ident ( sp, id_ext ( "tt" ) ) ) ) ) ;
489+
490+ let expanded = expand_wrapper ( cx, sp, cx_expr, block, & [ & [ "syntax" , "ext" , "quote" , "rt" ] ] ) ;
491+ base:: MacEager :: expr ( expanded)
492+ }
493+
468494fn ids_ext ( strs : Vec < String > ) -> Vec < ast:: Ident > {
469495 strs. iter ( ) . map ( |str| str_to_ident ( & ( * str) ) ) . collect ( )
470496}
@@ -527,7 +553,7 @@ fn mk_delim(cx: &ExtCtxt, sp: Span, delim: token::DelimToken) -> P<ast::Expr> {
527553}
528554
529555#[ allow( non_upper_case_globals) ]
530- fn mk_token ( cx : & ExtCtxt , sp : Span , tok : & token:: Token ) -> P < ast:: Expr > {
556+ fn expr_mk_token ( cx : & ExtCtxt , sp : Span , tok : & token:: Token ) -> P < ast:: Expr > {
531557 macro_rules! mk_lit {
532558 ( $name: expr, $suffix: expr, $( $args: expr) ,* ) => { {
533559 let inner = cx. expr_call( sp, mk_token_path( cx, sp, $name) , vec![ $( $args) ,* ] ) ;
@@ -606,6 +632,21 @@ fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
606632 vec ! ( mk_name( cx, sp, ident. ident( ) ) ) ) ;
607633 }
608634
635+ token:: MatchNt ( name, kind, namep, kindp) => {
636+ return cx. expr_call ( sp,
637+ mk_token_path ( cx, sp, "MatchNt" ) ,
638+ vec ! ( mk_ident( cx, sp, name) ,
639+ mk_ident( cx, sp, kind) ,
640+ match namep {
641+ ModName => mk_token_path( cx, sp, "ModName" ) ,
642+ Plain => mk_token_path( cx, sp, "Plain" ) ,
643+ } ,
644+ match kindp {
645+ ModName => mk_token_path( cx, sp, "ModName" ) ,
646+ Plain => mk_token_path( cx, sp, "Plain" ) ,
647+ } ) ) ;
648+ }
649+
609650 token:: Interpolated ( _) => panic ! ( "quote! with interpolated token" ) ,
610651
611652 _ => ( )
@@ -642,7 +683,7 @@ fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
642683 mk_token_path ( cx, sp, name)
643684}
644685
645- fn mk_tt ( cx : & ExtCtxt , tt : & ast:: TokenTree ) -> Vec < P < ast:: Stmt > > {
686+ fn statements_mk_tt ( cx : & ExtCtxt , tt : & ast:: TokenTree , matcher : bool ) -> Vec < P < ast:: Stmt > > {
646687 match * tt {
647688 ast:: TtToken ( sp, SubstNt ( ident, _) ) => {
648689 // tt.extend($ident.to_tokens(ext_cx).into_iter())
@@ -663,18 +704,18 @@ fn mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree) -> Vec<P<ast::Stmt>> {
663704
664705 vec ! ( cx. stmt_expr( e_push) )
665706 }
666- ref tt @ ast:: TtToken ( _, MatchNt ( ..) ) => {
707+ ref tt @ ast:: TtToken ( _, MatchNt ( ..) ) if !matcher => {
667708 let mut seq = vec ! [ ] ;
668709 for i in 0 ..tt. len ( ) {
669710 seq. push ( tt. get_tt ( i) ) ;
670711 }
671- mk_tts ( cx, & seq[ ..] )
712+ statements_mk_tts ( cx, & seq[ ..] , matcher )
672713 }
673714 ast:: TtToken ( sp, ref tok) => {
674715 let e_sp = cx. expr_ident ( sp, id_ext ( "_sp" ) ) ;
675716 let e_tok = cx. expr_call ( sp,
676717 mk_ast_path ( cx, sp, "TtToken" ) ,
677- vec ! ( e_sp, mk_token ( cx, sp, tok) ) ) ;
718+ vec ! ( e_sp, expr_mk_token ( cx, sp, tok) ) ) ;
678719 let e_push =
679720 cx. expr_method_call ( sp,
680721 cx. expr_ident ( sp, id_ext ( "tt" ) ) ,
@@ -683,27 +724,61 @@ fn mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree) -> Vec<P<ast::Stmt>> {
683724 vec ! ( cx. stmt_expr( e_push) )
684725 } ,
685726 ast:: TtDelimited ( _, ref delimed) => {
686- mk_tt ( cx, & delimed. open_tt ( ) ) . into_iter ( )
687- . chain ( delimed. tts . iter ( ) . flat_map ( |tt| mk_tt ( cx, tt) . into_iter ( ) ) )
688- . chain ( mk_tt ( cx, & delimed. close_tt ( ) ) . into_iter ( ) )
727+ statements_mk_tt ( cx, & delimed. open_tt ( ) , matcher) . into_iter ( )
728+ . chain ( delimed. tts . iter ( )
729+ . flat_map ( |tt| statements_mk_tt ( cx, tt, matcher) . into_iter ( ) ) )
730+ . chain ( statements_mk_tt ( cx, & delimed. close_tt ( ) , matcher) . into_iter ( ) )
689731 . collect ( )
690732 } ,
691- ast:: TtSequence ( ..) => panic ! ( "TtSequence in quote!" ) ,
692- }
693- }
733+ ast:: TtSequence ( sp, ref seq) => {
734+ if !matcher {
735+ panic ! ( "TtSequence in quote!" ) ;
736+ }
694737
695- fn mk_tts ( cx : & ExtCtxt , tts : & [ ast:: TokenTree ] ) -> Vec < P < ast:: Stmt > > {
696- let mut ss = Vec :: new ( ) ;
697- for tt in tts {
698- ss. extend ( mk_tt ( cx, tt) . into_iter ( ) ) ;
738+ let e_sp = cx. expr_ident ( sp, id_ext ( "_sp" ) ) ;
739+
740+ let stmt_let_tt = cx. stmt_let ( sp, true , id_ext ( "tt" ) , cx. expr_vec_ng ( sp) ) ;
741+ let mut tts_stmts = vec ! [ stmt_let_tt] ;
742+ tts_stmts. extend ( statements_mk_tts ( cx, & seq. tts [ ..] , matcher) . into_iter ( ) ) ;
743+ let e_tts = cx. expr_block ( cx. block ( sp, tts_stmts,
744+ Some ( cx. expr_ident ( sp, id_ext ( "tt" ) ) ) ) ) ;
745+ let e_separator = match seq. separator {
746+ Some ( ref sep) => cx. expr_some ( sp, expr_mk_token ( cx, sp, sep) ) ,
747+ None => cx. expr_none ( sp) ,
748+ } ;
749+ let e_op = match seq. op {
750+ ast:: ZeroOrMore => mk_ast_path ( cx, sp, "ZeroOrMore" ) ,
751+ ast:: OneOrMore => mk_ast_path ( cx, sp, "OneOrMore" ) ,
752+ } ;
753+ let fields = vec ! [ cx. field_imm( sp, id_ext( "tts" ) , e_tts) ,
754+ cx. field_imm( sp, id_ext( "separator" ) , e_separator) ,
755+ cx. field_imm( sp, id_ext( "op" ) , e_op) ,
756+ cx. field_imm( sp, id_ext( "num_captures" ) ,
757+ cx. expr_usize( sp, seq. num_captures) ) ] ;
758+ let seq_path = vec ! [ id_ext( "syntax" ) , id_ext( "ast" ) , id_ext( "SequenceRepetition" ) ] ;
759+ let e_seq_struct = cx. expr_struct ( sp, cx. path_global ( sp, seq_path) , fields) ;
760+ let e_rc_new = cx. expr_call_global ( sp, vec ! [ id_ext( "std" ) ,
761+ id_ext( "rc" ) ,
762+ id_ext( "Rc" ) ,
763+ id_ext( "new" ) ] ,
764+ vec ! [ e_seq_struct] ) ;
765+ let e_tok = cx. expr_call ( sp,
766+ mk_ast_path ( cx, sp, "TtSequence" ) ,
767+ vec ! ( e_sp, e_rc_new) ) ;
768+ let e_push =
769+ cx. expr_method_call ( sp,
770+ cx. expr_ident ( sp, id_ext ( "tt" ) ) ,
771+ id_ext ( "push" ) ,
772+ vec ! ( e_tok) ) ;
773+ vec ! ( cx. stmt_expr( e_push) )
774+ }
699775 }
700- ss
701776}
702777
703- fn expand_tts ( cx : & ExtCtxt , sp : Span , tts : & [ ast:: TokenTree ] )
704- -> ( P < ast:: Expr > , P < ast:: Expr > ) {
778+ fn parse_arguments_to_quote ( cx : & ExtCtxt , tts : & [ ast:: TokenTree ] )
779+ -> ( P < ast:: Expr > , Vec < ast:: TokenTree > ) {
705780 // NB: It appears that the main parser loses its mind if we consider
706- // $foo as a TtNonterminal during the main parse, so we have to re-parse
781+ // $foo as a SubstNt during the main parse, so we have to re-parse
707782 // under quote_depth > 0. This is silly and should go away; the _guess_ is
708783 // it has to do with transition away from supporting old-style macros, so
709784 // try removing it when enough of them are gone.
@@ -719,6 +794,10 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
719794 let tts = p. parse_all_token_trees ( ) ;
720795 p. abort_if_errors ( ) ;
721796
797+ ( cx_expr, tts)
798+ }
799+
800+ fn mk_stmts_let ( cx : & ExtCtxt , sp : Span ) -> Vec < P < ast:: Stmt > > {
722801 // We also bind a single value, sp, to ext_cx.call_site()
723802 //
724803 // This causes every span in a token-tree quote to be attributed to the
@@ -756,8 +835,23 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
756835
757836 let stmt_let_tt = cx. stmt_let ( sp, true , id_ext ( "tt" ) , cx. expr_vec_ng ( sp) ) ;
758837
759- let mut vector = vec ! ( stmt_let_sp, stmt_let_tt) ;
760- vector. extend ( mk_tts ( cx, & tts[ ..] ) . into_iter ( ) ) ;
838+ vec ! ( stmt_let_sp, stmt_let_tt)
839+ }
840+
841+ fn statements_mk_tts ( cx : & ExtCtxt , tts : & [ ast:: TokenTree ] , matcher : bool ) -> Vec < P < ast:: Stmt > > {
842+ let mut ss = Vec :: new ( ) ;
843+ for tt in tts {
844+ ss. extend ( statements_mk_tt ( cx, tt, matcher) . into_iter ( ) ) ;
845+ }
846+ ss
847+ }
848+
849+ fn expand_tts ( cx : & ExtCtxt , sp : Span , tts : & [ ast:: TokenTree ] )
850+ -> ( P < ast:: Expr > , P < ast:: Expr > ) {
851+ let ( cx_expr, tts) = parse_arguments_to_quote ( cx, tts) ;
852+
853+ let mut vector = mk_stmts_let ( cx, sp) ;
854+ vector. extend ( statements_mk_tts ( cx, & tts[ ..] , false ) . into_iter ( ) ) ;
761855 let block = cx. expr_block (
762856 cx. block_all ( sp,
763857 vector,
@@ -769,14 +863,14 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
769863fn expand_wrapper ( cx : & ExtCtxt ,
770864 sp : Span ,
771865 cx_expr : P < ast:: Expr > ,
772- expr : P < ast:: Expr > ) -> P < ast:: Expr > {
866+ expr : P < ast:: Expr > ,
867+ imports : & [ & [ & str ] ] ) -> P < ast:: Expr > {
773868 // Explicitly borrow to avoid moving from the invoker (#16992)
774869 let cx_expr_borrow = cx. expr_addr_of ( sp, cx. expr_deref ( sp, cx_expr) ) ;
775870 let stmt_let_ext_cx = cx. stmt_let ( sp, false , id_ext ( "ext_cx" ) , cx_expr_borrow) ;
776871
777- let stmts = [
778- & [ "syntax" , "ext" , "quote" , "rt" ] ,
779- ] . iter ( ) . map ( |path| {
872+ let stmts = imports. iter ( ) . map ( |path| {
873+ // make item: `use ...;`
780874 let path = path. iter ( ) . map ( |s| s. to_string ( ) ) . collect ( ) ;
781875 cx. stmt_item ( sp, cx. item_use_glob ( sp, ast:: Inherited , ids_ext ( path) ) )
782876 } ) . chain ( Some ( stmt_let_ext_cx) . into_iter ( ) ) . collect ( ) ;
@@ -807,5 +901,10 @@ fn expand_parse_call(cx: &ExtCtxt,
807901 let expr = cx. expr_method_call ( sp, new_parser_call, id_ext ( parse_method) ,
808902 arg_exprs) ;
809903
810- expand_wrapper ( cx, sp, cx_expr, expr)
904+ if parse_method == "parse_attribute" {
905+ expand_wrapper ( cx, sp, cx_expr, expr, & [ & [ "syntax" , "ext" , "quote" , "rt" ] ,
906+ & [ "syntax" , "parse" , "attr" ] ] )
907+ } else {
908+ expand_wrapper ( cx, sp, cx_expr, expr, & [ & [ "syntax" , "ext" , "quote" , "rt" ] ] )
909+ }
811910}
0 commit comments