Deduplicate trivia search

This commit is contained in:
Laurenz 2021-11-06 15:30:08 +01:00
parent 41bdafb578
commit 8117ca9950

View File

@ -16,7 +16,7 @@ pub struct Parser<'s> {
eof: bool, eof: bool,
/// The current token. /// The current token.
current: Option<NodeKind>, current: Option<NodeKind>,
/// The end byte index of the last (non-whitespace if in code mode) token. /// The end byte index of the last non-trivia token.
prev_end: usize, prev_end: usize,
/// The start byte index of the peeked token. /// The start byte index of the peeked token.
current_start: usize, current_start: usize,
@ -59,25 +59,19 @@ impl<'s> Parser<'s> {
{ {
let prev = mem::take(&mut self.children); let prev = mem::take(&mut self.children);
let output = f(self); let output = f(self);
let until = self.trivia_start();
let mut children = mem::replace(&mut self.children, prev); let mut children = mem::replace(&mut self.children, prev);
// Trailing trivia should not be wrapped into the new node.
let mut remains = vec![];
if self.tokens.mode() == TokenMode::Code { if self.tokens.mode() == TokenMode::Code {
let len = children.len(); // Trailing trivia should not be wrapped into the new node.
for n in (0 .. len).rev() { let idx = self.children.len();
if !self.is_trivia(&children[n].kind()) { self.children.push(Green::default());
break; self.children.extend(children.drain(until ..));
} self.children[idx] = GreenNode::with_children(kind, children).into();
} else {
remains.push(children.pop().unwrap()); self.children.push(GreenNode::with_children(kind, children).into());
}
remains.reverse();
} }
self.children.push(GreenNode::with_children(kind, children).into());
self.children.extend(remains);
output output
} }
@ -86,7 +80,7 @@ impl<'s> Parser<'s> {
self.eof self.eof
} }
/// Consume the current token and also trailing trivia if in code mode. /// Consume the current token and also trailing trivia.
pub fn eat(&mut self) { pub fn eat(&mut self) {
self.prev_end = self.tokens.index(); self.prev_end = self.tokens.index();
self.bump(); self.bump();
@ -169,9 +163,7 @@ impl<'s> Parser<'s> {
self.tokens.scanner().get(self.current_start() .. self.current_end()) self.tokens.scanner().get(self.current_start() .. self.current_end())
} }
/// The byte index at which the last token ended. /// The byte index at which the last non-trivia token ended.
///
/// Refers to the end of the last non-trivia token in code mode.
pub fn prev_end(&self) -> usize { pub fn prev_end(&self) -> usize {
self.prev_end self.prev_end
} }
@ -248,14 +240,7 @@ impl<'s> Parser<'s> {
// Rescan the peeked token if the mode changed. // Rescan the peeked token if the mode changed.
if rescan { if rescan {
if group_mode == TokenMode::Code { if group_mode == TokenMode::Code {
let len = self.children.len(); self.children.truncate(self.trivia_start());
for n in (0 .. len).rev() {
if !self.is_trivia(self.children[n].kind()) {
break;
}
self.children.pop();
}
} }
self.tokens.jump(self.prev_end()); self.tokens.jump(self.prev_end());
@ -307,6 +292,17 @@ impl<'s> Parser<'s> {
} }
} }
/// Find the index in the children list where trailing trivia starts.
fn trivia_start(&self) -> usize {
self.children.len()
- self
.children
.iter()
.rev()
.take_while(|node| self.is_trivia(node.kind()))
.count()
}
/// Whether the active group must end at a newline. /// Whether the active group must end at a newline.
fn stop_at_newline(&self) -> bool { fn stop_at_newline(&self) -> bool {
matches!( matches!(
@ -356,15 +352,7 @@ impl Parser<'_> {
/// Add an error that the `thing` was expected at the end of the last /// Add an error that the `thing` was expected at the end of the last
/// non-trivia token. /// non-trivia token.
pub fn expected_at(&mut self, thing: &str) { pub fn expected_at(&mut self, thing: &str) {
let mut found = self.children.len(); Marker(self.trivia_start()).expected_at(self, thing);
for (i, node) in self.children.iter().enumerate().rev() {
if !self.is_trivia(node.kind()) {
break;
}
found = i;
}
Marker(found).expected_at(self, thing);
} }
} }
@ -384,15 +372,11 @@ impl Marker {
success success
} }
/// Wrap all children after the marker in a node with the given `kind`. /// Wrap all children after the marker (excluding trailing trivia) in a node
/// with the given `kind`.
pub fn end(self, p: &mut Parser, kind: NodeKind) { pub fn end(self, p: &mut Parser, kind: NodeKind) {
let end = (self.0 .. p.children.len()) let until = p.trivia_start();
.rev() let children = p.children.drain(self.0 .. until).collect();
.find(|&i| !p.is_trivia(p.children[i].kind()))
.unwrap_or(self.0)
+ 1;
let children: Vec<_> = p.children.drain(self.0 .. end).collect();
p.children p.children
.insert(self.0, GreenNode::with_children(kind, children).into()); .insert(self.0, GreenNode::with_children(kind, children).into());
} }