Skip to content

Commit 8c4960b

Browse files
committed
Remove ext::tt::transcribe::tt_next_token.
1 parent abdc689 commit 8c4960b

File tree

1 file changed

+124
-149
lines changed

1 file changed

+124
-149
lines changed

src/libsyntax/ext/tt/transcribe.rs

Lines changed: 124 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
10-
use self::LockstepIterSize::*;
1110

1211
use ast::Ident;
1312
use errors::Handler;
@@ -41,6 +40,13 @@ enum Frame {
4140
},
4241
}
4342

43+
impl Frame {
44+
fn new(tts: Vec<TokenTree>) -> Frame {
45+
let forest = Rc::new(tokenstream::Delimited { delim: token::NoDelim, tts: tts });
46+
Frame::Delimited { forest: forest, idx: 0, span: DUMMY_SP }
47+
}
48+
}
49+
4450
impl Iterator for Frame {
4551
type Item = TokenTree;
4652

@@ -75,143 +81,42 @@ impl Iterator for Frame {
7581
}
7682
}
7783

78-
struct TtReader<'a> {
79-
sp_diag: &'a Handler,
80-
/// the unzipped tree:
81-
stack: SmallVector<Frame>,
82-
/* for MBE-style macro transcription */
83-
interpolations: HashMap<Ident, Rc<NamedMatch>>,
84-
85-
repeat_idx: Vec<usize>,
86-
repeat_len: Vec<usize>,
87-
}
88-
8984
/// This can do Macro-By-Example transcription. On the other hand, if
9085
/// `src` contains no `TokenTree::Sequence`s, `MatchNt`s or `SubstNt`s, `interp` can
9186
/// (and should) be None.
9287
pub fn transcribe(sp_diag: &Handler,
9388
interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
9489
src: Vec<tokenstream::TokenTree>)
9590
-> Vec<TokenTree> {
96-
let mut r = TtReader {
97-
sp_diag: sp_diag,
98-
stack: SmallVector::one(Frame::Delimited {
99-
forest: Rc::new(tokenstream::Delimited { delim: token::NoDelim, tts: src }),
100-
idx: 0,
101-
span: DUMMY_SP,
102-
}),
103-
interpolations: match interp { /* just a convenience */
104-
None => HashMap::new(),
105-
Some(x) => x,
106-
},
107-
repeat_idx: Vec::new(),
108-
repeat_len: Vec::new(),
109-
};
110-
111-
let mut tts = Vec::new();
112-
let mut prev_span = DUMMY_SP;
113-
while let Some(tt) = tt_next_token(&mut r, prev_span) {
114-
prev_span = tt.span();
115-
tts.push(tt);
116-
}
117-
tts
118-
}
119-
120-
fn lookup_cur_matched_by_matched(r: &TtReader, start: Rc<NamedMatch>) -> Rc<NamedMatch> {
121-
r.repeat_idx.iter().fold(start, |ad, idx| {
122-
match *ad {
123-
MatchedNonterminal(_) => {
124-
// end of the line; duplicate henceforth
125-
ad.clone()
126-
}
127-
MatchedSeq(ref ads, _) => ads[*idx].clone()
128-
}
129-
})
130-
}
131-
132-
fn lookup_cur_matched(r: &TtReader, name: Ident) -> Option<Rc<NamedMatch>> {
133-
let matched_opt = r.interpolations.get(&name).cloned();
134-
matched_opt.map(|s| lookup_cur_matched_by_matched(r, s))
135-
}
136-
137-
#[derive(Clone)]
138-
enum LockstepIterSize {
139-
LisUnconstrained,
140-
LisConstraint(usize, Ident),
141-
LisContradiction(String),
142-
}
91+
let mut stack = SmallVector::one(Frame::new(src));
92+
let interpolations = interp.unwrap_or_else(HashMap::new); /* just a convenience */
93+
let mut repeat_idx = Vec::new();
94+
let mut repeat_len = Vec::new();
95+
let mut result = Vec::new();
14396

144-
impl Add for LockstepIterSize {
145-
type Output = LockstepIterSize;
146-
147-
fn add(self, other: LockstepIterSize) -> LockstepIterSize {
148-
match self {
149-
LisUnconstrained => other,
150-
LisContradiction(_) => self,
151-
LisConstraint(l_len, ref l_id) => match other {
152-
LisUnconstrained => self.clone(),
153-
LisContradiction(_) => other,
154-
LisConstraint(r_len, _) if l_len == r_len => self.clone(),
155-
LisConstraint(r_len, r_id) => {
156-
LisContradiction(format!("inconsistent lockstep iteration: \
157-
'{}' has {} items, but '{}' has {}",
158-
l_id, l_len, r_id, r_len))
159-
}
160-
},
161-
}
162-
}
163-
}
164-
165-
fn lockstep_iter_size(t: &TokenTree, r: &TtReader) -> LockstepIterSize {
166-
match *t {
167-
TokenTree::Delimited(_, ref delimed) => {
168-
delimed.tts.iter().fold(LisUnconstrained, |size, tt| {
169-
size + lockstep_iter_size(tt, r)
170-
})
171-
},
172-
TokenTree::Sequence(_, ref seq) => {
173-
seq.tts.iter().fold(LisUnconstrained, |size, tt| {
174-
size + lockstep_iter_size(tt, r)
175-
})
176-
},
177-
TokenTree::Token(_, SubstNt(name)) | TokenTree::Token(_, MatchNt(name, _)) =>
178-
match lookup_cur_matched(r, name) {
179-
Some(matched) => match *matched {
180-
MatchedNonterminal(_) => LisUnconstrained,
181-
MatchedSeq(ref ads, _) => LisConstraint(ads.len(), name),
182-
},
183-
_ => LisUnconstrained
184-
},
185-
TokenTree::Token(..) => LisUnconstrained,
186-
}
187-
}
188-
189-
/// Return the next token from the TtReader.
190-
/// EFFECT: advances the reader's token field
191-
fn tt_next_token(r: &mut TtReader, prev_span: Span) -> Option<TokenTree> {
19297
loop {
193-
let tree = match r.stack.last_mut() {
194-
Some(frame) => frame.next(),
195-
None => return None,
196-
};
197-
198-
let tree = if let Some(tree) = tree {
98+
let tree = if let Some(tree) = stack.last_mut().unwrap().next() {
19999
tree
200100
} else {
201-
if let Frame::Sequence { ref mut idx, ref sep, .. } = *r.stack.last_mut().unwrap() {
202-
if *r.repeat_idx.last().unwrap() < *r.repeat_len.last().unwrap() - 1 {
203-
*r.repeat_idx.last_mut().unwrap() += 1;
101+
if let Frame::Sequence { ref mut idx, ref sep, .. } = *stack.last_mut().unwrap() {
102+
if *repeat_idx.last().unwrap() < *repeat_len.last().unwrap() - 1 {
103+
*repeat_idx.last_mut().unwrap() += 1;
204104
*idx = 0;
205105
if let Some(sep) = sep.clone() {
206-
return Some(TokenTree::Token(prev_span, sep)); // repeat same span, I guess
106+
// repeat same span, I guess
107+
let prev_span = result.last().map(TokenTree::span).unwrap_or(DUMMY_SP);
108+
result.push(TokenTree::Token(prev_span, sep));
207109
}
208110
continue
209111
}
210112
}
211113

212-
if let Frame::Sequence { .. } = r.stack.pop().unwrap() {
213-
r.repeat_idx.pop();
214-
r.repeat_len.pop();
114+
if let Frame::Sequence { .. } = stack.pop().unwrap() {
115+
repeat_idx.pop();
116+
repeat_len.pop();
117+
}
118+
if stack.is_empty() {
119+
return result;
215120
}
216121
continue
217122
};
@@ -220,73 +125,143 @@ fn tt_next_token(r: &mut TtReader, prev_span: Span) -> Option<TokenTree> {
220125
TokenTree::Sequence(sp, seq) => {
221126
// FIXME(pcwalton): Bad copy.
222127
match lockstep_iter_size(&TokenTree::Sequence(sp, seq.clone()),
223-
r) {
224-
LisUnconstrained => {
225-
panic!(r.sp_diag.span_fatal(
128+
&interpolations,
129+
&repeat_idx) {
130+
LockstepIterSize::Unconstrained => {
131+
panic!(sp_diag.span_fatal(
226132
sp.clone(), /* blame macro writer */
227133
"attempted to repeat an expression \
228134
containing no syntax \
229135
variables matched as repeating at this depth"));
230136
}
231-
LisContradiction(ref msg) => {
137+
LockstepIterSize::Contradiction(ref msg) => {
232138
// FIXME #2887 blame macro invoker instead
233-
panic!(r.sp_diag.span_fatal(sp.clone(), &msg[..]));
139+
panic!(sp_diag.span_fatal(sp.clone(), &msg[..]));
234140
}
235-
LisConstraint(len, _) => {
141+
LockstepIterSize::Constraint(len, _) => {
236142
if len == 0 {
237143
if seq.op == tokenstream::KleeneOp::OneOrMore {
238144
// FIXME #2887 blame invoker
239-
panic!(r.sp_diag.span_fatal(sp.clone(),
240-
"this must repeat at least once"));
145+
panic!(sp_diag.span_fatal(sp.clone(),
146+
"this must repeat at least once"));
241147
}
242-
243-
return tt_next_token(r, prev_span);
148+
} else {
149+
repeat_len.push(len);
150+
repeat_idx.push(0);
151+
stack.push(Frame::Sequence {
152+
idx: 0,
153+
sep: seq.separator.clone(),
154+
forest: seq,
155+
});
244156
}
245-
r.repeat_len.push(len);
246-
r.repeat_idx.push(0);
247-
r.stack.push(Frame::Sequence {
248-
idx: 0,
249-
sep: seq.separator.clone(),
250-
forest: seq,
251-
});
252157
}
253158
}
254159
}
255160
// FIXME #2887: think about span stuff here
256161
TokenTree::Token(sp, SubstNt(ident)) => {
257-
match lookup_cur_matched(r, ident) {
258-
None => {
259-
return Some(TokenTree::Token(sp, SubstNt(ident)));
260-
// this can't be 0 length, just like TokenTree::Delimited
261-
}
162+
match lookup_cur_matched(ident, &interpolations, &repeat_idx) {
163+
None => result.push(TokenTree::Token(sp, SubstNt(ident))),
262164
Some(cur_matched) => if let MatchedNonterminal(ref nt) = *cur_matched {
263165
match **nt {
264166
// sidestep the interpolation tricks for ident because
265167
// (a) idents can be in lots of places, so it'd be a pain
266168
// (b) we actually can, since it's a token.
267169
NtIdent(ref sn) => {
268-
return Some(TokenTree::Token(sn.span, token::Ident(sn.node)));
170+
result.push(TokenTree::Token(sn.span, token::Ident(sn.node)));
269171
}
270-
NtTT(ref tt) => return Some(tt.clone()),
172+
NtTT(ref tt) => result.push(tt.clone()),
271173
_ => {
272174
// FIXME(pcwalton): Bad copy
273-
return Some(TokenTree::Token(sp, token::Interpolated(nt.clone())));
175+
result.push(TokenTree::Token(sp, token::Interpolated(nt.clone())));
274176
}
275177
}
276178
} else {
277-
panic!(r.sp_diag.span_fatal(
179+
panic!(sp_diag.span_fatal(
278180
sp, /* blame the macro writer */
279181
&format!("variable '{}' is still repeating at this depth", ident)));
280182
}
281183
}
282184
}
283185
TokenTree::Delimited(span, delimited) => {
284-
r.stack.push(Frame::Delimited { forest: delimited, idx: 0, span: span });
186+
stack.push(Frame::Delimited { forest: delimited, idx: 0, span: span });
285187
}
286188
TokenTree::Token(span, MatchNt(name, kind)) => {
287-
r.stack.push(Frame::MatchNt { name: name, kind: kind, idx: 0, span: span });
189+
stack.push(Frame::MatchNt { name: name, kind: kind, idx: 0, span: span });
288190
}
289-
tt @ TokenTree::Token(..) => return Some(tt),
191+
tt @ TokenTree::Token(..) => result.push(tt),
290192
}
291193
}
292194
}
195+
196+
fn lookup_cur_matched(ident: Ident,
197+
interpolations: &HashMap<Ident, Rc<NamedMatch>>,
198+
repeat_idx: &[usize])
199+
-> Option<Rc<NamedMatch>> {
200+
interpolations.get(&ident).map(|matched| {
201+
repeat_idx.iter().fold(matched.clone(), |ad, idx| {
202+
match *ad {
203+
MatchedNonterminal(_) => {
204+
// end of the line; duplicate henceforth
205+
ad.clone()
206+
}
207+
MatchedSeq(ref ads, _) => ads[*idx].clone()
208+
}
209+
})
210+
})
211+
}
212+
213+
#[derive(Clone)]
214+
enum LockstepIterSize {
215+
Unconstrained,
216+
Constraint(usize, Ident),
217+
Contradiction(String),
218+
}
219+
220+
impl Add for LockstepIterSize {
221+
type Output = LockstepIterSize;
222+
223+
fn add(self, other: LockstepIterSize) -> LockstepIterSize {
224+
match self {
225+
LockstepIterSize::Unconstrained => other,
226+
LockstepIterSize::Contradiction(_) => self,
227+
LockstepIterSize::Constraint(l_len, ref l_id) => match other {
228+
LockstepIterSize::Unconstrained => self.clone(),
229+
LockstepIterSize::Contradiction(_) => other,
230+
LockstepIterSize::Constraint(r_len, _) if l_len == r_len => self.clone(),
231+
LockstepIterSize::Constraint(r_len, r_id) => {
232+
let msg = format!("inconsistent lockstep iteration: \
233+
'{}' has {} items, but '{}' has {}",
234+
l_id, l_len, r_id, r_len);
235+
LockstepIterSize::Contradiction(msg)
236+
}
237+
},
238+
}
239+
}
240+
}
241+
242+
fn lockstep_iter_size(tree: &TokenTree,
243+
interpolations: &HashMap<Ident, Rc<NamedMatch>>,
244+
repeat_idx: &[usize])
245+
-> LockstepIterSize {
246+
match *tree {
247+
TokenTree::Delimited(_, ref delimed) => {
248+
delimed.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| {
249+
size + lockstep_iter_size(tt, interpolations, repeat_idx)
250+
})
251+
},
252+
TokenTree::Sequence(_, ref seq) => {
253+
seq.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| {
254+
size + lockstep_iter_size(tt, interpolations, repeat_idx)
255+
})
256+
},
257+
TokenTree::Token(_, SubstNt(name)) | TokenTree::Token(_, MatchNt(name, _)) =>
258+
match lookup_cur_matched(name, interpolations, repeat_idx) {
259+
Some(matched) => match *matched {
260+
MatchedNonterminal(_) => LockstepIterSize::Unconstrained,
261+
MatchedSeq(ref ads, _) => LockstepIterSize::Constraint(ads.len(), name),
262+
},
263+
_ => LockstepIterSize::Unconstrained
264+
},
265+
TokenTree::Token(..) => LockstepIterSize::Unconstrained,
266+
}
267+
}

0 commit comments

Comments
 (0)