24
24
extern crate regex;
25
25
extern crate syntax;
26
26
27
+ use std:: rc:: Rc ;
28
+
27
29
use syntax:: ast;
28
30
use syntax:: codemap;
31
+ use syntax:: ext:: build:: AstBuilder ;
29
32
use syntax:: ext:: base:: {
30
33
SyntaxExtension , ExtCtxt , MacResult , MacExpr , DummyResult ,
31
34
NormalTT , BasicMacroExpander ,
@@ -112,24 +115,26 @@ impl<'a> NfaGen<'a> {
112
115
// expression returned.
113
116
let num_cap_locs = 2 * self . prog . num_captures ( ) ;
114
117
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) => {
118
121
let name = name. as_slice ( ) ;
119
122
quote_expr ! ( cx, Some ( $name. to_owned( ) ) )
120
123
}
121
- & None => quote_expr ! ( cx , None ) ,
124
+ None => cx . expr_none ( self . sp ) ,
122
125
}
123
126
) ;
124
127
let prefix_anchor =
125
128
match self . prog . insts . as_slice ( ) [ 1 ] {
126
129
EmptyBegin ( flags) if flags & FLAG_MULTI == 0 => true ,
127
130
_ => false ,
128
131
} ;
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
+
133
138
let check_prefix = self . check_prefix ( ) ;
134
139
let step_insts = self . step_insts ( ) ;
135
140
let add_insts = self . add_insts ( ) ;
@@ -320,12 +325,11 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
320
325
let nextpc = pc + 1 ;
321
326
let body = match * inst {
322
327
EmptyBegin ( flags) => {
323
- let nl = '\n' ;
324
328
let cond =
325
329
if flags & FLAG_MULTI > 0 {
326
330
quote_expr ! ( self . cx,
327
331
self . chars. is_begin( )
328
- || self . chars. prev == Some ( $nl )
332
+ || self . chars. prev == Some ( '\n' )
329
333
)
330
334
} else {
331
335
quote_expr ! ( self . cx, self . chars. is_begin( ) )
@@ -336,12 +340,11 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
336
340
} )
337
341
}
338
342
EmptyEnd ( flags) => {
339
- let nl = '\n' ;
340
343
let cond =
341
344
if flags & FLAG_MULTI > 0 {
342
345
quote_expr ! ( self . cx,
343
346
self . chars. is_end( )
344
- || self . chars. cur == Some ( $nl )
347
+ || self . chars. cur == Some ( '\n' )
345
348
)
346
349
} else {
347
350
quote_expr ! ( self . cx, self . chars. is_end( ) )
@@ -489,16 +492,16 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
489
492
if flags & FLAG_DOTNL > 0 {
490
493
quote_expr ! ( self . cx, self . add( nlist, $nextpc, caps) )
491
494
} else {
492
- let nl = '\n' ; // no char lits allowed? wtf?
493
495
quote_expr ! ( self . cx, {
494
- if self . chars. prev != Some ( $nl ) {
496
+ if self . chars. prev != Some ( '\n' ) {
495
497
self . add( nlist, $nextpc, caps)
496
498
}
499
+ ( )
497
500
} )
498
501
}
499
502
}
500
503
// EmptyBegin, EmptyEnd, EmptyWordBoundary, Save, Jump, Split
501
- _ => quote_expr ! ( self . cx , { } ) ,
504
+ _ => self . empty_block ( ) ,
502
505
} ;
503
506
self . arm_inst ( pc, body)
504
507
} ) . collect :: < Vec < ast:: Arm > > ( ) ;
@@ -510,36 +513,30 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
510
513
// This avoids a binary search (and is hopefully replaced by a jump
511
514
// table).
512
515
fn match_class ( & self , casei : bool , ranges : & [ ( char , char ) ] ) -> @ast:: Expr {
516
+ let expr_true = quote_expr ! ( self . cx, true ) ;
517
+
513
518
let mut arms = ranges. iter ( ) . map ( |& ( mut start, mut end) | {
514
519
if casei {
515
520
start = start. to_uppercase ( ) ;
516
521
end = end. to_uppercase ( ) ;
517
522
}
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)
529
526
} ) . collect :: < Vec < ast:: Arm > > ( ) ;
530
527
531
528
arms. push ( self . wild_arm_expr ( quote_expr ! ( self . cx, false ) ) ) ;
532
529
533
530
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)
535
532
}
536
533
537
534
// Generates code for checking a literal prefix of the search string.
538
535
// The code is only generated if the regex *has* a literal prefix.
539
536
// Otherwise, a no-op is returned.
540
537
fn check_prefix ( & self ) -> @ast:: Expr {
541
538
if self . prog . prefix . len ( ) == 0 {
542
- quote_expr ! ( self . cx , { } )
539
+ self . empty_block ( )
543
540
} else {
544
541
quote_expr ! ( self . cx,
545
542
if clist. size == 0 {
@@ -562,24 +559,20 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
562
559
// never be used, but is added to satisfy the compiler complaining about
563
560
// non-exhaustive patterns.
564
561
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, { } )
568
568
}
569
569
570
570
// Creates a match arm for the instruction at `pc` with the expression
571
571
// `body`.
572
572
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)
583
576
}
584
577
585
578
// Creates a wild-card match arm with the expression `body`.
@@ -596,56 +589,13 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
596
589
}
597
590
}
598
591
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
- }
606
592
607
593
// Converts `xs` to a `[x1, x2, .., xN]` expression by calling `to_expr`
608
594
// 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 )
610
596
-> @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)
649
599
}
650
600
}
651
601
0 commit comments