@@ -14,10 +14,9 @@ use ext::base::ExtCtxt;
14
14
use ext:: base;
15
15
use ext:: build:: AstBuilder ;
16
16
use parse:: parser:: { Parser , PathStyle } ;
17
- use parse:: token:: * ;
18
17
use parse:: token;
19
18
use ptr:: P ;
20
- use tokenstream:: { self , TokenTree } ;
19
+ use tokenstream:: TokenTree ;
21
20
22
21
23
22
/// Quasiquoting works via token trees.
@@ -356,14 +355,35 @@ pub mod rt {
356
355
}
357
356
358
357
fn parse_tts ( & self , s : String ) -> Vec < TokenTree > {
359
- panictry ! ( parse:: parse_tts_from_source_str(
360
- "<quote expansion>" . to_string( ) ,
361
- s,
362
- self . parse_sess( ) ) )
358
+ parse:: parse_tts_from_source_str ( "<quote expansion>" . to_string ( ) , s, self . parse_sess ( ) )
363
359
}
364
360
}
365
361
}
366
362
363
+ // Replaces `Token::OpenDelim .. Token::CloseDelim` with `TokenTree::Delimited(..)`.
364
+ pub fn unflatten ( tts : Vec < TokenTree > ) -> Vec < TokenTree > {
365
+ use std:: rc:: Rc ;
366
+ use tokenstream:: Delimited ;
367
+
368
+ let mut results = Vec :: new ( ) ;
369
+ let mut result = Vec :: new ( ) ;
370
+ for tree in tts {
371
+ match tree {
372
+ TokenTree :: Token ( _, token:: OpenDelim ( ..) ) => {
373
+ results. push ( :: std:: mem:: replace ( & mut result, Vec :: new ( ) ) ) ;
374
+ }
375
+ TokenTree :: Token ( span, token:: CloseDelim ( delim) ) => {
376
+ let tree =
377
+ TokenTree :: Delimited ( span, Rc :: new ( Delimited { delim : delim, tts : result } ) ) ;
378
+ result = results. pop ( ) . unwrap ( ) ;
379
+ result. push ( tree) ;
380
+ }
381
+ tree @ _ => result. push ( tree) ,
382
+ }
383
+ }
384
+ result
385
+ }
386
+
367
387
// These panicking parsing functions are used by the quote_*!() syntax extensions,
368
388
// but shouldn't be used otherwise.
369
389
pub fn parse_expr_panic ( parser : & mut Parser ) -> P < Expr > {
@@ -510,20 +530,6 @@ pub fn expand_quote_path(cx: &mut ExtCtxt,
510
530
base:: MacEager :: expr ( expanded)
511
531
}
512
532
513
- pub fn expand_quote_matcher ( cx : & mut ExtCtxt ,
514
- sp : Span ,
515
- tts : & [ TokenTree ] )
516
- -> Box < base:: MacResult +' static > {
517
- let ( cx_expr, tts) = parse_arguments_to_quote ( cx, tts) ;
518
- let mut vector = mk_stmts_let ( cx, sp) ;
519
- vector. extend ( statements_mk_tts ( cx, & tts[ ..] , true ) ) ;
520
- vector. push ( cx. stmt_expr ( cx. expr_ident ( sp, id_ext ( "tt" ) ) ) ) ;
521
- let block = cx. expr_block ( cx. block ( sp, vector) ) ;
522
-
523
- let expanded = expand_wrapper ( cx, sp, cx_expr, block, & [ & [ "syntax" , "ext" , "quote" , "rt" ] ] ) ;
524
- base:: MacEager :: expr ( expanded)
525
- }
526
-
527
533
fn ids_ext ( strs : Vec < String > ) -> Vec < ast:: Ident > {
528
534
strs. iter ( ) . map ( |s| ast:: Ident :: from_str ( s) ) . collect ( )
529
535
}
@@ -669,12 +675,6 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
669
675
vec ! [ mk_name( cx, sp, ast:: Ident :: with_empty_ctxt( ident) ) ] ) ;
670
676
}
671
677
672
- token:: MatchNt ( name, kind) => {
673
- return cx. expr_call ( sp,
674
- mk_token_path ( cx, sp, "MatchNt" ) ,
675
- vec ! [ mk_ident( cx, sp, name) , mk_ident( cx, sp, kind) ] ) ;
676
- }
677
-
678
678
token:: Interpolated ( _) => panic ! ( "quote! with interpolated token" ) ,
679
679
680
680
_ => ( )
@@ -712,9 +712,9 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
712
712
mk_token_path ( cx, sp, name)
713
713
}
714
714
715
- fn statements_mk_tt ( cx : & ExtCtxt , tt : & TokenTree , matcher : bool ) -> Vec < ast:: Stmt > {
715
+ fn statements_mk_tt ( cx : & ExtCtxt , tt : & TokenTree , quoted : bool ) -> Vec < ast:: Stmt > {
716
716
match * tt {
717
- TokenTree :: Token ( sp, SubstNt ( ident) ) => {
717
+ TokenTree :: Token ( sp, token :: Ident ( ident) ) if quoted => {
718
718
// tt.extend($ident.to_tokens(ext_cx))
719
719
720
720
let e_to_toks =
@@ -733,13 +733,6 @@ fn statements_mk_tt(cx: &ExtCtxt, tt: &TokenTree, matcher: bool) -> Vec<ast::Stm
733
733
734
734
vec ! [ cx. stmt_expr( e_push) ]
735
735
}
736
- ref tt @ TokenTree :: Token ( _, MatchNt ( ..) ) if !matcher => {
737
- let mut seq = vec ! [ ] ;
738
- for i in 0 ..tt. len ( ) {
739
- seq. push ( tt. get_tt ( i) ) ;
740
- }
741
- statements_mk_tts ( cx, & seq[ ..] , matcher)
742
- }
743
736
TokenTree :: Token ( sp, ref tok) => {
744
737
let e_sp = cx. expr_ident ( sp, id_ext ( "_sp" ) ) ;
745
738
let e_tok = cx. expr_call ( sp,
@@ -753,77 +746,17 @@ fn statements_mk_tt(cx: &ExtCtxt, tt: &TokenTree, matcher: bool) -> Vec<ast::Stm
753
746
vec ! [ cx. stmt_expr( e_push) ]
754
747
} ,
755
748
TokenTree :: Delimited ( span, ref delimed) => {
756
- statements_mk_tt ( cx, & delimed. open_tt ( span) , matcher) . into_iter ( )
757
- . chain ( delimed. tts . iter ( )
758
- . flat_map ( |tt| statements_mk_tt ( cx, tt, matcher) ) )
759
- . chain ( statements_mk_tt ( cx, & delimed. close_tt ( span) , matcher) )
760
- . collect ( )
761
- } ,
762
- TokenTree :: Sequence ( sp, ref seq) => {
763
- if !matcher {
764
- panic ! ( "TokenTree::Sequence in quote!" ) ;
765
- }
766
-
767
- let e_sp = cx. expr_ident ( sp, id_ext ( "_sp" ) ) ;
768
-
769
- let stmt_let_tt = cx. stmt_let ( sp, true , id_ext ( "tt" ) , cx. expr_vec_ng ( sp) ) ;
770
- let mut tts_stmts = vec ! [ stmt_let_tt] ;
771
- tts_stmts. extend ( statements_mk_tts ( cx, & seq. tts [ ..] , matcher) ) ;
772
- tts_stmts. push ( cx. stmt_expr ( cx. expr_ident ( sp, id_ext ( "tt" ) ) ) ) ;
773
- let e_tts = cx. expr_block ( cx. block ( sp, tts_stmts) ) ;
774
-
775
- let e_separator = match seq. separator {
776
- Some ( ref sep) => cx. expr_some ( sp, expr_mk_token ( cx, sp, sep) ) ,
777
- None => cx. expr_none ( sp) ,
778
- } ;
779
- let e_op = match seq. op {
780
- tokenstream:: KleeneOp :: ZeroOrMore => "ZeroOrMore" ,
781
- tokenstream:: KleeneOp :: OneOrMore => "OneOrMore" ,
782
- } ;
783
- let e_op_idents = vec ! [
784
- id_ext( "syntax" ) ,
785
- id_ext( "tokenstream" ) ,
786
- id_ext( "KleeneOp" ) ,
787
- id_ext( e_op) ,
788
- ] ;
789
- let e_op = cx. expr_path ( cx. path_global ( sp, e_op_idents) ) ;
790
- let fields = vec ! [ cx. field_imm( sp, id_ext( "tts" ) , e_tts) ,
791
- cx. field_imm( sp, id_ext( "separator" ) , e_separator) ,
792
- cx. field_imm( sp, id_ext( "op" ) , e_op) ,
793
- cx. field_imm( sp, id_ext( "num_captures" ) ,
794
- cx. expr_usize( sp, seq. num_captures) ) ] ;
795
- let seq_path = vec ! [ id_ext( "syntax" ) ,
796
- id_ext( "tokenstream" ) ,
797
- id_ext( "SequenceRepetition" ) ] ;
798
- let e_seq_struct = cx. expr_struct ( sp, cx. path_global ( sp, seq_path) , fields) ;
799
- let e_rc_new = cx. expr_call_global ( sp, vec ! [ id_ext( "std" ) ,
800
- id_ext( "rc" ) ,
801
- id_ext( "Rc" ) ,
802
- id_ext( "new" ) ] ,
803
- vec ! [ e_seq_struct] ) ;
804
- let e_tok = cx. expr_call ( sp,
805
- mk_tt_path ( cx, sp, "Sequence" ) ,
806
- vec ! [ e_sp, e_rc_new] ) ;
807
- let e_push =
808
- cx. expr_method_call ( sp,
809
- cx. expr_ident ( sp, id_ext ( "tt" ) ) ,
810
- id_ext ( "push" ) ,
811
- vec ! [ e_tok] ) ;
812
- vec ! [ cx. stmt_expr( e_push) ]
749
+ let mut stmts = statements_mk_tt ( cx, & delimed. open_tt ( span) , false ) ;
750
+ stmts. extend ( statements_mk_tts ( cx, & delimed. tts ) ) ;
751
+ stmts. extend ( statements_mk_tt ( cx, & delimed. close_tt ( span) , false ) ) ;
752
+ stmts
813
753
}
814
754
}
815
755
}
816
756
817
757
fn parse_arguments_to_quote ( cx : & ExtCtxt , tts : & [ TokenTree ] )
818
758
-> ( P < ast:: Expr > , Vec < TokenTree > ) {
819
- // NB: It appears that the main parser loses its mind if we consider
820
- // $foo as a SubstNt during the main parse, so we have to re-parse
821
- // under quote_depth > 0. This is silly and should go away; the _guess_ is
822
- // it has to do with transition away from supporting old-style macros, so
823
- // try removing it when enough of them are gone.
824
-
825
759
let mut p = cx. new_parser_from_tts ( tts) ;
826
- p. quote_depth += 1 ;
827
760
828
761
let cx_expr = panictry ! ( p. parse_expr( ) ) ;
829
762
if !p. eat ( & token:: Comma ) {
@@ -877,24 +810,31 @@ fn mk_stmts_let(cx: &ExtCtxt, sp: Span) -> Vec<ast::Stmt> {
877
810
vec ! [ stmt_let_sp, stmt_let_tt]
878
811
}
879
812
880
- fn statements_mk_tts ( cx : & ExtCtxt , tts : & [ TokenTree ] , matcher : bool ) -> Vec < ast:: Stmt > {
813
+ fn statements_mk_tts ( cx : & ExtCtxt , tts : & [ TokenTree ] ) -> Vec < ast:: Stmt > {
881
814
let mut ss = Vec :: new ( ) ;
815
+ let mut quoted = false ;
882
816
for tt in tts {
883
- ss. extend ( statements_mk_tt ( cx, tt, matcher) ) ;
817
+ quoted = match * tt {
818
+ TokenTree :: Token ( _, token:: Dollar ) if !quoted => true ,
819
+ _ => {
820
+ ss. extend ( statements_mk_tt ( cx, tt, quoted) ) ;
821
+ false
822
+ }
823
+ }
884
824
}
885
825
ss
886
826
}
887
827
888
- fn expand_tts ( cx : & ExtCtxt , sp : Span , tts : & [ TokenTree ] )
889
- -> ( P < ast:: Expr > , P < ast:: Expr > ) {
828
+ fn expand_tts ( cx : & ExtCtxt , sp : Span , tts : & [ TokenTree ] ) -> ( P < ast:: Expr > , P < ast:: Expr > ) {
890
829
let ( cx_expr, tts) = parse_arguments_to_quote ( cx, tts) ;
891
830
892
831
let mut vector = mk_stmts_let ( cx, sp) ;
893
- vector. extend ( statements_mk_tts ( cx, & tts[ ..] , false ) ) ;
832
+ vector. extend ( statements_mk_tts ( cx, & tts[ ..] ) ) ;
894
833
vector. push ( cx. stmt_expr ( cx. expr_ident ( sp, id_ext ( "tt" ) ) ) ) ;
895
834
let block = cx. expr_block ( cx. block ( sp, vector) ) ;
835
+ let unflatten = vec ! [ id_ext( "syntax" ) , id_ext( "ext" ) , id_ext( "quote" ) , id_ext( "unflatten" ) ] ;
896
836
897
- ( cx_expr, block)
837
+ ( cx_expr, cx . expr_call_global ( sp , unflatten , vec ! [ block] ) )
898
838
}
899
839
900
840
fn expand_wrapper ( cx : & ExtCtxt ,
0 commit comments