Skip to content

Commit 9578e1a

Browse files
committed
Fix partially consumed tokens in macro matchers.
1 parent d34318d commit 9578e1a

File tree

3 files changed

+38
-15
lines changed

3 files changed

+38
-15
lines changed

src/libsyntax/ext/tt/macro_parser.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -476,24 +476,21 @@ pub fn parse(sess: &ParseSess,
476476
}
477477
rdr.next_token();
478478
} else /* bb_eis.len() == 1 */ {
479-
let mut rust_parser = Parser::new(sess, cfg.clone(), Box::new(rdr.clone()));
480-
481-
let mut ei = bb_eis.pop().unwrap();
482-
match ei.top_elts.get_tt(ei.idx) {
483-
TokenTree::Token(span, MatchNt(_, ident)) => {
479+
rdr.next_tok = {
480+
let mut rust_parser = Parser::new(sess, cfg.clone(), Box::new(&mut rdr));
481+
let mut ei = bb_eis.pop().unwrap();
482+
if let TokenTree::Token(span, MatchNt(_, ident)) = ei.top_elts.get_tt(ei.idx) {
484483
let match_cur = ei.match_cur;
485484
(&mut ei.matches[match_cur]).push(Rc::new(MatchedNonterminal(
486485
parse_nt(&mut rust_parser, span, &ident.name.as_str()))));
487486
ei.idx += 1;
488487
ei.match_cur += 1;
488+
} else {
489+
unreachable!()
489490
}
490-
_ => panic!()
491-
}
492-
cur_eis.push(ei);
493-
494-
for _ in 0..rust_parser.tokens_consumed {
495-
let _ = rdr.next_token();
496-
}
491+
cur_eis.push(ei);
492+
Some(TokenAndSpan { tok: rust_parser.token, sp: rust_parser.span })
493+
};
497494
}
498495
}
499496

src/libsyntax/ext/tt/transcribe.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub struct TtReader<'a> {
4848
/* cached: */
4949
pub cur_tok: Token,
5050
pub cur_span: Span,
51+
pub next_tok: Option<TokenAndSpan>,
5152
/// Transform doc comments. Only useful in macro invocations
5253
pub desugar_doc_comments: bool,
5354
pub fatal_errs: Vec<DiagnosticBuilder<'a>>,
@@ -100,6 +101,7 @@ pub fn new_tt_reader_with_doc_flag(sp_diag: &Handler,
100101
/* dummy values, never read: */
101102
cur_tok: token::Eof,
102103
cur_span: DUMMY_SP,
104+
next_tok: None,
103105
fatal_errs: Vec::new(),
104106
};
105107
tt_next_token(&mut r); /* get cur_tok and cur_span set up */
@@ -178,6 +180,9 @@ fn lockstep_iter_size(t: &TokenTree, r: &TtReader) -> LockstepIterSize {
178180
/// Return the next token from the TtReader.
179181
/// EFFECT: advances the reader's token field
180182
pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
183+
if let Some(tok) = r.next_tok.take() {
184+
return tok;
185+
}
181186
// FIXME(pcwalton): Bad copy?
182187
let ret_val = TokenAndSpan {
183188
tok: r.cur_tok.clone(),

src/libsyntax/parse/lexer/mod.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ impl<'a> Reader for StringReader<'a> {
144144

145145
impl<'a> Reader for TtReader<'a> {
146146
fn is_eof(&self) -> bool {
147-
self.cur_tok == token::Eof
147+
self.peek().tok == token::Eof
148148
}
149149
fn try_next_token(&mut self) -> Result<TokenAndSpan, ()> {
150150
assert!(self.fatal_errs.is_empty());
@@ -165,10 +165,31 @@ impl<'a> Reader for TtReader<'a> {
165165
self.fatal_errs.clear();
166166
}
167167
fn peek(&self) -> TokenAndSpan {
168-
TokenAndSpan {
168+
self.next_tok.clone().unwrap_or(TokenAndSpan {
169169
tok: self.cur_tok.clone(),
170170
sp: self.cur_span,
171-
}
171+
})
172+
}
173+
}
174+
175+
impl<'a, 'b> Reader for &'b mut TtReader<'a> {
176+
fn is_eof(&self) -> bool {
177+
(**self).is_eof()
178+
}
179+
fn try_next_token(&mut self) -> Result<TokenAndSpan, ()> {
180+
(**self).try_next_token()
181+
}
182+
fn fatal(&self, m: &str) -> FatalError {
183+
(**self).fatal(m)
184+
}
185+
fn err(&self, m: &str) {
186+
(**self).err(m)
187+
}
188+
fn emit_fatal_errors(&mut self) {
189+
(**self).emit_fatal_errors()
190+
}
191+
fn peek(&self) -> TokenAndSpan {
192+
(**self).peek()
172193
}
173194
}
174195

0 commit comments

Comments
 (0)