From aac3afcba8ee9b3692f784c78626aa0596aaf612 Mon Sep 17 00:00:00 2001 From: Martin Haug Date: Mon, 21 Feb 2022 13:48:21 +0100 Subject: Remove `Parbreak` as a `NodeKind` --- src/parse/mod.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/parse/mod.rs') diff --git a/src/parse/mod.rs b/src/parse/mod.rs index c14c45cf..bd217c1c 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -172,11 +172,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; } -- cgit v1.2.3 From 20ac96f27a2e06b985abc1c95049c32c2b88ef5d Mon Sep 17 00:00:00 2001 From: Martin Haug Date: Mon, 21 Feb 2022 22:49:50 +0100 Subject: New incremental parsing paradigm Also move column offset into scanner. This fixes #62 --- src/parse/mod.rs | 148 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 79 insertions(+), 69 deletions(-) (limited to 'src/parse/mod.rs') 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 { } } -/// 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, 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, bool)> { +) -> Option<(Vec, 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, 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, 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, bool)> { +) -> Option<(Vec, 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, bool)> { +) -> Option<(Vec, 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, 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; -- cgit v1.2.3 From 4c8634c600ad0bba03ccdf884b32f234ecbff30c Mon Sep 17 00:00:00 2001 From: Martin Haug Date: Wed, 23 Feb 2022 13:57:15 +0100 Subject: Early stop for falling indents. Fix code edits and at_start handling. Also fix dedenting for multi-byte chars in raw blocks. --- src/parse/mod.rs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'src/parse/mod.rs') diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 7c0a0932..c08c5d6f 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -37,6 +37,7 @@ pub fn parse_markup_elements( differential: isize, reference: &[Green], mut at_start: bool, + column: usize, ) -> Option<(Vec, bool, usize)> { let mut p = Parser::with_prefix(prefix, src, TokenMode::Markup); @@ -47,6 +48,12 @@ pub fn parse_markup_elements( let mut stopped = false; 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 { @@ -85,11 +92,15 @@ pub fn parse_markup_elements( } } + if p.prev_end() < end_pos { + return None; + } + if p.eof() && !stopped { replaced = reference.len(); } - let (mut res, terminated) = p.consume_open_ended()?; + let (mut res, terminated) = p.consume()?; if stopped { res.pop().unwrap(); } @@ -103,8 +114,9 @@ pub fn parse_template( src: &str, end_pos: usize, _: isize, - reference: &[Green], + _: &[Green], _: bool, + _: usize, ) -> Option<(Vec, bool, usize)> { let mut p = Parser::with_prefix(prefix, src, TokenMode::Code); if !p.at(&NodeKind::LeftBracket) { @@ -113,7 +125,7 @@ pub fn parse_template( template(&mut p); - let (mut green, terminated) = p.consume_open_ended()?; + let (mut green, terminated) = p.consume()?; let first = green.remove(0); if first.len() != end_pos { return None; @@ -128,8 +140,9 @@ pub fn parse_block( src: &str, end_pos: usize, _: isize, - reference: &[Green], + _: &[Green], _: bool, + _: usize, ) -> Option<(Vec, bool, usize)> { let mut p = Parser::with_prefix(prefix, src, TokenMode::Code); if !p.at(&NodeKind::LeftBrace) { @@ -138,9 +151,8 @@ pub fn parse_block( block(&mut p); - let (mut green, terminated) = p.consume_open_ended()?; + let (mut green, terminated) = p.consume()?; let first = green.remove(0); - if first.len() != end_pos { return None; } -- cgit v1.2.3 From 9fda623b02b2a0a9e9cdf806d9945d0759c8bf01 Mon Sep 17 00:00:00 2001 From: Martin Haug Date: Wed, 23 Feb 2022 20:06:48 +0100 Subject: Code Review: That's just like your struct, man. --- src/parse/mod.rs | 72 ++++++++++++++++++++++---------------------------------- 1 file changed, 28 insertions(+), 44 deletions(-) (limited to 'src/parse/mod.rs') diff --git a/src/parse/mod.rs b/src/parse/mod.rs index c08c5d6f..11ce872f 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -30,7 +30,7 @@ pub fn parse(src: &str) -> Arc { /// 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, @@ -43,11 +43,11 @@ pub fn parse_markup_elements( let mut node: Option<&Green> = None; let mut iter = reference.iter(); - let mut offset = 0; + let mut offset = differential; let mut replaced = 0; let mut stopped = false; - while !p.eof() { + 'outer: while !p.eof() { if let Some(NodeKind::Space(1 ..)) = p.peek() { if p.column(p.current_end()) < column { return None; @@ -56,44 +56,36 @@ pub fn parse_markup_elements( 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; - } - } + if p.prev_end() < end_pos { + continue; + } - let result = iter.next(); - if let Some(node) = node { - offset += node.len(); - } - node = result; - if node.is_none() { - break; - } else { - replaced += 1; + 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 stopped { + if let Some(node) = node { + offset += node.len() as isize; + } + + node = iter.next(); + if node.is_none() { break; } - } - } - if p.prev_end() < end_pos { - return None; + replaced += 1; + } } if p.eof() && !stopped { @@ -109,14 +101,10 @@ pub fn parse_markup_elements( } /// 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, end_pos: usize, - _: isize, - _: &[Green], - _: bool, - _: usize, ) -> Option<(Vec, bool, usize)> { let mut p = Parser::with_prefix(prefix, src, TokenMode::Code); if !p.at(&NodeKind::LeftBracket) { @@ -135,14 +123,10 @@ pub fn parse_template( } /// 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, end_pos: usize, - _: isize, - _: &[Green], - _: bool, - _: usize, ) -> Option<(Vec, bool, usize)> { let mut p = Parser::with_prefix(prefix, src, TokenMode::Code); if !p.at(&NodeKind::LeftBrace) { -- cgit v1.2.3