Other,
}
+// Simple circular buffer used for keeping few next tokens.
+#[derive(Default)]
+struct LookaheadBuffer {
+ buffer: [TokenAndSpan; LOOKAHEAD_BUFFER_CAPACITY],
+ start: usize,
+ end: usize,
+}
+
+const LOOKAHEAD_BUFFER_CAPACITY: usize = 8;
+
+impl LookaheadBuffer {
+ fn len(&self) -> usize {
+ (LOOKAHEAD_BUFFER_CAPACITY + self.end - self.start) % LOOKAHEAD_BUFFER_CAPACITY
+ }
+}
+
/* ident is handled by common.rs */
pub struct Parser<'a> {
pub cfg: CrateConfig,
/// the previous token kind
prev_token_kind: PrevTokenKind,
- pub buffer: [TokenAndSpan; 4],
- pub buffer_start: isize,
- pub buffer_end: isize,
+ lookahead_buffer: LookaheadBuffer,
pub tokens_consumed: usize,
pub restrictions: Restrictions,
pub quote_depth: usize, // not (yet) related to the quasiquoter
_ => PathBuf::from(sess.codemap().span_to_filename(span)),
};
directory.pop();
- let placeholder = TokenAndSpan {
- tok: token::Underscore,
- sp: span,
- };
Parser {
reader: rdr,
span: span,
prev_span: span,
prev_token_kind: PrevTokenKind::Other,
- buffer: [
- placeholder.clone(),
- placeholder.clone(),
- placeholder.clone(),
- placeholder.clone(),
- ],
- buffer_start: 0,
- buffer_end: 0,
+ lookahead_buffer: Default::default(),
tokens_consumed: 0,
restrictions: Restrictions::empty(),
quote_depth: 0,
_ => PrevTokenKind::Other,
};
- let next = if self.buffer_start == self.buffer_end {
+ let next = if self.lookahead_buffer.start == self.lookahead_buffer.end {
self.reader.real_token()
} else {
// Avoid token copies with `replace`.
- let buffer_start = self.buffer_start as usize;
- let next_index = (buffer_start + 1) & 3;
- self.buffer_start = next_index as isize;
-
- let placeholder = TokenAndSpan {
- tok: token::Underscore,
- sp: self.span,
- };
- mem::replace(&mut self.buffer[buffer_start], placeholder)
+ let old_start = self.lookahead_buffer.start;
+ self.lookahead_buffer.start = (old_start + 1) % LOOKAHEAD_BUFFER_CAPACITY;
+ mem::replace(&mut self.lookahead_buffer.buffer[old_start], Default::default())
};
self.span = next.sp;
self.token = next.tok;
self.expected_tokens.clear();
}
- pub fn buffer_length(&mut self) -> isize {
- if self.buffer_start <= self.buffer_end {
- return self.buffer_end - self.buffer_start;
- }
- return (4 - self.buffer_start) + self.buffer_end;
- }
- pub fn look_ahead<R, F>(&mut self, distance: usize, f: F) -> R where
+ pub fn look_ahead<R, F>(&mut self, dist: usize, f: F) -> R where
F: FnOnce(&token::Token) -> R,
{
- let dist = distance as isize;
- while self.buffer_length() < dist {
- self.buffer[self.buffer_end as usize] = self.reader.real_token();
- self.buffer_end = (self.buffer_end + 1) & 3;
+ if dist == 0 {
+ f(&self.token)
+ } else if dist < LOOKAHEAD_BUFFER_CAPACITY {
+ while self.lookahead_buffer.len() < dist {
+ self.lookahead_buffer.buffer[self.lookahead_buffer.end] = self.reader.real_token();
+ self.lookahead_buffer.end =
+ (self.lookahead_buffer.end + 1) % LOOKAHEAD_BUFFER_CAPACITY;
+ }
+ let index = (self.lookahead_buffer.start + dist - 1) % LOOKAHEAD_BUFFER_CAPACITY;
+ f(&self.lookahead_buffer.buffer[index].tok)
+ } else {
+ self.bug("lookahead distance is too large");
}
- f(&self.buffer[((self.buffer_start + dist - 1) & 3) as usize].tok)
}
pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> {
self.sess.span_diagnostic.struct_span_fatal(self.span, m)
Ok(ast::TyKind::ImplTrait(bounds))
}
-
pub fn parse_ty_path(&mut self) -> PResult<'a, TyKind> {
Ok(TyKind::Path(None, self.parse_path(PathStyle::Type)?))
}