@@ -41,6 +41,7 @@ type matcher_pos = ~{
41
41
mut idx: uint,
42
42
mut up: matcher_pos_up, // mutable for swapping only
43
43
matches: ~[ dvec<@arb_depth>] ,
44
+ match_lo: uint, match_hi: uint,
44
45
sp_lo: uint,
45
46
} ;
46
47
@@ -55,17 +56,25 @@ fn count_names(ms: &[matcher]) -> uint {
55
56
vec:: foldl ( 0 u, ms, |ct, m| {
56
57
ct + alt m. node {
57
58
mtc_tok ( _) { 0 u }
58
- mtc_rep ( more_ms, _, _) { count_names ( more_ms) }
59
+ mtc_rep ( more_ms, _, _, _ , _ ) { count_names ( more_ms) }
59
60
mtc_bb ( _, _, _) { 1 u }
60
61
} } )
61
62
}
62
63
63
64
#[ warn( no_non_implicitly_copyable_typarams) ]
64
- fn new_matcher_pos ( ms : ~[ matcher ] , sep : option < token > , lo : uint )
65
+ fn initial_matcher_pos ( ms : ~[ matcher ] , sep : option < token > , lo : uint )
65
66
-> matcher_pos {
67
+ let mut match_idx_hi = 0 u;
68
+ for ms. each( ) |elt| {
69
+ alt elt. node {
70
+ mtc_tok( _) { }
71
+ mtc_rep( _, _, _, _, hi) { match_idx_hi = hi; } //it is monotonic...
72
+ mtc_bb ( _, _, pos) { match_idx_hi = pos+1 u; } //...so latest is highest
73
+ }
74
+ }
66
75
~{ elts: ms, sep: sep, mut idx: 0 u, mut up: matcher_pos_up ( none) ,
67
76
matches: copy vec:: from_fn ( count_names ( ms) , |_i| dvec:: dvec ( ) ) ,
68
- sp_lo: lo}
77
+ match_lo : 0 u , match_hi : match_idx_hi , sp_lo: lo}
69
78
}
70
79
71
80
/* logically, an arb_depth should contain only one kind of nonterminal */
@@ -79,7 +88,7 @@ fn nameize(p_s: parse_sess, ms: ~[matcher], res: ~[@arb_depth])
79
88
ret_val : hashmap < ident , @arb_depth > ) {
80
89
alt m {
81
90
{ node : mtc_tok ( _) , span : _} { }
82
- { node: mtc_rep ( more_ms, _, _) , span: _} {
91
+ { node: mtc_rep ( more_ms, _, _, _ , _ ) , span: _} {
83
92
for more_ms. each( ) |next_m| { n_rec( p_s, next_m, res, ret_val) } ;
84
93
}
85
94
{ node: mtc_bb ( bind_name, _, idx) , span: sp} {
@@ -104,7 +113,7 @@ enum parse_result {
104
113
fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher])
105
114
-> parse_result {
106
115
let mut cur_eis = ~[];
107
- vec::push(cur_eis, new_matcher_pos (ms, none, rdr.peek().sp.lo));
116
+ vec::push(cur_eis, initial_matcher_pos (ms, none, rdr.peek().sp.lo));
108
117
109
118
loop {
110
119
let mut bb_eis = ~[]; // black-box parsed by parser.rs
@@ -141,10 +150,10 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher])
141
150
// I bet this is a perf problem: we're preemptively
142
151
// doing a lot of array work that will get thrown away
143
152
// most of the time.
144
- for ei . matches . eachi ( ) |idx , elt| {
145
- let sub = elt . get ( ) ;
146
- // Some subtrees don't contain the name at all
147
- if sub. len ( ) == 0 u { again ; }
153
+
154
+ // Only touch the binders we have actually bound
155
+ for uint :: range ( ei . match_lo , ei . match_hi ) |idx| {
156
+ let sub = ei . matches [ idx ] . get ( ) ;
148
157
new_pos. matches [ idx]
149
158
. push ( @seq ( sub, mk_sp ( ei. sp_lo , sp. hi ) ) ) ;
150
159
}
@@ -176,10 +185,15 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher])
176
185
} else {
177
186
alt copy ei. elts [ idx] . node {
178
187
/* need to descend into sequence */
179
- mtc_rep ( matchers, sep, zero_ok) {
188
+ mtc_rep ( matchers, sep, zero_ok, match_idx_lo , match_idx_hi ) {
180
189
if zero_ok {
181
190
let new_ei = copy ei;
182
191
new_ei. idx += 1 u;
192
+ //we specifically matched zero repeats.
193
+ for uint:: range( match_idx_lo, match_idx_hi) |idx| {
194
+ new_ei. matches [ idx] . push ( @seq ( ~[ ] , sp) ) ;
195
+ }
196
+
183
197
vec:: push ( cur_eis, new_ei) ;
184
198
}
185
199
@@ -189,7 +203,9 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher])
189
203
vec:: push ( cur_eis , ~{
190
204
elts : matchers , sep : sep , mut idx : 0 u ,
191
205
mut up : matcher_pos_up ( some ( ei_t ) ) ,
192
- matches : matches , sp_lo : sp . lo
206
+ matches : matches ,
207
+ match_lo : match_idx_lo , match_hi : match_idx_hi ,
208
+ sp_lo : sp . lo
193
209
} ) ;
194
210
}
195
211
mtc_bb( _, _ , _) { vec:: push ( bb_eis, ei) }
0 commit comments