about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>2017-01-27 13:21:20 +0000
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>2017-02-28 22:13:38 +0000
commit8c4960bfde5c18d119f5d6398bbca04640298164 (patch)
tree90f9dc5440e05630df0041fe7adbb2b3ddc16ed8
parentabdc68973ea5961c3e942c7176c2894d00c547d7 (diff)
downloadrust-8c4960bfde5c18d119f5d6398bbca04640298164.tar.gz
rust-8c4960bfde5c18d119f5d6398bbca04640298164.zip
Remove `ext::tt::transcribe::tt_next_token`.
-rw-r--r--src/libsyntax/ext/tt/transcribe.rs273
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,
+    }
+}