2424extern crate regex;
2525extern crate syntax;
2626
27+ use std:: rc:: Rc ;
28+
2729use syntax:: ast;
2830use syntax:: codemap;
31+ use syntax:: ext:: build:: AstBuilder ;
2932use syntax:: ext:: base:: {
3033 SyntaxExtension , ExtCtxt , MacResult , MacExpr , DummyResult ,
3134 NormalTT , BasicMacroExpander ,
@@ -112,24 +115,26 @@ impl<'a> NfaGen<'a> {
112115 // expression returned.
113116 let num_cap_locs = 2 * self . prog . num_captures ( ) ;
114117 let num_insts = self . prog . insts . len ( ) ;
115- let cap_names = self . vec_expr ( self . names . as_slice ( ) ,
116- |cx, name| match name {
117- & Some ( ref name) => {
118+ let cap_names = self . vec_expr ( self . names . as_slice ( ) . iter ( ) ,
119+ |cx, name| match * name {
120+ Some ( ref name) => {
118121 let name = name. as_slice ( ) ;
119122 quote_expr ! ( cx, Some ( ~$name) )
120123 }
121- & None => quote_expr ! ( cx , None ) ,
124+ None => cx . expr_none ( self . sp ) ,
122125 }
123126 ) ;
124127 let prefix_anchor =
125128 match self . prog . insts . as_slice ( ) [ 1 ] {
126129 EmptyBegin ( flags) if flags & FLAG_MULTI == 0 => true ,
127130 _ => false ,
128131 } ;
129- let init_groups = self . vec_from_fn ( num_cap_locs,
130- |cx| quote_expr ! ( cx, None ) ) ;
131- let prefix_bytes = self . vec_expr ( self . prog . prefix . as_slice ( ) . as_bytes ( ) ,
132- |cx, b| quote_expr ! ( cx, $b) ) ;
132+ let init_groups = self . vec_expr ( range ( 0 , num_cap_locs) ,
133+ |cx, _| cx. expr_none ( self . sp ) ) ;
134+
135+ let prefix_lit = Rc :: new ( Vec :: from_slice ( self . prog . prefix . as_slice ( ) . as_bytes ( ) ) ) ;
136+ let prefix_bytes = self . cx . expr_lit ( self . sp , ast:: LitBinary ( prefix_lit) ) ;
137+
133138 let check_prefix = self . check_prefix ( ) ;
134139 let step_insts = self . step_insts ( ) ;
135140 let add_insts = self . add_insts ( ) ;
@@ -320,12 +325,11 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
320325 let nextpc = pc + 1 ;
321326 let body = match * inst {
322327 EmptyBegin ( flags) => {
323- let nl = '\n' ;
324328 let cond =
325329 if flags & FLAG_MULTI > 0 {
326330 quote_expr ! ( self . cx,
327331 self . chars. is_begin( )
328- || self . chars. prev == Some ( $nl )
332+ || self . chars. prev == Some ( '\n' )
329333 )
330334 } else {
331335 quote_expr ! ( self . cx, self . chars. is_begin( ) )
@@ -336,12 +340,11 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
336340 } )
337341 }
338342 EmptyEnd ( flags) => {
339- let nl = '\n' ;
340343 let cond =
341344 if flags & FLAG_MULTI > 0 {
342345 quote_expr ! ( self . cx,
343346 self . chars. is_end( )
344- || self . chars. cur == Some ( $nl )
347+ || self . chars. cur == Some ( '\n' )
345348 )
346349 } else {
347350 quote_expr ! ( self . cx, self . chars. is_end( ) )
@@ -489,16 +492,16 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
489492 if flags & FLAG_DOTNL > 0 {
490493 quote_expr ! ( self . cx, self . add( nlist, $nextpc, caps) )
491494 } else {
492- let nl = '\n' ; // no char lits allowed? wtf?
493495 quote_expr ! ( self . cx, {
494- if self . chars. prev != Some ( $nl ) {
496+ if self . chars. prev != Some ( '\n' ) {
495497 self . add( nlist, $nextpc, caps)
496498 }
499+ ( )
497500 } )
498501 }
499502 }
500503 // EmptyBegin, EmptyEnd, EmptyWordBoundary, Save, Jump, Split
501- _ => quote_expr ! ( self . cx , { } ) ,
504+ _ => self . empty_block ( ) ,
502505 } ;
503506 self . arm_inst ( pc, body)
504507 } ) . collect :: < Vec < ast:: Arm > > ( ) ;
@@ -510,36 +513,30 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
510513 // This avoids a binary search (and is hopefully replaced by a jump
511514 // table).
512515 fn match_class ( & self , casei : bool , ranges : & [ ( char , char ) ] ) -> @ast:: Expr {
516+ let expr_true = quote_expr ! ( self . cx, true ) ;
517+
513518 let mut arms = ranges. iter ( ) . map ( |& ( mut start, mut end) | {
514519 if casei {
515520 start = start. to_uppercase ( ) ;
516521 end = end. to_uppercase ( ) ;
517522 }
518- ast:: Arm {
519- attrs : vec ! ( ) ,
520- pats : vec ! ( @ast:: Pat {
521- id: ast:: DUMMY_NODE_ID ,
522- span: self . sp,
523- node: ast:: PatRange ( quote_expr!( self . cx, $start) ,
524- quote_expr!( self . cx, $end) ) ,
525- } ) ,
526- guard : None ,
527- body : quote_expr ! ( self . cx, true ) ,
528- }
523+ let pat = self . cx . pat ( self . sp , ast:: PatRange ( quote_expr ! ( self . cx, $start) ,
524+ quote_expr ! ( self . cx, $end) ) ) ;
525+ self . cx . arm ( self . sp , vec ! ( pat) , expr_true)
529526 } ) . collect :: < Vec < ast:: Arm > > ( ) ;
530527
531528 arms. push ( self . wild_arm_expr ( quote_expr ! ( self . cx, false ) ) ) ;
532529
533530 let match_on = quote_expr ! ( self . cx, c) ;
534- self . dummy_expr ( ast :: ExprMatch ( match_on, arms) )
531+ self . cx . expr_match ( self . sp , match_on, arms)
535532 }
536533
537534 // Generates code for checking a literal prefix of the search string.
538535 // The code is only generated if the regex *has* a literal prefix.
539536 // Otherwise, a no-op is returned.
540537 fn check_prefix ( & self ) -> @ast:: Expr {
541538 if self . prog . prefix . len ( ) == 0 {
542- quote_expr ! ( self . cx , { } )
539+ self . empty_block ( )
543540 } else {
544541 quote_expr ! ( self . cx,
545542 if clist. size == 0 {
@@ -562,24 +559,20 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
562559 // never be used, but is added to satisfy the compiler complaining about
563560 // non-exhaustive patterns.
564561 fn match_insts ( & self , mut arms : Vec < ast:: Arm > ) -> @ast:: Expr {
565- let mat_pc = quote_expr ! ( self . cx, pc) ;
566- arms. push ( self . wild_arm_expr ( quote_expr ! ( self . cx, { } ) ) ) ;
567- self . dummy_expr ( ast:: ExprMatch ( mat_pc, arms) )
562+ arms. push ( self . wild_arm_expr ( self . empty_block ( ) ) ) ;
563+ self . cx . expr_match ( self . sp , quote_expr ! ( self . cx, pc) , arms)
564+ }
565+
566+ fn empty_block ( & self ) -> @ast:: Expr {
567+ quote_expr ! ( self . cx, { } )
568568 }
569569
570570 // Creates a match arm for the instruction at `pc` with the expression
571571 // `body`.
572572 fn arm_inst ( & self , pc : uint , body : @ast:: Expr ) -> ast:: Arm {
573- ast:: Arm {
574- attrs : vec ! ( ) ,
575- pats : vec ! ( @ast:: Pat {
576- id: ast:: DUMMY_NODE_ID ,
577- span: self . sp,
578- node: ast:: PatLit ( quote_expr!( self . cx, $pc) ) ,
579- } ) ,
580- guard : None ,
581- body : body,
582- }
573+ let pc_pat = self . cx . pat_lit ( self . sp , quote_expr ! ( self . cx, $pc) ) ;
574+
575+ self . cx . arm ( self . sp , vec ! ( pc_pat) , body)
583576 }
584577
585578 // Creates a wild-card match arm with the expression `body`.
@@ -596,56 +589,13 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
596589 }
597590 }
598591
599- // Builds a `[a, b, .., len]` expression where each element is the result
600- // of executing `to_expr`.
601- fn vec_from_fn ( & self , len : uint , to_expr: |& ExtCtxt | -> @ast:: Expr )
602- -> @ast:: Expr {
603- self . vec_expr ( Vec :: from_elem ( len, ( ) ) . as_slice ( ) ,
604- |cx, _| to_expr ( cx) )
605- }
606592
607593 // Converts `xs` to a `[x1, x2, .., xN]` expression by calling `to_expr`
608594 // on each element in `xs`.
609- fn vec_expr < T > ( & self , xs : & [ T ] , to_expr : |& ExtCtxt , & T | -> @ast:: Expr )
595+ fn vec_expr < T , It : Iterator < T > > ( & self , xs : It , to_expr : |& ExtCtxt , T | -> @ast:: Expr )
610596 -> @ast:: Expr {
611- let mut exprs = vec ! ( ) ;
612- for x in xs. iter ( ) {
613- exprs. push ( to_expr ( self . cx , x) )
614- }
615- let vec_exprs = self . dummy_expr ( ast:: ExprVec ( exprs) ) ;
616- quote_expr ! ( self . cx, $vec_exprs)
617- }
618-
619- // Creates an expression with a dummy node ID given an underlying
620- // `ast::Expr_`.
621- fn dummy_expr ( & self , e : ast:: Expr_ ) -> @ast:: Expr {
622- @ast:: Expr {
623- id : ast:: DUMMY_NODE_ID ,
624- node : e,
625- span : self . sp ,
626- }
627- }
628- }
629-
630- // This trait is defined in the quote module in the syntax crate, but I
631- // don't think it's exported.
632- // Interestingly, quote_expr! only requires that a 'to_tokens' method be
633- // defined rather than satisfying a particular trait.
634- #[ doc( hidden) ]
635- trait ToTokens {
636- fn to_tokens ( & self , cx : & ExtCtxt ) -> Vec < ast:: TokenTree > ;
637- }
638-
639- impl ToTokens for char {
640- fn to_tokens ( & self , _: & ExtCtxt ) -> Vec < ast:: TokenTree > {
641- vec ! ( ast:: TTTok ( codemap:: DUMMY_SP , token:: LIT_CHAR ( ( * self ) as u32 ) ) )
642- }
643- }
644-
645- impl ToTokens for bool {
646- fn to_tokens ( & self , _: & ExtCtxt ) -> Vec < ast:: TokenTree > {
647- let ident = token:: IDENT ( token:: str_to_ident ( self . to_str ( ) ) , false ) ;
648- vec ! ( ast:: TTTok ( codemap:: DUMMY_SP , ident) )
597+ let exprs = xs. map ( |x| to_expr ( self . cx , x) ) . collect ( ) ;
598+ self . cx . expr_vec ( self . sp , exprs)
649599 }
650600}
651601
0 commit comments