diff options
| author | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2017-01-27 13:21:20 +0000 |
|---|---|---|
| committer | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2017-02-28 22:13:38 +0000 |
| commit | 8c4960bfde5c18d119f5d6398bbca04640298164 (patch) | |
| tree | 90f9dc5440e05630df0041fe7adbb2b3ddc16ed8 | |
| parent | abdc68973ea5961c3e942c7176c2894d00c547d7 (diff) | |
| download | rust-8c4960bfde5c18d119f5d6398bbca04640298164.tar.gz rust-8c4960bfde5c18d119f5d6398bbca04640298164.zip | |
Remove `ext::tt::transcribe::tt_next_token`.
| -rw-r--r-- | src/libsyntax/ext/tt/transcribe.rs | 273 |
1 files changed, 124 insertions, 149 deletions
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 9f3d937b056..fce89d06216 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -7,7 +7,6 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. -use self::LockstepIterSize::*; use ast::Ident; use errors::Handler; @@ -41,6 +40,13 @@ enum Frame { }, } +impl Frame { + fn new(tts: Vec<TokenTree>) -> Frame { + let forest = Rc::new(tokenstream::Delimited { delim: token::NoDelim, tts: tts }); + Frame::Delimited { forest: forest, idx: 0, span: DUMMY_SP } + } +} + impl Iterator for Frame { type Item = TokenTree; @@ -75,17 +81,6 @@ impl Iterator for Frame { } } -struct TtReader<'a> { - sp_diag: &'a Handler, - /// the unzipped tree: - stack: SmallVector<Frame>, - /* for MBE-style macro transcription */ - interpolations: HashMap<Ident, Rc<NamedMatch>>, - - repeat_idx: Vec<usize>, - repeat_len: Vec<usize>, -} - /// This can do Macro-By-Example transcription. On the other hand, if /// `src` contains no `TokenTree::Sequence`s, `MatchNt`s or `SubstNt`s, `interp` can /// (and should) be None. @@ -93,125 +88,35 @@ pub fn transcribe(sp_diag: &Handler, interp: Option<HashMap<Ident, Rc<NamedMatch>>>, src: Vec<tokenstream::TokenTree>) -> Vec<TokenTree> { - let mut r = TtReader { - sp_diag: sp_diag, - stack: SmallVector::one(Frame::Delimited { - forest: Rc::new(tokenstream::Delimited { delim: token::NoDelim, tts: src }), - idx: 0, - span: DUMMY_SP, - }), - interpolations: match interp { /* just a convenience */ - None => HashMap::new(), - Some(x) => x, - }, - repeat_idx: Vec::new(), - repeat_len: Vec::new(), - }; - - let mut tts = Vec::new(); - let mut prev_span = DUMMY_SP; - while let Some(tt) = tt_next_token(&mut r, prev_span) { - prev_span = tt.span(); - tts.push(tt); - } - tts -} - -fn lookup_cur_matched_by_matched(r: &TtReader, start: Rc<NamedMatch>) -> Rc<NamedMatch> { - r.repeat_idx.iter().fold(start, |ad, idx| { - match *ad { - MatchedNonterminal(_) => { - // end of the line; duplicate henceforth - ad.clone() - } - MatchedSeq(ref ads, _) => ads[*idx].clone() - } - }) -} - -fn lookup_cur_matched(r: &TtReader, name: Ident) -> Option<Rc<NamedMatch>> { - let matched_opt = r.interpolations.get(&name).cloned(); - matched_opt.map(|s| lookup_cur_matched_by_matched(r, s)) -} - -#[derive(Clone)] -enum LockstepIterSize { - LisUnconstrained, - LisConstraint(usize, Ident), - LisContradiction(String), -} + let mut stack = SmallVector::one(Frame::new(src)); + let interpolations = interp.unwrap_or_else(HashMap::new); /* just a convenience */ + let mut repeat_idx = Vec::new(); + let mut repeat_len = Vec::new(); + let mut result = Vec::new(); -impl Add for LockstepIterSize { - type Output = LockstepIterSize; - - fn add(self, other: LockstepIterSize) -> LockstepIterSize { - match self { - LisUnconstrained => other, - LisContradiction(_) => self, - LisConstraint(l_len, ref l_id) => match other { - LisUnconstrained => self.clone(), - LisContradiction(_) => other, - LisConstraint(r_len, _) if l_len == r_len => self.clone(), - LisConstraint(r_len, r_id) => { - LisContradiction(format!("inconsistent lockstep iteration: \ - '{}' has {} items, but '{}' has {}", - l_id, l_len, r_id, r_len)) - } - }, - } - } -} - -fn lockstep_iter_size(t: &TokenTree, r: &TtReader) -> LockstepIterSize { - match *t { - TokenTree::Delimited(_, ref delimed) => { - delimed.tts.iter().fold(LisUnconstrained, |size, tt| { - size + lockstep_iter_size(tt, r) - }) - }, - TokenTree::Sequence(_, ref seq) => { - seq.tts.iter().fold(LisUnconstrained, |size, tt| { - size + lockstep_iter_size(tt, r) - }) - }, - TokenTree::Token(_, SubstNt(name)) | TokenTree::Token(_, MatchNt(name, _)) => - match lookup_cur_matched(r, name) { - Some(matched) => match *matched { - MatchedNonterminal(_) => LisUnconstrained, - MatchedSeq(ref ads, _) => LisConstraint(ads.len(), name), - }, - _ => LisUnconstrained - }, - TokenTree::Token(..) => LisUnconstrained, - } -} - -/// Return the next token from the TtReader. -/// EFFECT: advances the reader's token field -fn tt_next_token(r: &mut TtReader, prev_span: Span) -> Option<TokenTree> { loop { - let tree = match r.stack.last_mut() { - Some(frame) => frame.next(), - None => return None, - }; - - let tree = if let Some(tree) = tree { + let tree = if let Some(tree) = stack.last_mut().unwrap().next() { tree } else { - if let Frame::Sequence { ref mut idx, ref sep, .. } = *r.stack.last_mut().unwrap() { - if *r.repeat_idx.last().unwrap() < *r.repeat_len.last().unwrap() - 1 { - *r.repeat_idx.last_mut().unwrap() += 1; + if let Frame::Sequence { ref mut idx, ref sep, .. } = *stack.last_mut().unwrap() { + if *repeat_idx.last().unwrap() < *repeat_len.last().unwrap() - 1 { + *repeat_idx.last_mut().unwrap() += 1; *idx = 0; if let Some(sep) = sep.clone() { - return Some(TokenTree::Token(prev_span, sep)); // repeat same span, I guess + // repeat same span, I guess + let prev_span = result.last().map(TokenTree::span).unwrap_or(DUMMY_SP); + result.push(TokenTree::Token(prev_span, sep)); } continue } } - if let Frame::Sequence { .. } = r.stack.pop().unwrap() { - r.repeat_idx.pop(); - r.repeat_len.pop(); + if let Frame::Sequence { .. } = stack.pop().unwrap() { + repeat_idx.pop(); + repeat_len.pop(); + } + if stack.is_empty() { + return result; } continue }; @@ -220,73 +125,143 @@ fn tt_next_token(r: &mut TtReader, prev_span: Span) -> Option<TokenTree> { TokenTree::Sequence(sp, seq) => { // FIXME(pcwalton): Bad copy. match lockstep_iter_size(&TokenTree::Sequence(sp, seq.clone()), - r) { - LisUnconstrained => { - panic!(r.sp_diag.span_fatal( + &interpolations, + &repeat_idx) { + LockstepIterSize::Unconstrained => { + panic!(sp_diag.span_fatal( sp.clone(), /* blame macro writer */ "attempted to repeat an expression \ containing no syntax \ variables matched as repeating at this depth")); } - LisContradiction(ref msg) => { + LockstepIterSize::Contradiction(ref msg) => { // FIXME #2887 blame macro invoker instead - panic!(r.sp_diag.span_fatal(sp.clone(), &msg[..])); + panic!(sp_diag.span_fatal(sp.clone(), &msg[..])); } - LisConstraint(len, _) => { + LockstepIterSize::Constraint(len, _) => { if len == 0 { if seq.op == tokenstream::KleeneOp::OneOrMore { // FIXME #2887 blame invoker - panic!(r.sp_diag.span_fatal(sp.clone(), - "this must repeat at least once")); + panic!(sp_diag.span_fatal(sp.clone(), + "this must repeat at least once")); } - - return tt_next_token(r, prev_span); + } else { + repeat_len.push(len); + repeat_idx.push(0); + stack.push(Frame::Sequence { + idx: 0, + sep: seq.separator.clone(), + forest: seq, + }); } - r.repeat_len.push(len); - r.repeat_idx.push(0); - r.stack.push(Frame::Sequence { - idx: 0, - sep: seq.separator.clone(), - forest: seq, - }); } } } // FIXME #2887: think about span stuff here TokenTree::Token(sp, SubstNt(ident)) => { - match lookup_cur_matched(r, ident) { - None => { - return Some(TokenTree::Token(sp, SubstNt(ident))); - // this can't be 0 length, just like TokenTree::Delimited - } + match lookup_cur_matched(ident, &interpolations, &repeat_idx) { + None => result.push(TokenTree::Token(sp, SubstNt(ident))), Some(cur_matched) => if let MatchedNonterminal(ref nt) = *cur_matched { match **nt { // sidestep the interpolation tricks for ident because // (a) idents can be in lots of places, so it'd be a pain // (b) we actually can, since it's a token. NtIdent(ref sn) => { - return Some(TokenTree::Token(sn.span, token::Ident(sn.node))); + result.push(TokenTree::Token(sn.span, token::Ident(sn.node))); } - NtTT(ref tt) => return Some(tt.clone()), + NtTT(ref tt) => result.push(tt.clone()), _ => { // FIXME(pcwalton): Bad copy - return Some(TokenTree::Token(sp, token::Interpolated(nt.clone()))); + result.push(TokenTree::Token(sp, token::Interpolated(nt.clone()))); } } } else { - panic!(r.sp_diag.span_fatal( + panic!(sp_diag.span_fatal( sp, /* blame the macro writer */ &format!("variable '{}' is still repeating at this depth", ident))); } } } TokenTree::Delimited(span, delimited) => { - r.stack.push(Frame::Delimited { forest: delimited, idx: 0, span: span }); + stack.push(Frame::Delimited { forest: delimited, idx: 0, span: span }); } TokenTree::Token(span, MatchNt(name, kind)) => { - r.stack.push(Frame::MatchNt { name: name, kind: kind, idx: 0, span: span }); + stack.push(Frame::MatchNt { name: name, kind: kind, idx: 0, span: span }); } - tt @ TokenTree::Token(..) => return Some(tt), + tt @ TokenTree::Token(..) => result.push(tt), } } } + +fn lookup_cur_matched(ident: Ident, + interpolations: &HashMap<Ident, Rc<NamedMatch>>, + repeat_idx: &[usize]) + -> Option<Rc<NamedMatch>> { + interpolations.get(&ident).map(|matched| { + repeat_idx.iter().fold(matched.clone(), |ad, idx| { + match *ad { + MatchedNonterminal(_) => { + // end of the line; duplicate henceforth + ad.clone() + } + MatchedSeq(ref ads, _) => ads[*idx].clone() + } + }) + }) +} + +#[derive(Clone)] +enum LockstepIterSize { + Unconstrained, + Constraint(usize, Ident), + Contradiction(String), +} + +impl Add for LockstepIterSize { + type Output = LockstepIterSize; + + fn add(self, other: LockstepIterSize) -> LockstepIterSize { + match self { + LockstepIterSize::Unconstrained => other, + LockstepIterSize::Contradiction(_) => self, + LockstepIterSize::Constraint(l_len, ref l_id) => match other { + LockstepIterSize::Unconstrained => self.clone(), + LockstepIterSize::Contradiction(_) => other, + LockstepIterSize::Constraint(r_len, _) if l_len == r_len => self.clone(), + LockstepIterSize::Constraint(r_len, r_id) => { + let msg = format!("inconsistent lockstep iteration: \ + '{}' has {} items, but '{}' has {}", + l_id, l_len, r_id, r_len); + LockstepIterSize::Contradiction(msg) + } + }, + } + } +} + +fn lockstep_iter_size(tree: &TokenTree, + interpolations: &HashMap<Ident, Rc<NamedMatch>>, + repeat_idx: &[usize]) + -> LockstepIterSize { + match *tree { + TokenTree::Delimited(_, ref delimed) => { + delimed.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| { + size + lockstep_iter_size(tt, interpolations, repeat_idx) + }) + }, + TokenTree::Sequence(_, ref seq) => { + seq.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| { + size + lockstep_iter_size(tt, interpolations, repeat_idx) + }) + }, + TokenTree::Token(_, SubstNt(name)) | TokenTree::Token(_, MatchNt(name, _)) => + match lookup_cur_matched(name, interpolations, repeat_idx) { + Some(matched) => match *matched { + MatchedNonterminal(_) => LockstepIterSize::Unconstrained, + MatchedSeq(ref ads, _) => LockstepIterSize::Constraint(ads.len(), name), + }, + _ => LockstepIterSize::Unconstrained + }, + TokenTree::Token(..) => LockstepIterSize::Unconstrained, + } +} |
