@@ -125,33 +125,23 @@ struct MatcherPos<'tt> {
125
125
/// The "dot" position within the current submatcher, i.e. the index into `tts`.
126
126
idx : usize ,
127
127
128
- /// This boxed slice has one element per metavar in the *top-level* matcher, even when this
128
+ /// This vector ends up with one element per metavar in the *top-level* matcher, even when this
129
129
/// `MatcherPos` is for a submatcher. Each element records token trees matched against the
130
- /// relevant metavar by the black box parser.
131
- ///
132
- /// In a top-level `MatcherPos` each `NamedMatchVec` will have zero elements before processing
133
- /// and one element after processing; the one element will be a `MatchedSeq` if the
130
+ /// relevant metavar by the black box parser. The element will be a `MatchedSeq` if the
134
131
/// corresponding metavar is within a sequence.
135
- ///
136
- /// In a sequence submatcher each `NamedMatchVec` will have zero elements before processing and
137
- /// any number of elements after processing (as allowed by the sequence's Kleene op, i.e.
138
- /// zero-or-one, zero-or-more, one-or-more). After processing these elements will be merged
139
- /// into the parent `MatcherPos`'s matches (within a `MatchedSeq`).
140
- matches : Box < [ Lrc < NamedMatchVec > ] > ,
132
+ matches : Lrc < NamedMatchVec > ,
133
+
134
+ /// The number of sequences this mp is within.
135
+ seq_depth : usize ,
141
136
142
137
/// The position in `matches` of the first metavar in this (sub)matcher. Zero if there are
143
138
/// no metavars.
144
139
match_lo : usize ,
145
140
146
141
/// The position in `matches` of the next metavar to be matched against the source token
147
- /// stream. `match_lo <= match_cur <= match_hi`. Should not be used if there are no metavars,
148
- /// i.e. `match_lo == match_hi`.
142
+ /// stream. Should not be used if there are no metavars.
149
143
match_cur : usize ,
150
144
151
- /// The position in `matches` one past the last metavar in this (sub)matcher. Equal to
152
- /// `match_lo` if there are not metavars.
153
- match_hi : usize ,
154
-
155
145
/// This field is only used if we are matching a sequence.
156
146
sequence : Option < MatcherPosSequence < ' tt > > ,
157
147
@@ -162,50 +152,73 @@ struct MatcherPos<'tt> {
162
152
163
153
// This type is used a lot. Make sure it doesn't unintentionally get bigger.
164
154
#[ cfg( all( target_arch = "x86_64" , target_pointer_width = "64" ) ) ]
165
- rustc_data_structures:: static_assert_size!( MatcherPos <' _>, 112 ) ;
155
+ rustc_data_structures:: static_assert_size!( MatcherPos <' _>, 104 ) ;
166
156
167
157
impl < ' tt > MatcherPos < ' tt > {
168
- fn empty_matches ( len : usize ) -> Box < [ Lrc < NamedMatchVec > ] > {
169
- if len == 0 {
170
- vec ! [ ]
171
- } else {
172
- let empty_matches = Lrc :: new ( SmallVec :: new ( ) ) ;
173
- vec ! [ empty_matches; len]
174
- }
175
- . into_boxed_slice ( )
176
- }
177
-
178
158
fn top_level ( matcher : & ' tt [ TokenTree ] ) -> Self {
179
- let match_idx_hi = count_metavar_decls ( matcher) ;
180
159
MatcherPos {
181
160
tts : matcher,
182
161
idx : 0 ,
183
- matches : Self :: empty_matches ( match_idx_hi) ,
162
+ matches : Lrc :: new ( smallvec ! [ ] ) ,
163
+ seq_depth : 0 ,
184
164
match_lo : 0 ,
185
165
match_cur : 0 ,
186
- match_hi : match_idx_hi,
187
166
stack : smallvec ! [ ] ,
188
167
sequence : None ,
189
168
}
190
169
}
191
170
192
171
fn sequence ( parent : Box < MatcherPos < ' tt > > , seq : & ' tt SequenceRepetition ) -> Self {
193
- MatcherPos {
172
+ let mut mp = MatcherPos {
194
173
tts : & seq. tts ,
195
174
idx : 0 ,
196
- matches : Self :: empty_matches ( parent. matches . len ( ) ) ,
175
+ matches : parent. matches . clone ( ) ,
176
+ seq_depth : parent. seq_depth ,
197
177
match_lo : parent. match_cur ,
198
178
match_cur : parent. match_cur ,
199
- match_hi : parent. match_cur + seq. num_captures ,
200
179
sequence : Some ( MatcherPosSequence { parent, seq } ) ,
201
180
stack : smallvec ! [ ] ,
181
+ } ;
182
+ // Start with an empty vec for each metavar within the sequence. Note that `mp.seq_depth`
183
+ // must have the parent's depth at this point for these `push_match` calls to work.
184
+ for idx in mp. match_lo ..mp. match_lo + seq. num_captures {
185
+ mp. push_match ( idx, MatchedSeq ( Lrc :: new ( smallvec ! [ ] ) ) ) ;
202
186
}
187
+ mp. seq_depth += 1 ;
188
+ mp
203
189
}
204
190
205
191
/// Adds `m` as a named match for the `idx`-th metavar.
206
192
fn push_match ( & mut self , idx : usize , m : NamedMatch ) {
207
- let matches = Lrc :: make_mut ( & mut self . matches [ idx] ) ;
208
- matches. push ( m) ;
193
+ let matches = Lrc :: make_mut ( & mut self . matches ) ;
194
+ match self . seq_depth {
195
+ 0 => {
196
+ // We are not within a sequence. Just append `m`.
197
+ assert_eq ! ( idx, matches. len( ) ) ;
198
+ matches. push ( m) ;
199
+ }
200
+ _ => {
201
+ // We are within a sequence. Find the final `MatchedSeq` at the appropriate depth
202
+ // and append `m` to its vector.
203
+ let mut curr = & mut matches[ idx] ;
204
+ for _ in 0 ..self . seq_depth - 1 {
205
+ match curr {
206
+ MatchedSeq ( seq) => {
207
+ let seq = Lrc :: make_mut ( seq) ;
208
+ curr = seq. last_mut ( ) . unwrap ( ) ;
209
+ }
210
+ _ => unreachable ! ( ) ,
211
+ }
212
+ }
213
+ match curr {
214
+ MatchedSeq ( seq) => {
215
+ let seq = Lrc :: make_mut ( seq) ;
216
+ seq. push ( m) ;
217
+ }
218
+ _ => unreachable ! ( ) ,
219
+ }
220
+ }
221
+ }
209
222
}
210
223
}
211
224
@@ -528,11 +541,8 @@ impl<'tt> TtParser<'tt> {
528
541
// sequence in `parent`. This allows for the case where the sequence matching
529
542
// is finished.
530
543
let mut new_mp = sequence. parent . clone ( ) ;
531
- for idx in mp. match_lo ..mp. match_hi {
532
- let sub = mp. matches [ idx] . clone ( ) ;
533
- new_mp. push_match ( idx, MatchedSeq ( sub) ) ;
534
- }
535
- new_mp. match_cur = mp. match_hi ;
544
+ new_mp. matches = mp. matches . clone ( ) ;
545
+ new_mp. match_cur = mp. match_lo + sequence. seq . num_captures ;
536
546
new_mp. idx += 1 ;
537
547
self . cur_mps . push ( new_mp) ;
538
548
}
@@ -577,13 +587,10 @@ impl<'tt> TtParser<'tt> {
577
587
if * token == token:: Eof {
578
588
Some ( match eof_mps {
579
589
EofMatcherPositions :: One ( mut eof_mp) => {
580
- let matches = eof_mp. matches . iter_mut ( ) . map ( |dv| {
581
- // Top-level metavars only ever get one match. (Sub-matchers can get
582
- // multiple matches, which get aggregated into a `MatcherSeq` before being
583
- // put into the top-level.)
584
- debug_assert_eq ! ( dv. len( ) , 1 ) ;
585
- Lrc :: make_mut ( dv) . pop ( ) . unwrap ( )
586
- } ) ;
590
+ assert_eq ! ( eof_mp. matches. len( ) , count_metavar_decls( matcher) ) ;
591
+ // Need to take ownership of the matches from within the `Lrc`.
592
+ Lrc :: make_mut ( & mut eof_mp. matches ) ;
593
+ let matches = Lrc :: try_unwrap ( eof_mp. matches ) . unwrap ( ) . into_iter ( ) ;
587
594
nameize ( sess, matcher, matches)
588
595
}
589
596
EofMatcherPositions :: Multiple => {
0 commit comments