mirror of
https://github.com/typst/typst
synced 2025-05-19 11:35:27 +08:00
Deduplicate trivia search
This commit is contained in:
parent
41bdafb578
commit
8117ca9950
@ -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());
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user