Skip to content

Commit 7854e9e

Browse files
Rollup merge of #62329 - matklad:no-peeking, r=petrochenkov
Remove support for 1-token lookahead from the lexer `StringReader` maintained `peek_token` and `peek_span_src_raw` for look ahead. `peek_token` was used only by rustdoc syntax coloring. After moving peeking logic into highlighter, I was able to remove `peek_token` from the lexer. I tried to use `iter::Peekable`, but that wasn't as pretty as I hoped, due to buffered fatal errors. So I went with hand-rolled peeking. After that I've noticed that the only peeking behavior left was for raw tokens to test tt jointness. I've rewritten it in terms of trivia tokens, and not just spans. After that it became possible to simplify the awkward constructor of the lexer, which could return `Err` if the first peeked token contained error.
2 parents 99366a9 + 3e362a4 commit 7854e9e

File tree

7 files changed

+129
-180
lines changed

7 files changed

+129
-180
lines changed

src/librustc_save_analysis/span_utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ impl<'a> SpanUtils<'a> {
5353
pub fn sub_span_of_token(&self, span: Span, tok: TokenKind) -> Option<Span> {
5454
let mut toks = self.retokenise_span(span);
5555
loop {
56-
let next = toks.real_token();
56+
let next = toks.next_token();
5757
if next == token::Eof {
5858
return None;
5959
}

src/librustdoc/html/highlight.rs

+31-20
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,17 @@ pub fn render_with_highlighting(
3838
FileName::Custom(String::from("rustdoc-highlighting")),
3939
src.to_owned(),
4040
);
41-
let highlight_result =
42-
lexer::StringReader::new_or_buffered_errs(&sess, fm, None).and_then(|lexer| {
43-
let mut classifier = Classifier::new(lexer, sess.source_map());
44-
45-
let mut highlighted_source = vec![];
46-
if classifier.write_source(&mut highlighted_source).is_err() {
47-
Err(classifier.lexer.buffer_fatal_errors())
48-
} else {
49-
Ok(String::from_utf8_lossy(&highlighted_source).into_owned())
50-
}
51-
});
41+
let highlight_result = {
42+
let lexer = lexer::StringReader::new(&sess, fm, None);
43+
let mut classifier = Classifier::new(lexer, sess.source_map());
44+
45+
let mut highlighted_source = vec![];
46+
if classifier.write_source(&mut highlighted_source).is_err() {
47+
Err(classifier.lexer.buffer_fatal_errors())
48+
} else {
49+
Ok(String::from_utf8_lossy(&highlighted_source).into_owned())
50+
}
51+
};
5252

5353
match highlight_result {
5454
Ok(highlighted_source) => {
@@ -79,6 +79,7 @@ pub fn render_with_highlighting(
7979
/// each span of text in sequence.
8080
struct Classifier<'a> {
8181
lexer: lexer::StringReader<'a>,
82+
peek_token: Option<Token>,
8283
source_map: &'a SourceMap,
8384

8485
// State of the classifier.
@@ -178,6 +179,7 @@ impl<'a> Classifier<'a> {
178179
fn new(lexer: lexer::StringReader<'a>, source_map: &'a SourceMap) -> Classifier<'a> {
179180
Classifier {
180181
lexer,
182+
peek_token: None,
181183
source_map,
182184
in_attribute: false,
183185
in_macro: false,
@@ -187,10 +189,19 @@ impl<'a> Classifier<'a> {
187189

188190
/// Gets the next token out of the lexer.
189191
fn try_next_token(&mut self) -> Result<Token, HighlightError> {
190-
match self.lexer.try_next_token() {
191-
Ok(token) => Ok(token),
192-
Err(_) => Err(HighlightError::LexError),
192+
if let Some(token) = self.peek_token.take() {
193+
return Ok(token);
194+
}
195+
self.lexer.try_next_token().map_err(|()| HighlightError::LexError)
196+
}
197+
198+
fn peek(&mut self) -> Result<&Token, HighlightError> {
199+
if self.peek_token.is_none() {
200+
self.peek_token = Some(
201+
self.lexer.try_next_token().map_err(|()| HighlightError::LexError)?
202+
);
193203
}
204+
Ok(self.peek_token.as_ref().unwrap())
194205
}
195206

196207
/// Exhausts the `lexer` writing the output into `out`.
@@ -234,7 +245,7 @@ impl<'a> Classifier<'a> {
234245
// reference or dereference operator or a reference or pointer type, instead of the
235246
// bit-and or multiplication operator.
236247
token::BinOp(token::And) | token::BinOp(token::Star)
237-
if self.lexer.peek() != &token::Whitespace => Class::RefKeyWord,
248+
if self.peek()? != &token::Whitespace => Class::RefKeyWord,
238249

239250
// Consider this as part of a macro invocation if there was a
240251
// leading identifier.
@@ -257,7 +268,7 @@ impl<'a> Classifier<'a> {
257268
token::Question => Class::QuestionMark,
258269

259270
token::Dollar => {
260-
if self.lexer.peek().is_ident() {
271+
if self.peek()?.is_ident() {
261272
self.in_macro_nonterminal = true;
262273
Class::MacroNonTerminal
263274
} else {
@@ -280,9 +291,9 @@ impl<'a> Classifier<'a> {
280291
// as an attribute.
281292

282293
// Case 1: #![inner_attribute]
283-
if self.lexer.peek() == &token::Not {
294+
if self.peek()? == &token::Not {
284295
self.try_next_token()?; // NOTE: consumes `!` token!
285-
if self.lexer.peek() == &token::OpenDelim(token::Bracket) {
296+
if self.peek()? == &token::OpenDelim(token::Bracket) {
286297
self.in_attribute = true;
287298
out.enter_span(Class::Attribute)?;
288299
}
@@ -292,7 +303,7 @@ impl<'a> Classifier<'a> {
292303
}
293304

294305
// Case 2: #[outer_attribute]
295-
if self.lexer.peek() == &token::OpenDelim(token::Bracket) {
306+
if self.peek()? == &token::OpenDelim(token::Bracket) {
296307
self.in_attribute = true;
297308
out.enter_span(Class::Attribute)?;
298309
}
@@ -341,7 +352,7 @@ impl<'a> Classifier<'a> {
341352
if self.in_macro_nonterminal {
342353
self.in_macro_nonterminal = false;
343354
Class::MacroNonTerminal
344-
} else if self.lexer.peek() == &token::Not {
355+
} else if self.peek()? == &token::Not {
345356
self.in_macro = true;
346357
Class::Macro
347358
} else {

src/librustdoc/passes/check_code_block_syntax.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
3232
dox[code_block.code].to_owned(),
3333
);
3434

35-
let errors = Lexer::new_or_buffered_errs(&sess, source_file, None).and_then(|mut lexer| {
35+
let errors = {
36+
let mut lexer = Lexer::new(&sess, source_file, None);
3637
while let Ok(token::Token { kind, .. }) = lexer.try_next_token() {
3738
if kind == token::Eof {
3839
break;
@@ -46,7 +47,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
4647
} else {
4748
Ok(())
4849
}
49-
});
50+
};
5051

5152
if let Err(errors) = errors {
5253
let mut diag = if let Some(sp) =

src/libsyntax/parse/lexer/comments.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ fn read_block_comment(rdr: &mut StringReader<'_>,
268268
while level > 0 {
269269
debug!("=== block comment level {}", level);
270270
if rdr.is_eof() {
271-
rdr.fatal("unterminated block comment").raise();
271+
rdr.fatal_span_(rdr.pos, rdr.pos, "unterminated block comment").raise();
272272
}
273273
if rdr.ch_is('\n') {
274274
trim_whitespace_prefix_and_push_line(&mut lines, curr_line, col);
@@ -346,7 +346,7 @@ pub fn gather_comments(sess: &ParseSess, path: FileName, srdr: &mut dyn Read) ->
346346
srdr.read_to_string(&mut src).unwrap();
347347
let cm = SourceMap::new(sess.source_map().path_mapping().clone());
348348
let source_file = cm.new_source_file(path, src);
349-
let mut rdr = lexer::StringReader::new_raw(sess, source_file, None);
349+
let mut rdr = lexer::StringReader::new(sess, source_file, None);
350350

351351
let mut comments: Vec<Comment> = Vec::new();
352352
let mut code_to_the_left = false; // Only code

0 commit comments

Comments
 (0)