summaryrefslogtreecommitdiff
path: root/src/parse/mod.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-02-23 23:58:05 +0100
committerGitHub <noreply@github.com>2022-02-23 23:58:05 +0100
commit90132b0d658f1b2a5df75eb458150e6782b2c30c (patch)
treeb4c237b22b31a6f965849fd7b540c7aec364ef96 /src/parse/mod.rs
parentf2f473a81fde9c09e0f361f1b85fb5c14337f360 (diff)
parent9fda623b02b2a0a9e9cdf806d9945d0759c8bf01 (diff)
Merge pull request #64 from typst/new-incr-parse
New Incremental Parser
Diffstat (limited to 'src/parse/mod.rs')
-rw-r--r--src/parse/mod.rs162
1 files changed, 82 insertions, 80 deletions
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
index c14c45cf..11ce872f 100644
--- a/src/parse/mod.rs
+++ b/src/parse/mod.rs
@@ -28,103 +28,120 @@ pub fn parse(src: &str) -> Arc<GreenNode> {
}
}
-/// Parse some markup. Returns `Some` if all of the input was consumed.
-pub fn parse_markup(
- prefix: &str,
- src: &str,
- _: bool,
- min_column: usize,
-) -> Option<(Vec<Green>, bool)> {
- let mut p = Parser::with_prefix(prefix, src, TokenMode::Markup);
- if min_column == 0 {
- markup(&mut p, true);
- } else {
- markup_indented(&mut p, min_column);
- }
- p.consume()
-}
-
/// Parse some markup without the topmost node. Returns `Some` if all of the
/// input was consumed.
-pub fn parse_markup_elements(
+pub fn reparse_markup_elements(
prefix: &str,
src: &str,
+ end_pos: usize,
+ differential: isize,
+ reference: &[Green],
mut at_start: bool,
- _: usize,
-) -> Option<(Vec<Green>, bool)> {
+ column: usize,
+) -> Option<(Vec<Green>, bool, usize)> {
let mut p = Parser::with_prefix(prefix, src, TokenMode::Markup);
- while !p.eof() {
+
+ let mut node: Option<&Green> = None;
+ let mut iter = reference.iter();
+ let mut offset = differential;
+ let mut replaced = 0;
+ let mut stopped = false;
+
+ 'outer: while !p.eof() {
+ if let Some(NodeKind::Space(1 ..)) = p.peek() {
+ if p.column(p.current_end()) < column {
+ return None;
+ }
+ }
+
markup_node(&mut p, &mut at_start);
+
+ if p.prev_end() < end_pos {
+ continue;
+ }
+
+ let recent = p.children.last().unwrap();
+ let recent_start = p.prev_end() - recent.len();
+
+ while offset <= recent_start as isize {
+ if let Some(node) = node {
+ // The nodes are equal, at the same position and have the
+ // same content. The parsing trees have converged again, so
+ // the reparse may stop here.
+ if offset == recent_start as isize && node == recent {
+ replaced -= 1;
+ stopped = true;
+ break 'outer;
+ }
+ }
+
+ if let Some(node) = node {
+ offset += node.len() as isize;
+ }
+
+ node = iter.next();
+ if node.is_none() {
+ break;
+ }
+
+ replaced += 1;
+ }
}
- p.consume()
-}
-/// Parse an atomic primary. Returns `Some` if all of the input was consumed.
-pub fn parse_atomic(
- prefix: &str,
- src: &str,
- _: bool,
- _: usize,
-) -> Option<(Vec<Green>, bool)> {
- let mut p = Parser::with_prefix(prefix, src, TokenMode::Code);
- primary(&mut p, true).ok()?;
- p.consume_open_ended()
-}
+ if p.eof() && !stopped {
+ replaced = reference.len();
+ }
-/// Parse an atomic primary. Returns `Some` if all of the input was consumed.
-pub fn parse_atomic_markup(
- prefix: &str,
- src: &str,
- _: bool,
- _: usize,
-) -> Option<(Vec<Green>, bool)> {
- let mut p = Parser::with_prefix(prefix, src, TokenMode::Markup);
- markup_expr(&mut p);
- p.consume_open_ended()
+ let (mut res, terminated) = p.consume()?;
+ if stopped {
+ res.pop().unwrap();
+ }
+
+ Some((res, terminated, replaced))
}
/// Parse a template literal. Returns `Some` if all of the input was consumed.
-pub fn parse_template(
+pub fn reparse_template(
prefix: &str,
src: &str,
- _: bool,
- _: usize,
-) -> Option<(Vec<Green>, bool)> {
+ end_pos: usize,
+) -> Option<(Vec<Green>, bool, usize)> {
let mut p = Parser::with_prefix(prefix, src, TokenMode::Code);
if !p.at(&NodeKind::LeftBracket) {
return None;
}
template(&mut p);
- p.consume()
+
+ let (mut green, terminated) = p.consume()?;
+ let first = green.remove(0);
+ if first.len() != end_pos {
+ return None;
+ }
+
+ Some((vec![first], terminated, 1))
}
/// Parse a code block. Returns `Some` if all of the input was consumed.
-pub fn parse_block(
+pub fn reparse_block(
prefix: &str,
src: &str,
- _: bool,
- _: usize,
-) -> Option<(Vec<Green>, bool)> {
+ end_pos: usize,
+) -> Option<(Vec<Green>, bool, usize)> {
let mut p = Parser::with_prefix(prefix, src, TokenMode::Code);
if !p.at(&NodeKind::LeftBrace) {
return None;
}
block(&mut p);
- p.consume()
-}
-/// Parse a comment. Returns `Some` if all of the input was consumed.
-pub fn parse_comment(
- prefix: &str,
- src: &str,
- _: bool,
- _: usize,
-) -> Option<(Vec<Green>, bool)> {
- let mut p = Parser::with_prefix(prefix, src, TokenMode::Code);
- comment(&mut p).ok()?;
- p.consume()
+ let (mut green, terminated) = p.consume()?;
+ let first = green.remove(0);
+ if first.len() != end_pos {
+ return None;
+ }
+
+ Some((vec![first], terminated, 1))
}
/// Parse markup.
@@ -172,11 +189,7 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) {
// Whitespace.
NodeKind::Space(newlines) => {
*at_start |= *newlines > 0;
- if *newlines < 2 {
- p.eat();
- } else {
- p.convert(NodeKind::Parbreak);
- }
+ p.eat();
return;
}
@@ -920,17 +933,6 @@ fn body(p: &mut Parser) -> ParseResult {
Ok(())
}
-/// Parse a comment.
-fn comment(p: &mut Parser) -> ParseResult {
- match p.peek() {
- Some(NodeKind::LineComment | NodeKind::BlockComment) => {
- p.eat();
- Ok(())
- }
- _ => Err(ParseError),
- }
-}
-
#[cfg(test)]
mod tests {
use std::fmt::Debug;