Skip to content

Commit 65ff4ca

Browse files
committed
Refactor parser lookahead buffer and increase its size
1 parent 7bccb82 commit 65ff4ca

File tree

2 files changed

+41
-38
lines changed

2 files changed

+41
-38
lines changed

src/libsyntax/parse/lexer/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ pub struct TokenAndSpan {
7474
pub sp: Span,
7575
}
7676

77+
impl Default for TokenAndSpan {
78+
fn default() -> Self {
79+
TokenAndSpan { tok: token::Underscore, sp: syntax_pos::DUMMY_SP }
80+
}
81+
}
82+
7783
pub struct StringReader<'a> {
7884
pub span_diagnostic: &'a Handler,
7985
/// The absolute offset within the codemap of the next character to read

src/libsyntax/parse/parser.rs

Lines changed: 35 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,22 @@ enum PrevTokenKind {
245245
Other,
246246
}
247247

248+
// Simple circular buffer used for keeping few next tokens.
249+
#[derive(Default)]
250+
struct LookaheadBuffer {
251+
buffer: [TokenAndSpan; LOOKAHEAD_BUFFER_CAPACITY],
252+
start: usize,
253+
end: usize,
254+
}
255+
256+
const LOOKAHEAD_BUFFER_CAPACITY: usize = 8;
257+
258+
impl LookaheadBuffer {
259+
fn len(&self) -> usize {
260+
(LOOKAHEAD_BUFFER_CAPACITY + self.end - self.start) % LOOKAHEAD_BUFFER_CAPACITY
261+
}
262+
}
263+
248264
/* ident is handled by common.rs */
249265

250266
pub struct Parser<'a> {
@@ -258,9 +274,7 @@ pub struct Parser<'a> {
258274
pub cfg: CrateConfig,
259275
/// the previous token kind
260276
prev_token_kind: PrevTokenKind,
261-
pub buffer: [TokenAndSpan; 4],
262-
pub buffer_start: isize,
263-
pub buffer_end: isize,
277+
lookahead_buffer: LookaheadBuffer,
264278
pub tokens_consumed: usize,
265279
pub restrictions: Restrictions,
266280
pub quote_depth: usize, // not (yet) related to the quasiquoter
@@ -356,10 +370,6 @@ impl<'a> Parser<'a> {
356370
_ => PathBuf::from(sess.codemap().span_to_filename(span)),
357371
};
358372
directory.pop();
359-
let placeholder = TokenAndSpan {
360-
tok: token::Underscore,
361-
sp: span,
362-
};
363373

364374
Parser {
365375
reader: rdr,
@@ -369,14 +379,7 @@ impl<'a> Parser<'a> {
369379
span: span,
370380
prev_span: span,
371381
prev_token_kind: PrevTokenKind::Other,
372-
buffer: [
373-
placeholder.clone(),
374-
placeholder.clone(),
375-
placeholder.clone(),
376-
placeholder.clone(),
377-
],
378-
buffer_start: 0,
379-
buffer_end: 0,
382+
lookahead_buffer: Default::default(),
380383
tokens_consumed: 0,
381384
restrictions: Restrictions::empty(),
382385
quote_depth: 0,
@@ -937,19 +940,13 @@ impl<'a> Parser<'a> {
937940
_ => PrevTokenKind::Other,
938941
};
939942

940-
let next = if self.buffer_start == self.buffer_end {
943+
let next = if self.lookahead_buffer.start == self.lookahead_buffer.end {
941944
self.reader.real_token()
942945
} else {
943946
// Avoid token copies with `replace`.
944-
let buffer_start = self.buffer_start as usize;
945-
let next_index = (buffer_start + 1) & 3;
946-
self.buffer_start = next_index as isize;
947-
948-
let placeholder = TokenAndSpan {
949-
tok: token::Underscore,
950-
sp: self.span,
951-
};
952-
mem::replace(&mut self.buffer[buffer_start], placeholder)
947+
let old_start = self.lookahead_buffer.start;
948+
self.lookahead_buffer.start = (old_start + 1) % LOOKAHEAD_BUFFER_CAPACITY;
949+
mem::replace(&mut self.lookahead_buffer.buffer[old_start], Default::default())
953950
};
954951
self.span = next.sp;
955952
self.token = next.tok;
@@ -982,21 +979,22 @@ impl<'a> Parser<'a> {
982979
self.expected_tokens.clear();
983980
}
984981

985-
pub fn buffer_length(&mut self) -> isize {
986-
if self.buffer_start <= self.buffer_end {
987-
return self.buffer_end - self.buffer_start;
988-
}
989-
return (4 - self.buffer_start) + self.buffer_end;
990-
}
991-
pub fn look_ahead<R, F>(&mut self, distance: usize, f: F) -> R where
982+
pub fn look_ahead<R, F>(&mut self, dist: usize, f: F) -> R where
992983
F: FnOnce(&token::Token) -> R,
993984
{
994-
let dist = distance as isize;
995-
while self.buffer_length() < dist {
996-
self.buffer[self.buffer_end as usize] = self.reader.real_token();
997-
self.buffer_end = (self.buffer_end + 1) & 3;
985+
if dist == 0 {
986+
f(&self.token)
987+
} else if dist < LOOKAHEAD_BUFFER_CAPACITY {
988+
while self.lookahead_buffer.len() < dist {
989+
self.lookahead_buffer.buffer[self.lookahead_buffer.end] = self.reader.real_token();
990+
self.lookahead_buffer.end =
991+
(self.lookahead_buffer.end + 1) % LOOKAHEAD_BUFFER_CAPACITY;
992+
}
993+
let index = (self.lookahead_buffer.start + dist - 1) % LOOKAHEAD_BUFFER_CAPACITY;
994+
f(&self.lookahead_buffer.buffer[index].tok)
995+
} else {
996+
self.bug("lookahead distance is too large");
998997
}
999-
f(&self.buffer[((self.buffer_start + dist - 1) & 3) as usize].tok)
1000998
}
1001999
pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> {
10021000
self.sess.span_diagnostic.struct_span_fatal(self.span, m)
@@ -1118,7 +1116,6 @@ impl<'a> Parser<'a> {
11181116
Ok(ast::TyKind::ImplTrait(bounds))
11191117
}
11201118

1121-
11221119
pub fn parse_ty_path(&mut self) -> PResult<'a, TyKind> {
11231120
Ok(TyKind::Path(None, self.parse_path(PathStyle::Type)?))
11241121
}

0 commit comments

Comments
 (0)