summaryrefslogtreecommitdiff
path: root/src/parse/mod.rs
diff options
context:
space:
mode:
authorMartin Haug <mhaug@live.de>2022-02-21 22:49:50 +0100
committerMartin Haug <mhaug@live.de>2022-02-23 13:58:56 +0100
commit20ac96f27a2e06b985abc1c95049c32c2b88ef5d (patch)
treeb145fa807c4088626c2f0bf1eeb32cff0fd163e1 /src/parse/mod.rs
parentaac3afcba8ee9b3692f784c78626aa0596aaf612 (diff)
New incremental parsing paradigm
Also move column offset into scanner. This fixes #62
Diffstat (limited to 'src/parse/mod.rs')
-rw-r--r--src/parse/mod.rs148
1 files changed, 79 insertions, 69 deletions
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
index bd217c1c..7c0a0932 100644
--- a/src/parse/mod.rs
+++ b/src/parse/mod.rs
@@ -28,103 +28,124 @@ 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(
prefix: &str,
src: &str,
+ end_pos: usize,
+ differential: isize,
+ reference: &[Green],
mut at_start: bool,
- _: usize,
-) -> Option<(Vec<Green>, bool)> {
+) -> Option<(Vec<Green>, bool, usize)> {
let mut p = Parser::with_prefix(prefix, src, TokenMode::Markup);
+
+ let mut node: Option<&Green> = None;
+ let mut iter = reference.iter();
+ let mut offset = 0;
+ let mut replaced = 0;
+ let mut stopped = false;
+
while !p.eof() {
markup_node(&mut p, &mut at_start);
+
+ if p.prev_end() >= end_pos {
+ let recent = p.children.last().unwrap();
+ let recent_start = p.prev_end() - recent.len();
+
+ while offset <= recent_start {
+ 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 as isize + differential) as usize == recent_start
+ && node == recent
+ {
+ replaced -= 1;
+ stopped = true;
+ break;
+ }
+ }
+
+ let result = iter.next();
+ if let Some(node) = node {
+ offset += node.len();
+ }
+ node = result;
+ if node.is_none() {
+ break;
+ } else {
+ replaced += 1;
+ }
+ }
+
+ if stopped {
+ break;
+ }
+ }
}
- 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_open_ended()?;
+ 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(
prefix: &str,
src: &str,
+ end_pos: usize,
+ _: isize,
+ reference: &[Green],
_: bool,
- _: usize,
-) -> Option<(Vec<Green>, bool)> {
+) -> 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_open_ended()?;
+ 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(
prefix: &str,
src: &str,
+ end_pos: usize,
+ _: isize,
+ reference: &[Green],
_: bool,
- _: usize,
-) -> Option<(Vec<Green>, bool)> {
+) -> 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_open_ended()?;
+ let first = green.remove(0);
+
+ if first.len() != end_pos {
+ return None;
+ }
+
+ Some((vec![first], terminated, 1))
}
/// Parse markup.
@@ -916,17 +937,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;