diff --git a/src/compiler/process.rs b/src/compiler/process.rs index ddeb8ad..90fe67f 100644 --- a/src/compiler/process.rs +++ b/src/compiler/process.rs @@ -7,6 +7,7 @@ use rusqlite::Connection; use crate::document::document::Document; use crate::parser::langparser::LangParser; +use crate::parser::parser::ParseMode; use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::source::Source; @@ -25,7 +26,7 @@ fn parse( ) -> Result>, String> { // Parse //let source = SourceFile::new(input.to_string(), None).unwrap(); - let (doc, _) = parser.parse(ParserState::new(parser, None), source.clone(), None); + let (doc, _) = parser.parse(ParserState::new(parser, None), source.clone(), None, ParseMode::default()); if debug_opts.contains(&"ast".to_string()) { println!("-- BEGIN AST DEBUGGING --"); diff --git a/src/document/references.rs b/src/document/references.rs index fb379f5..7e7ae0c 100644 --- a/src/document/references.rs +++ b/src/document/references.rs @@ -43,9 +43,10 @@ pub mod tests { use super::*; use crate::parser::langparser::LangParser; + use crate::parser::parser::ParseMode; use crate::parser::parser::Parser; - use crate::parser::source::SourceFile; use crate::parser::parser::ParserState; + use crate::parser::source::SourceFile; #[test] fn validate_refname_tests() { @@ -55,7 +56,12 @@ pub mod tests { None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); assert_eq!(validate_refname(&*doc, " abc ", true), Ok("abc")); assert_eq!( diff --git a/src/document/variable.rs b/src/document/variable.rs index 60611f6..1158fd1 100644 --- a/src/document/variable.rs +++ b/src/document/variable.rs @@ -1,5 +1,6 @@ use super::document::Document; use crate::elements::text::Text; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::source::Source; use crate::parser::source::Token; @@ -63,7 +64,7 @@ impl Variable for BaseVariable { )); state.with_state(|new_state| { - let _ = new_state.parser.parse_into(new_state, source, document); + let _ = new_state.parser.parse_into(new_state, source, document, ParseMode::default()); }); } } diff --git a/src/elements/blockquote.rs b/src/elements/blockquote.rs index 846e882..d54af18 100644 --- a/src/elements/blockquote.rs +++ b/src/elements/blockquote.rs @@ -25,6 +25,7 @@ use crate::document::element::ElemKind; use crate::document::element::Element; use crate::elements::paragraph::Paragraph; use crate::elements::text::Text; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::rule::Rule; use crate::parser::source::Cursor; @@ -233,7 +234,15 @@ impl Rule for BlockquoteRule { fn previous(&self) -> Option<&'static str> { Some("List") } - fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box)> { + fn next_match( + &self, + mode: &ParseMode, + _state: &ParserState, + cursor: &Cursor, + ) -> Option<(usize, Box)> { + if mode.paragraph_only { + return None; + } self.start_re .find_at(cursor.source.content(), cursor.pos) .map(|m| (m.start(), Box::new([false; 0]) as Box)) @@ -310,7 +319,7 @@ impl Rule for BlockquoteRule { let parsed_doc = state.with_state(|new_state| { new_state .parser - .parse(new_state, entry_src, Some(document)) + .parse(new_state, entry_src, Some(document), ParseMode::default()) .0 }); @@ -447,7 +456,12 @@ END None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Paragraph { Text{ content == "BEFORE" }; }; @@ -496,7 +510,12 @@ AFTER None, )); let parser = LangParser::default(); - let (_, state) = parser.parse(ParserState::new(&parser, None), source, None); + let (_, state) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); let style = state .shared diff --git a/src/elements/code.rs b/src/elements/code.rs index 415471e..5d5b1ec 100644 --- a/src/elements/code.rs +++ b/src/elements/code.rs @@ -26,6 +26,7 @@ use crate::document::element::ElemKind; use crate::document::element::Element; use crate::lsp::semantic::Semantics; use crate::lua::kernel::CTX; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::rule::RegexRule; use crate::parser::source::Source; @@ -309,8 +310,7 @@ impl CodeRule { Regex::new( r"``(?:\[((?:\\.|[^\\\\])*?)\])?(?:([^\r\n`]*?)(?:,|\n))?((?:\\(?:.|\n)|[^\\\\])*?)``", ) - .unwrap() - + .unwrap(), ], properties: PropertyParser { properties: props }, } @@ -319,10 +319,15 @@ impl CodeRule { impl RegexRule for CodeRule { fn name(&self) -> &'static str { "Code" } + fn previous(&self) -> Option<&'static str> { Some("Blockquote") } fn regexes(&self) -> &[regex::Regex] { &self.re } + fn enabled(&self, mode: &ParseMode, id: usize) -> bool { + return !mode.paragraph_only || id != 0; + } + fn on_regex_match( &self, index: usize, @@ -710,7 +715,12 @@ fn fact(n: usize) -> usize None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); let borrow = doc.content().borrow(); let found = borrow @@ -756,7 +766,12 @@ fn fact(n: usize) -> usize None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); let borrow = doc.content().borrow(); let found = borrow @@ -806,6 +821,7 @@ test code ParserState::new_with_semantics(&parser, None), source.clone(), None, + ParseMode::default(), ); validate_semantics!(state, source.clone(), 0, code_sep { delta_line == 1, delta_start == 0, length == 3 }; diff --git a/src/elements/comment.rs b/src/elements/comment.rs index 6aacd6c..e063246 100644 --- a/src/elements/comment.rs +++ b/src/elements/comment.rs @@ -3,6 +3,7 @@ use crate::document::document::Document; use crate::document::element::ElemKind; use crate::document::element::Element; use crate::lsp::semantic::Semantics; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::rule::RegexRule; use crate::parser::source::Source; @@ -56,6 +57,8 @@ impl RegexRule for CommentRule { fn regexes(&self) -> &[Regex] { &self.re } + fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true } + fn on_regex_match( &self, _: usize, @@ -132,7 +135,12 @@ COMMENT ::Test None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Paragraph { @@ -160,6 +168,7 @@ COMMENT ::Test ParserState::new_with_semantics(&parser, None), source.clone(), None, + ParseMode::default(), ); validate_semantics!(state, source.clone(), 0, diff --git a/src/elements/customstyle.rs b/src/elements/customstyle.rs index f263573..d010904 100644 --- a/src/elements/customstyle.rs +++ b/src/elements/customstyle.rs @@ -1,4 +1,5 @@ use crate::lua::kernel::Kernel; +use crate::parser::parser::ParseMode; use std::any::Any; use std::cell::Ref; use std::cell::RefCell; @@ -140,10 +141,13 @@ impl RuleState for CustomStyleState { let paragraph = document.last_element::().unwrap(); let paragraph_end = paragraph .content - .last().map(|last| ( + .last() + .map(|last| { + ( last.location().source(), last.location().end() - 1..last.location().end(), - )) + ) + }) .unwrap(); reports.push( @@ -179,14 +183,20 @@ static STATE_NAME: &str = "elements.custom_style"; pub struct CustomStyleRule; impl CustomStyleRule { - pub fn new() -> Self { Self{} } + pub fn new() -> Self { Self {} } } impl Rule for CustomStyleRule { fn name(&self) -> &'static str { "Custom Style" } + fn previous(&self) -> Option<&'static str> { Some("Style") } - fn next_match(&self, state: &ParserState, cursor: &Cursor) -> Option<(usize, Box)> { + fn next_match( + &self, + _mode: &ParseMode, + state: &ParserState, + cursor: &Cursor, + ) -> Option<(usize, Box)> { let content = cursor.source.content(); let mut closest_match = usize::MAX; @@ -479,6 +489,7 @@ mod tests { use crate::elements::raw::Raw; use crate::elements::text::Text; use crate::parser::langparser::LangParser; + use crate::parser::parser::ParseMode; use crate::parser::parser::Parser; use crate::parser::source::SourceFile; use crate::validate_document; @@ -512,7 +523,12 @@ pre |styled| post °Hello°. None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Paragraph { @@ -556,7 +572,12 @@ pre [styled] post (Hello). None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Paragraph { diff --git a/src/elements/elemstyle.rs b/src/elements/elemstyle.rs index e341a2a..c5e7b40 100644 --- a/src/elements/elemstyle.rs +++ b/src/elements/elemstyle.rs @@ -1,3 +1,4 @@ +use crate::parser::parser::ParseMode; use crate::parser::style::ElementStyle; use std::any::Any; use std::ops::Range; @@ -59,11 +60,18 @@ impl ElemStyleRule { impl Rule for ElemStyleRule { fn name(&self) -> &'static str { "Element Style" } + fn previous(&self) -> Option<&'static str> { Some("Script") } - fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box)> { + fn next_match( + &self, + _mode: &ParseMode, + _state: &ParserState, + cursor: &Cursor, + ) -> Option<(usize, Box)> { self.start_re - .find_at(cursor.source.content(), cursor.pos).map(|m| (m.start(), Box::new([false; 0]) as Box)) + .find_at(cursor.source.content(), cursor.pos) + .map(|m| (m.start(), Box::new([false; 0]) as Box)) } fn on_match<'a>( @@ -132,7 +140,9 @@ impl Rule for ElemStyleRule { .with_message("Invalid Style Value") .with_label( Label::new((cursor.source.clone(), matches.get(0).unwrap().range())) - .with_message("Unable to parse json string after style key".to_string()) + .with_message( + "Unable to parse json string after style key".to_string(), + ) .with_color(state.parser.colors().error), ) .finish(), diff --git a/src/elements/graphviz.rs b/src/elements/graphviz.rs index 89cfe8c..fd205ff 100644 --- a/src/elements/graphviz.rs +++ b/src/elements/graphviz.rs @@ -5,6 +5,7 @@ use std::sync::Arc; use std::sync::Once; use crate::lua::kernel::CTX; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::util::Property; use crate::parser::util::PropertyMapError; @@ -189,10 +190,13 @@ impl GraphRule { impl RegexRule for GraphRule { fn name(&self) -> &'static str { "Graphviz" } + fn previous(&self) -> Option<&'static str> { Some("Tex") } fn regexes(&self) -> &[regex::Regex] { &self.re } + fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only } + fn on_regex_match( &self, _: usize, @@ -441,7 +445,12 @@ Another graph None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Graphviz { width == "200px", dot == "Some graph..." }; @@ -461,7 +470,12 @@ Another graph None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Graphviz { width == "200px", dot == "Some graph..." }; diff --git a/src/elements/import.rs b/src/elements/import.rs index 80b224a..3143379 100644 --- a/src/elements/import.rs +++ b/src/elements/import.rs @@ -1,6 +1,7 @@ use crate::document::document::Document; use crate::document::document::DocumentAccessors; use crate::lsp::semantic::Semantics; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::parser::ReportColors; use crate::parser::rule::RegexRule; @@ -43,10 +44,13 @@ impl ImportRule { impl RegexRule for ImportRule { fn name(&self) -> &'static str { "Import" } + fn previous(&self) -> Option<&'static str> { Some("Paragraph") } fn regexes(&self) -> &[Regex] { &self.re } + fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only } + fn on_regex_match<'a>( &self, _: usize, @@ -165,7 +169,10 @@ impl RegexRule for ImportRule { }; state.with_state(|new_state| { - let (import_doc, _) = new_state.parser.parse(new_state, import, Some(document)); + let (import_doc, _) = + new_state + .parser + .parse(new_state, import, Some(document), ParseMode::default()); document.merge(import_doc.content(), import_doc.scope(), Some(&import_as)); }); @@ -181,27 +188,27 @@ impl RegexRule for ImportRule { ); } - - if let Some((sems, tokens)) = Semantics::from_source(token.source(), &state.shared.semantics) + if let Some((sems, tokens)) = + Semantics::from_source(token.source(), &state.shared.semantics) { // @import - let import = if token.source().content().as_bytes()[matches.get(0).unwrap().start()] == b'\n' - { - matches.get(0).unwrap().start() + 1 - } - else - { - matches.get(0).unwrap().start() - }; + let import = + if token.source().content().as_bytes()[matches.get(0).unwrap().start()] == b'\n' { + matches.get(0).unwrap().start() + 1 + } else { + matches.get(0).unwrap().start() + }; sems.add(import..import + 7, tokens.import_import); - if let Some(import_as) = matches.get(1) - { - sems.add(import_as.start()-1..import_as.start(), tokens.import_as_sep); + if let Some(import_as) = matches.get(1) { + sems.add( + import_as.start() - 1..import_as.start(), + tokens.import_as_sep, + ); sems.add(import_as.range(), tokens.import_as); - sems.add(import_as.end()..import_as.end()+1, tokens.import_as_sep); + sems.add(import_as.end()..import_as.end() + 1, tokens.import_as_sep); } - + let path = matches.get(2).unwrap().range(); sems.add(path, tokens.import_path); } diff --git a/src/elements/layout.rs b/src/elements/layout.rs index 2ef6739..1db16be 100644 --- a/src/elements/layout.rs +++ b/src/elements/layout.rs @@ -6,6 +6,7 @@ use crate::document::element::Element; use crate::lua::kernel::CTX; use crate::parser::layout::LayoutHolder; use crate::parser::layout::LayoutType; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::parser::ReportColors; use crate::parser::rule::RegexRule; @@ -232,7 +233,12 @@ impl Element for Layout { fn location(&self) -> &Token { &self.location } fn kind(&self) -> ElemKind { ElemKind::Block } fn element_name(&self) -> &'static str { "Layout" } - fn compile(&self, compiler: &Compiler, document: &dyn Document, _cursor: usize) -> Result { + fn compile( + &self, + compiler: &Compiler, + document: &dyn Document, + _cursor: usize, + ) -> Result { self.layout .compile(self.token, self.id, &self.properties, compiler, document) } @@ -379,10 +385,13 @@ static STATE_NAME: &str = "elements.layout"; impl RegexRule for LayoutRule { fn name(&self) -> &'static str { "Layout" } + fn previous(&self) -> Option<&'static str> { Some("Media") } fn regexes(&self) -> &[regex::Regex] { &self.re } + fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only } + fn on_regex_match( &self, index: usize, @@ -897,7 +906,12 @@ mod tests { None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Layout { token == LayoutToken::Begin, id == 0 }; @@ -949,7 +963,12 @@ mod tests { None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Layout { token == LayoutToken::Begin, id == 0 }; diff --git a/src/elements/link.rs b/src/elements/link.rs index b739d8b..7a69834 100644 --- a/src/elements/link.rs +++ b/src/elements/link.rs @@ -6,6 +6,7 @@ use crate::document::element::ElemKind; use crate::document::element::Element; use crate::lsp::semantic::Semantics; use crate::lua::kernel::CTX; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::rule::RegexRule; use crate::parser::source::Source; @@ -94,10 +95,13 @@ impl LinkRule { impl RegexRule for LinkRule { fn name(&self) -> &'static str { "Link" } + fn previous(&self) -> Option<&'static str> { Some("Link") } fn regexes(&self) -> &[Regex] { &self.re } + fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true } + fn on_regex_match<'a>( &self, _: usize, @@ -314,7 +318,12 @@ Some [link](url). None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Paragraph { @@ -344,7 +353,12 @@ nml.link.push("**BOLD link**", "another url") None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Paragraph { @@ -375,6 +389,7 @@ nml.link.push("**BOLD link**", "another url") ParserState::new_with_semantics(&parser, None), source.clone(), None, + ParseMode::default(), ); validate_semantics!(state, source.clone(), 0, diff --git a/src/elements/list.rs b/src/elements/list.rs index 8be12a2..6aafbab 100644 --- a/src/elements/list.rs +++ b/src/elements/list.rs @@ -12,6 +12,7 @@ use crate::document::element::ContainerElement; use crate::document::element::ElemKind; use crate::document::element::Element; use crate::lsp::semantic::Semantics; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::rule::Rule; use crate::parser::source::Cursor; @@ -269,9 +270,18 @@ impl ListRule { impl Rule for ListRule { fn name(&self) -> &'static str { "List" } + fn previous(&self) -> Option<&'static str> { Some("Raw") } - fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box)> { + fn next_match( + &self, + mode: &ParseMode, + _state: &ParserState, + cursor: &Cursor, + ) -> Option<(usize, Box)> { + if mode.paragraph_only { + return None; + } self.start_re .find_at(cursor.source.content(), cursor.pos) .map(|m| (m.start(), Box::new([false; 0]) as Box)) @@ -406,6 +416,7 @@ impl Rule for ListRule { // Parse entry content let token = Token::new(entry_start..end_cursor.pos, end_cursor.source.clone()); + //println!("content={}", entry_content); let entry_src = Rc::new(VirtualSource::new( token.clone(), "List Entry".to_string(), @@ -475,7 +486,8 @@ mod tests { use crate::parser::langparser::LangParser; use crate::parser::parser::Parser; use crate::parser::source::SourceFile; - use crate::{validate_document, validate_semantics}; + use crate::validate_document; + use crate::validate_semantics; #[test] fn parser() { @@ -498,7 +510,7 @@ mod tests { )); let parser = LangParser::default(); let state = ParserState::new(&parser, None); - let (doc, _) = parser.parse(state, source, None); + let (doc, _) = parser.parse(state, source, None, ParseMode::default()); validate_document!(doc.content().borrow(), 0, ListMarker { numbered == false, kind == MarkerKind::Open }; @@ -549,7 +561,8 @@ mod tests { *[offset=5] First **bold** Second line *- Another ->@ + + "# .to_string(), None, @@ -559,6 +572,7 @@ mod tests { ParserState::new_with_semantics(&parser, None), source.clone(), None, + ParseMode::default(), ); validate_semantics!(state, source.clone(), 0, list_bullet { delta_line == 1, delta_start == 1, length == 1 }; diff --git a/src/elements/media.rs b/src/elements/media.rs index b3dfbf1..29b67cd 100644 --- a/src/elements/media.rs +++ b/src/elements/media.rs @@ -21,6 +21,7 @@ use crate::document::element::ElemKind; use crate::document::element::Element; use crate::document::element::ReferenceableElement; use crate::document::references::validate_refname; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::parser::ReportColors; use crate::parser::rule::RegexRule; @@ -72,14 +73,21 @@ impl Element for Media { fn as_container(&self) -> Option<&dyn ContainerElement> { Some(self) } - fn compile(&self, compiler: &Compiler, document: &dyn Document, cursor: usize) -> Result { + fn compile( + &self, + compiler: &Compiler, + document: &dyn Document, + cursor: usize, + ) -> Result { match compiler.target() { Target::HTML => { let mut result = String::new(); result.push_str("
"); for medium in &self.media { - result += medium.compile(compiler, document, cursor+result.len())?.as_str(); + result += medium + .compile(compiler, document, cursor + result.len())? + .as_str(); } result.push_str("
"); @@ -132,7 +140,12 @@ impl Element for Medium { fn as_referenceable(&self) -> Option<&dyn ReferenceableElement> { Some(self) } - fn compile(&self, compiler: &Compiler, document: &dyn Document, cursor: usize) -> Result { + fn compile( + &self, + compiler: &Compiler, + document: &dyn Document, + cursor: usize, + ) -> Result { match compiler.target() { Target::HTML => { let mut result = String::new(); @@ -145,10 +158,18 @@ impl Element for Medium { .width .as_ref() .map_or(String::new(), |w| format!(r#" style="width:{w};""#)); - result.push_str(format!(r#"
"#, self.refid(compiler, refcount)).as_str()); + result.push_str( + format!( + r#"
"#, + self.refid(compiler, refcount) + ) + .as_str(), + ); result += match self.media_type { MediaType::IMAGE => format!(r#""#, self.uri), - MediaType::VIDEO => format!(r#""#, self.uri + MediaType::VIDEO => format!( + r#""#, + self.uri ), MediaType::AUDIO => { format!(r#""#, self.uri) @@ -158,17 +179,17 @@ impl Element for Medium { let caption = self .caption - .as_ref().map(|cap| format!( - " {}", - Compiler::sanitize(compiler.target(), cap.as_str()) - )) + .as_ref() + .map(|cap| format!(" {}", Compiler::sanitize(compiler.target(), cap.as_str()))) .unwrap_or_default(); result.push_str( format!(r#"

({refcount}){caption}

"#).as_str(), ); if let Some(paragraph) = self.description.as_ref() { - result += paragraph.compile(compiler, document, cursor+result.len())?.as_str(); + result += paragraph + .compile(compiler, document, cursor + result.len())? + .as_str(); } result.push_str("
"); @@ -214,9 +235,7 @@ impl ReferenceableElement for Medium { } } - fn refid(&self, _compiler: &Compiler, refid: usize) -> String { - format!("medium-{refid}") - } + fn refid(&self, _compiler: &Compiler, refid: usize) -> String { format!("medium-{refid}") } } #[auto_registry::auto_registry(registry = "rules", path = "crate::elements::media")] @@ -324,10 +343,13 @@ impl MediaRule { impl RegexRule for MediaRule { fn name(&self) -> &'static str { "Media" } + fn previous(&self) -> Option<&'static str> { Some("Graphviz") } fn regexes(&self) -> &[regex::Regex] { &self.re } + fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only } + fn on_regex_match<'a>( &self, _: usize, @@ -433,13 +455,15 @@ impl RegexRule for MediaRule { .get("width", |_, value| -> Result { Ok(value.clone()) }) - .ok().map(|(_, s)| s); + .ok() + .map(|(_, s)| s); let caption = properties .get("caption", |_, value| -> Result { Ok(value.clone()) }) - .ok().map(|(_, value)| value); + .ok() + .map(|(_, value)| value); let description = match matches.get(4) { Some(content) => { @@ -546,7 +570,12 @@ mod tests { None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); let borrow = doc.content().borrow(); let group = borrow.first().as_ref().unwrap().as_container().unwrap(); diff --git a/src/elements/paragraph.rs b/src/elements/paragraph.rs index b3f909b..c6b5aa2 100644 --- a/src/elements/paragraph.rs +++ b/src/elements/paragraph.rs @@ -11,6 +11,7 @@ use crate::document::document::Document; use crate::document::element::ContainerElement; use crate::document::element::ElemKind; use crate::document::element::Element; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::rule::Rule; use crate::parser::source::Cursor; @@ -48,7 +49,12 @@ impl Element for Paragraph { fn element_name(&self) -> &'static str { "Paragraph" } - fn compile(&self, compiler: &Compiler, document: &dyn Document, cursor: usize) -> Result { + fn compile( + &self, + compiler: &Compiler, + document: &dyn Document, + cursor: usize, + ) -> Result { if self.content.is_empty() { return Ok(String::new()); } @@ -63,7 +69,9 @@ impl Element for Paragraph { result.push_str("

"); for elems in &self.content { - result += elems.compile(compiler, document, cursor+result.len())?.as_str(); + result += elems + .compile(compiler, document, cursor + result.len())? + .as_str(); } result.push_str("

"); @@ -106,11 +114,18 @@ impl ParagraphRule { impl Rule for ParagraphRule { fn name(&self) -> &'static str { "Paragraph" } + fn previous(&self) -> Option<&'static str> { Some("Comment") } - fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box)> { + fn next_match( + &self, + _mode: &ParseMode, + _state: &ParserState, + cursor: &Cursor, + ) -> Option<(usize, Box)> { self.re - .find_at(cursor.source.content(), cursor.pos).map(|m| (m.start(), Box::new([false; 0]) as Box)) + .find_at(cursor.source.content(), cursor.pos) + .map(|m| (m.start(), Box::new([false; 0]) as Box)) } fn on_match( @@ -166,7 +181,12 @@ Last paragraph None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Paragraph { diff --git a/src/elements/raw.rs b/src/elements/raw.rs index 53b8fd7..e1d3474 100644 --- a/src/elements/raw.rs +++ b/src/elements/raw.rs @@ -3,6 +3,7 @@ use crate::document::document::Document; use crate::document::element::ElemKind; use crate::document::element::Element; use crate::lua::kernel::CTX; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::rule::RegexRule; use crate::parser::source::Source; @@ -39,7 +40,12 @@ impl Element for Raw { fn element_name(&self) -> &'static str { "Raw" } - fn compile(&self, _compiler: &Compiler, _document: &dyn Document, _cursor: usize) -> Result { + fn compile( + &self, + _compiler: &Compiler, + _document: &dyn Document, + _cursor: usize, + ) -> Result { Ok(self.content.clone()) } } @@ -73,10 +79,13 @@ impl RawRule { impl RegexRule for RawRule { fn name(&self) -> &'static str { "Raw" } + fn previous(&self) -> Option<&'static str> { Some("Variable Substitution") } fn regexes(&self) -> &[regex::Regex] { &self.re } + fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true } + fn on_regex_match( &self, _index: usize, @@ -271,7 +280,7 @@ mod tests { use crate::elements::text::Text; use crate::parser::langparser::LangParser; use crate::parser::parser::Parser; -use crate::parser::source::SourceFile; + use crate::parser::source::SourceFile; use crate::validate_document; #[test] @@ -285,7 +294,12 @@ Break{?[kind=block] Raw?}NewParagraph{??} None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Paragraph; @@ -308,7 +322,12 @@ Break%%NewParagraph%") None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Paragraph; diff --git a/src/elements/reference.rs b/src/elements/reference.rs index 6cc1aaf..ef7e455 100644 --- a/src/elements/reference.rs +++ b/src/elements/reference.rs @@ -22,6 +22,7 @@ use crate::document::element::ElemKind; use crate::document::element::Element; use crate::document::references::validate_refname; use crate::lsp::semantic::Semantics; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::parser::ReportColors; use crate::parser::rule::RegexRule; @@ -227,10 +228,13 @@ impl ReferenceRule { impl RegexRule for ReferenceRule { fn name(&self) -> &'static str { "Reference" } + fn previous(&self) -> Option<&'static str> { Some("Text") } fn regexes(&self) -> &[regex::Regex] { &self.re } + fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true } + fn on_regex_match<'a>( &self, _: usize, @@ -449,7 +453,12 @@ mod tests { None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Section; @@ -476,7 +485,12 @@ mod tests { None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Paragraph { diff --git a/src/elements/script.rs b/src/elements/script.rs index efdf27e..0020a58 100644 --- a/src/elements/script.rs +++ b/src/elements/script.rs @@ -2,6 +2,7 @@ use crate::document::document::Document; use crate::lsp::semantic::Semantics; use crate::lua::kernel::Kernel; use crate::lua::kernel::KernelContext; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::parser::ReportColors; use crate::parser::rule::RegexRule; @@ -79,10 +80,13 @@ impl ScriptRule { impl RegexRule for ScriptRule { fn name(&self) -> &'static str { "Script" } + fn previous(&self) -> Option<&'static str> { Some("Import") } fn regexes(&self) -> &[regex::Regex] { &self.re } + fn enabled(&self, mode: &ParseMode, id: usize) -> bool { !mode.paragraph_only || id != 0 } + fn on_regex_match<'a>( &self, index: usize, @@ -244,9 +248,12 @@ impl RegexRule for ScriptRule { )) as Rc; state.with_state(|new_state| { - new_state - .parser - .parse_into(new_state, parse_source, document); + new_state.parser.parse_into( + new_state, + parse_source, + document, + ParseMode::default(), + ); }) } } @@ -350,7 +357,12 @@ Evaluation: %% None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Paragraph; @@ -393,6 +405,7 @@ end ParserState::new_with_semantics(&parser, None), source.clone(), None, + ParseMode::default(), ); validate_semantics!(state, source.clone(), 0, script_sep { delta_line == 1, delta_start == 0, length == 2 }; diff --git a/src/elements/section.rs b/src/elements/section.rs index 6ba21b8..1db17b5 100644 --- a/src/elements/section.rs +++ b/src/elements/section.rs @@ -6,6 +6,7 @@ use crate::document::element::Element; use crate::document::element::ReferenceableElement; use crate::lsp::semantic::Semantics; use crate::lua::kernel::CTX; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::rule::RegexRule; use crate::parser::source::Source; @@ -168,10 +169,13 @@ pub mod section_kind { impl RegexRule for SectionRule { fn name(&self) -> &'static str { "Section" } + fn previous(&self) -> Option<&'static str> { Some("Custom Style") } fn regexes(&self) -> &[Regex] { &self.re } + fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only } + fn on_regex_match( &self, _: usize, @@ -327,15 +331,17 @@ impl RegexRule for SectionRule { }), ); - if let Some((sems, tokens)) = Semantics::from_source(token.source(), &state.shared.semantics) + if let Some((sems, tokens)) = + Semantics::from_source(token.source(), &state.shared.semantics) { sems.add(matches.get(1).unwrap().range(), tokens.section_heading); - if let Some(reference) = matches.get(2) - { - sems.add(reference.start()-1..reference.end()+1, tokens.section_reference); + if let Some(reference) = matches.get(2) { + sems.add( + reference.start() - 1..reference.end() + 1, + tokens.section_reference, + ); } - if let Some(kind) = matches.get(3) - { + if let Some(kind) = matches.get(3) { sems.add(kind.range(), tokens.section_kind); } sems.add(matches.get(5).unwrap().range(), tokens.section_name); @@ -452,7 +458,8 @@ mod tests { use crate::parser::langparser::LangParser; use crate::parser::parser::Parser; use crate::parser::source::SourceFile; - use crate::{validate_document, validate_semantics}; + use crate::validate_document; + use crate::validate_semantics; use super::*; @@ -472,7 +479,12 @@ mod tests { None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Section { depth == 1, title == "1" }; @@ -502,7 +514,12 @@ nml.section.push("6", 6, "", "refname") None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Section { depth == 1, title == "1" }; @@ -529,7 +546,7 @@ nml.section.push("6", 6, "", "refname") )); let parser = LangParser::default(); let state = ParserState::new(&parser, None); - let (_, state) = parser.parse(state, source, None); + let (_, state) = parser.parse(state, source, None, ParseMode::default()); let style = state .shared @@ -547,8 +564,7 @@ nml.section.push("6", 6, "", "refname") } #[test] - fn semantics() - { + fn semantics() { let source = Rc::new(SourceFile::with_content( "".to_string(), r#" @@ -560,21 +576,26 @@ nml.section.push("6", 6, "", "refname") None, )); let parser = LangParser::default(); - let (_, state) = parser.parse(ParserState::new_with_semantics(&parser, None), source.clone(), None); + let (_, state) = parser.parse( + ParserState::new_with_semantics(&parser, None), + source.clone(), + None, + ParseMode::default(), + ); validate_semantics!(state, source.clone(), 0, - section_heading { delta_line == 1, delta_start == 0, length == 1 }; - section_name { delta_line == 0, delta_start == 1 }; + section_heading { delta_line == 1, delta_start == 0, length == 1 }; + section_name { delta_line == 0, delta_start == 1 }; - section_heading { delta_line == 1, delta_start == 0, length == 2 }; - section_reference { delta_line == 0, delta_start == 2, length == 4 }; - section_kind { delta_line == 0, delta_start == 4, length == 1 }; - section_name { delta_line == 0, delta_start == 1 }; + section_heading { delta_line == 1, delta_start == 0, length == 2 }; + section_reference { delta_line == 0, delta_start == 2, length == 4 }; + section_kind { delta_line == 0, delta_start == 4, length == 1 }; + section_name { delta_line == 0, delta_start == 1 }; - section_heading { delta_line == 1, delta_start == 0, length == 1 }; - section_reference { delta_line == 0, delta_start == 1, length == 9 }; - section_kind { delta_line == 0, delta_start == 9, length == 2 }; - section_name { delta_line == 0, delta_start == 2 }; - ); + section_heading { delta_line == 1, delta_start == 0, length == 1 }; + section_reference { delta_line == 0, delta_start == 1, length == 9 }; + section_kind { delta_line == 0, delta_start == 9, length == 2 }; + section_name { delta_line == 0, delta_start == 2 }; + ); } } diff --git a/src/elements/style.rs b/src/elements/style.rs index 290f1ab..6bf7ebd 100644 --- a/src/elements/style.rs +++ b/src/elements/style.rs @@ -6,6 +6,7 @@ use crate::document::element::ElemKind; use crate::document::element::Element; use crate::lsp::semantic::Semantics; use crate::lua::kernel::CTX; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::rule::RegexRule; use crate::parser::source::Source; @@ -167,10 +168,13 @@ static STATE_NAME: &str = "elements.style"; impl RegexRule for StyleRule { fn name(&self) -> &'static str { "Style" } + fn previous(&self) -> Option<&'static str> { Some("Layout") } fn regexes(&self) -> &[regex::Regex] { &self.re } + fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true } + fn on_regex_match( &self, index: usize, @@ -316,7 +320,12 @@ __`UNDERLINE+EM`__ None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Paragraph { @@ -357,7 +366,12 @@ terminated here%% None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Paragraph { @@ -399,6 +413,7 @@ __teかst__ *another* ParserState::new_with_semantics(&parser, None), source.clone(), None, + ParseMode::default(), ); validate_semantics!(state, source.clone(), 0, diff --git a/src/elements/tex.rs b/src/elements/tex.rs index f9345b2..2619440 100644 --- a/src/elements/tex.rs +++ b/src/elements/tex.rs @@ -29,6 +29,7 @@ use crate::document::document::Document; use crate::document::element::ElemKind; use crate::document::element::Element; use crate::lua::kernel::CTX; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::parser::ReportColors; use crate::parser::rule::RegexRule; @@ -114,7 +115,9 @@ impl FormattedTex { } let mut result = String::new(); - if let Err(e) = process.stdout.unwrap().read_to_string(&mut result) { panic!("Unable to read `latex2svg` stdout: {}", e) } + if let Err(e) = process.stdout.unwrap().read_to_string(&mut result) { + panic!("Unable to read `latex2svg` stdout: {}", e) + } println!("Done!"); Ok(result) @@ -303,10 +306,13 @@ impl TexRule { impl RegexRule for TexRule { fn name(&self) -> &'static str { "Tex" } + fn previous(&self) -> Option<&'static str> { Some("Code") } fn regexes(&self) -> &[regex::Regex] { &self.re } + fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true } + fn on_regex_match( &self, index: usize, @@ -407,14 +413,16 @@ impl RegexRule for TexRule { .get("caption", |_, value| -> Result { Ok(value.clone()) }) - .ok().map(|(_, value)| value); + .ok() + .map(|(_, value)| value); // Environ let tex_env = properties .get("env", |_, value| -> Result { Ok(value.clone()) }) - .ok().map(|(_, value)| value) + .ok() + .map(|(_, value)| value) .unwrap(); state.push( @@ -548,7 +556,12 @@ $[kind=block,env=another] e^{i\pi}=-1$ None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Tex { mathmode == true, tex == "1+1=2", env == "main", caption == Some("Some, text\\".to_string()) }; @@ -576,7 +589,12 @@ $[env=another] e^{i\pi}=-1$ None, )); let parser = LangParser::default(); - let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None); + let (doc, _) = parser.parse( + ParserState::new(&parser, None), + source, + None, + ParseMode::default(), + ); validate_document!(doc.content().borrow(), 0, Paragraph { diff --git a/src/elements/text.rs b/src/elements/text.rs index 75e1e1a..edc13ff 100644 --- a/src/elements/text.rs +++ b/src/elements/text.rs @@ -11,6 +11,7 @@ use crate::document::document::Document; use crate::document::element::ElemKind; use crate::document::element::Element; use crate::lua::kernel::CTX; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::rule::Rule; use crate::parser::source::Cursor; @@ -24,12 +25,7 @@ pub struct Text { } impl Text { - pub fn new(location: Token, content: String) -> Text { - Text { - location, - content, - } - } + pub fn new(location: Token, content: String) -> Text { Text { location, content } } } impl Element for Text { @@ -37,7 +33,12 @@ impl Element for Text { fn kind(&self) -> ElemKind { ElemKind::Inline } fn element_name(&self) -> &'static str { "Text" } - fn compile(&self, compiler: &Compiler, _document: &dyn Document, _cursor: usize) -> Result { + fn compile( + &self, + compiler: &Compiler, + _document: &dyn Document, + _cursor: usize, + ) -> Result { Ok(Compiler::sanitize(compiler.target(), self.content.as_str())) } } @@ -51,9 +52,15 @@ impl TextRule { impl Rule for TextRule { fn name(&self) -> &'static str { "Text" } + fn previous(&self) -> Option<&'static str> { Some("Link") } - fn next_match(&self, _state: &ParserState, _cursor: &Cursor) -> Option<(usize, Box)> { + fn next_match( + &self, + _mode: &ParseMode, + _state: &ParserState, + _cursor: &Cursor, + ) -> Option<(usize, Box)> { None } diff --git a/src/elements/variable.rs b/src/elements/variable.rs index 5454b8d..8ec6f8e 100644 --- a/src/elements/variable.rs +++ b/src/elements/variable.rs @@ -4,6 +4,7 @@ use crate::document::variable::PathVariable; use crate::document::variable::Variable; use crate::lsp::semantic::Semantics; use crate::lua::kernel::CTX; +use crate::parser::parser::ParseMode; use crate::parser::parser::ParserState; use crate::parser::parser::ReportColors; use crate::parser::rule::RegexRule; @@ -119,10 +120,13 @@ impl VariableRule { impl RegexRule for VariableRule { fn name(&self) -> &'static str { "Variable" } + fn previous(&self) -> Option<&'static str> { Some("Element Style") } fn regexes(&self) -> &[Regex] { &self.re } + fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only } + fn on_regex_match( &self, _: usize, @@ -257,17 +261,18 @@ impl RegexRule for VariableRule { } } - if let Some((sems, tokens)) = Semantics::from_source(token.source(), &state.shared.semantics) + if let Some((sems, tokens)) = + Semantics::from_source(token.source(), &state.shared.semantics) { let name = matches.get(2).unwrap().range(); if let Some(kind) = matches.get(1).map(|m| m.range()) { - sems.add(kind.start-1..kind.start, tokens.variable_operator); + sems.add(kind.start - 1..kind.start, tokens.variable_operator); sems.add(kind, tokens.variable_kind); } else { - sems.add(name.start-1..name.start, tokens.variable_operator); + sems.add(name.start - 1..name.start, tokens.variable_operator); } sems.add(name.clone(), tokens.variable_name); - sems.add(name.end..name.end+1, tokens.variable_sep); + sems.add(name.end..name.end + 1, tokens.variable_sep); let value = matches.get(3).unwrap().range(); sems.add(value.clone(), tokens.variable_value); } @@ -297,8 +302,7 @@ impl RegexRule for VariableRule { let mut value: Option = None; CTX.with_borrow(|ctx| { ctx.as_ref().map(|ctx| { - if let Some(var) = ctx.document.get_variable(name.as_str()) - { + if let Some(var) = ctx.document.get_variable(name.as_str()) { value = Some(var.to_string()); } }) @@ -328,10 +332,13 @@ impl VariableSubstitutionRule { impl RegexRule for VariableSubstitutionRule { fn name(&self) -> &'static str { "Variable Substitution" } + fn previous(&self) -> Option<&'static str> { Some("Variable") } fn regexes(&self) -> &[regex::Regex] { &self.re } + fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true } + fn on_regex_match<'a>( &self, _index: usize, @@ -351,7 +358,9 @@ impl RegexRule for VariableSubstitutionRule { .with_message("Empty variable name") .with_label( Label::new((token.source(), matches.get(0).unwrap().range())) - .with_message("Missing variable name for substitution".to_string()) + .with_message( + "Missing variable name for substitution".to_string(), + ) .with_color(state.parser.colors().error), ) .finish(), @@ -366,7 +375,9 @@ impl RegexRule for VariableSubstitutionRule { .with_message("Invalid variable name") .with_label( Label::new((token.source(), name.range())) - .with_message("Variable names contains leading spaces".to_string()) + .with_message( + "Variable names contains leading spaces".to_string(), + ) .with_color(state.parser.colors().error), ) .with_help("Remove leading spaces") @@ -382,7 +393,9 @@ impl RegexRule for VariableSubstitutionRule { .with_message("Invalid variable name") .with_label( Label::new((token.source(), name.range())) - .with_message("Variable names contains trailing spaces".to_string()) + .with_message( + "Variable names contains trailing spaces".to_string(), + ) .with_color(state.parser.colors().error), ) .with_help("Remove trailing spaces") @@ -392,20 +405,21 @@ impl RegexRule for VariableSubstitutionRule { return result; } // Invalid name - if let Err(msg) = VariableRule::validate_name(state.parser.colors(), name.as_str()) { - result.push( - Report::build(ReportKind::Error, token.source(), name.start()) - .with_message("Invalid variable name") - .with_label( - Label::new((token.source(), name.range())) - .with_message(msg) - .with_color(state.parser.colors().error), - ) - .finish(), - ); + if let Err(msg) = VariableRule::validate_name(state.parser.colors(), name.as_str()) + { + result.push( + Report::build(ReportKind::Error, token.source(), name.start()) + .with_message("Invalid variable name") + .with_label( + Label::new((token.source(), name.range())) + .with_message(msg) + .with_color(state.parser.colors().error), + ) + .finish(), + ); - return result; - } + return result; + } // Get variable match document.get_variable(name.as_str()) { @@ -433,12 +447,13 @@ impl RegexRule for VariableSubstitutionRule { variable.parse(state, token.clone(), document); - if let Some((sems, tokens)) = Semantics::from_source(token.source(), &state.shared.semantics) + if let Some((sems, tokens)) = + Semantics::from_source(token.source(), &state.shared.semantics) { let name = matches.get(1).unwrap().range(); - sems.add(name.start-1..name.start, tokens.variable_sub_sep); + sems.add(name.start - 1..name.start, tokens.variable_sub_sep); sems.add(name.clone(), tokens.variable_sub_name); - sems.add(name.end..name.end+1, tokens.variable_sub_sep); + sems.add(name.end..name.end + 1, tokens.variable_sub_sep); } result diff --git a/src/main.rs b/src/main.rs index cc7b18f..3dc9690 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,9 +2,9 @@ mod cache; mod compiler; mod document; mod elements; +mod lsp; mod lua; mod parser; -mod lsp; use std::env; use std::io::BufWriter; diff --git a/src/parser/langparser.rs b/src/parser/langparser.rs index e14cc43..81d7f5e 100644 --- a/src/parser/langparser.rs +++ b/src/parser/langparser.rs @@ -5,9 +5,9 @@ use crate::document::document::Document; use crate::document::element::DocumentEnd; use crate::document::langdocument::LangDocument; use crate::elements::text::Text; -use crate::lsp::semantic::Semantics; use crate::lsp::semantic::SemanticsData; +use super::parser::ParseMode; use super::parser::Parser; use super::parser::ParserState; use super::parser::ReportColors; @@ -37,8 +37,7 @@ impl LangParser { }; // Register rules - for rule in super::rule::get_rule_registry() - { + for rule in super::rule::get_rule_registry() { s.add_rule(rule).unwrap(); } @@ -59,16 +58,19 @@ impl Parser for LangParser { state: ParserState<'p, 'a>, source: Rc, parent: Option<&'doc dyn Document<'doc>>, + mode: ParseMode, ) -> (Box + 'doc>, ParserState<'p, 'a>) { let doc = LangDocument::new(source.clone(), parent); // Insert semantics into state - if let (Some(_), Some(semantics)) = (source.clone().downcast_rc::().ok(), state.shared.semantics.as_ref()) - { + if let (Some(_), Some(semantics)) = ( + source.clone().downcast_rc::().ok(), + state.shared.semantics.as_ref(), + ) { let mut b = semantics.borrow_mut(); - if !b.sems.contains_key(&source) - { - b.sems.insert(source.clone(), SemanticsData::new(source.clone())); + if !b.sems.contains_key(&source) { + b.sems + .insert(source.clone(), SemanticsData::new(source.clone())); } } @@ -86,7 +88,7 @@ impl Parser for LangParser { } loop { - let (rule_pos, mut result) = state.update_matches(&cursor); + let (rule_pos, mut result) = state.update_matches(&mode, &cursor); // Unmatched content let text_content = @@ -125,13 +127,12 @@ impl Parser for LangParser { super::state::Scope::DOCUMENT, )); - if parent.is_none() - { + if parent.is_none() { state.push( &doc, Box::new(DocumentEnd(Token::new( - doc.source().content().len()..doc.source().content().len(), - doc.source(), + doc.source().content().len()..doc.source().content().len(), + doc.source(), ))), ); } @@ -144,12 +145,13 @@ impl Parser for LangParser { state: ParserState<'p, 'a>, source: Rc, document: &'doc dyn Document<'doc>, + mode: ParseMode, ) -> ParserState<'p, 'a> { let content = source.content(); let mut cursor = Cursor::new(0usize, source.clone()); loop { - let (rule_pos, mut result) = state.update_matches(&cursor); + let (rule_pos, mut result) = state.update_matches(&mode, &cursor); // Unmatched content let text_content = diff --git a/src/parser/parser.rs b/src/parser/parser.rs index a1a7d9c..d95f13a 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -147,7 +147,10 @@ impl<'a, 'b> ParserState<'a, 'b> { /// Constructs a new state with semantics enabled /// See [`ParserState::new`] for mote information - pub fn new_with_semantics(parser: &'a dyn Parser, parent: Option<&'a ParserState<'a, 'b>>) -> Self { + pub fn new_with_semantics( + parser: &'a dyn Parser, + parent: Option<&'a ParserState<'a, 'b>>, + ) -> Self { let matches = parser.rules().iter().map(|_| (0, None)).collect::>(); let shared = if let Some(parent) = &parent { parent.shared.clone() @@ -199,7 +202,11 @@ impl<'a, 'b> ParserState<'a, 'b> { /// Notes that the result of every call to [`Rule::next_match`] gets stored /// in a table: [`ParserState::matches`]. Until the cursor steps over a /// position in the table, `next_match` won't be called. - pub fn update_matches(&self, cursor: &Cursor) -> (Cursor, Option<(usize, Box)>) { + pub fn update_matches( + &self, + mode: &ParseMode, + cursor: &Cursor, + ) -> (Cursor, Option<(usize, Box)>) { let mut matches_borrow = self.matches.borrow_mut(); self.parser @@ -212,7 +219,7 @@ impl<'a, 'b> ParserState<'a, 'b> { return; } - (*matched_at, *match_data) = match rule.next_match(self, cursor) { + (*matched_at, *match_data) = match rule.next_match(&mode, self, cursor) { None => (usize::MAX, None), Some((mut pos, mut data)) => { // Check if escaped @@ -233,7 +240,7 @@ impl<'a, 'b> ParserState<'a, 'b> { } // Find next potential match - (pos, data) = match rule.next_match(self, &cursor.at(pos + 1)) { + (pos, data) = match rule.next_match(&mode, self, &cursor.at(pos + 1)) { Some((new_pos, new_data)) => (new_pos, new_data), None => (usize::MAX, data), // Stop iterating } @@ -308,24 +315,28 @@ impl<'a, 'b> ParserState<'a, 'b> { /// # Error /// /// Returns an error if `rule_name` was not found in the parser's ruleset. - pub fn reset_match(&self, rule_name: &str) -> Result<(), String> - { - if self.parser.rules().iter() + pub fn reset_match(&self, rule_name: &str) -> Result<(), String> { + if self + .parser + .rules() + .iter() .zip(self.matches.borrow_mut().iter_mut()) .try_for_each(|(rule, (match_pos, match_data))| { - if rule.name() != rule_name { return Ok(()) } + if rule.name() != rule_name { + return Ok(()); + } *match_pos = 0; match_data.take(); Err(()) - }).is_ok() + }) + .is_ok() { return Err(format!("Could not find rule: {rule_name}")); } // Resurcively reset - if let Some(parent) = self.parent - { + if let Some(parent) = self.parent { return parent.reset_match(rule_name); } @@ -333,6 +344,18 @@ impl<'a, 'b> ParserState<'a, 'b> { } } +pub struct ParseMode { + pub paragraph_only: bool, +} + +impl Default for ParseMode { + fn default() -> Self { + Self { + paragraph_only: false, + } + } +} + pub trait Parser { /// Gets the colors for formatting errors /// @@ -365,6 +388,7 @@ pub trait Parser { state: ParserState<'p, 'a>, source: Rc, parent: Option<&'doc dyn Document<'doc>>, + mode: ParseMode, ) -> (Box + 'doc>, ParserState<'p, 'a>); /// Parse [`Source`] into an already existing [`Document`] @@ -384,6 +408,7 @@ pub trait Parser { state: ParserState<'p, 'a>, source: Rc, document: &'doc dyn Document<'doc>, + mode: ParseMode, ) -> ParserState<'p, 'a>; /// Adds a rule to the parser. @@ -444,8 +469,11 @@ pub trait Parser { if let Some(_s) = source.downcast_ref::() { let start = location.start() - + if location.source().content().as_bytes()[location.start()] - == b'\n' { 1 } else { 0 }; + + if location.source().content().as_bytes()[location.start()] == b'\n' { + 1 + } else { + 0 + }; report.labels.push( Label::new((location.source(), start..location.end())) .with_message("In evaluation of") diff --git a/src/parser/rule.rs b/src/parser/rule.rs index 8ed0aef..f27ee2c 100644 --- a/src/parser/rule.rs +++ b/src/parser/rule.rs @@ -1,4 +1,5 @@ use super::layout::LayoutHolder; +use super::parser::ParseMode; use super::parser::ParserState; use super::source::Cursor; use super::source::Source; @@ -73,7 +74,13 @@ pub trait Rule: Downcast { fn previous(&self) -> Option<&'static str>; /// Finds the next match starting from [`cursor`] - fn next_match(&self, state: &ParserState, cursor: &Cursor) -> Option<(usize, Box)>; + fn next_match( + &self, + mode: &ParseMode, + state: &ParserState, + cursor: &Cursor, + ) -> Option<(usize, Box)>; + /// Callback when rule matches fn on_match<'a>( &self, @@ -110,6 +117,9 @@ pub trait RegexRule { /// Returns the rule's regexes fn regexes(&self) -> &[regex::Regex]; + /// Wheter parsing for the rule is enabled + fn enabled(&self, mode: &ParseMode, index: usize) -> bool; + /// Callback on regex rule match fn on_regex_match<'a>( &self, @@ -127,13 +137,22 @@ pub trait RegexRule { impl Rule for T { fn name(&self) -> &'static str { RegexRule::name(self) } + fn previous(&self) -> Option<&'static str> { RegexRule::previous(self) } /// Finds the next match starting from [`cursor`] - fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box)> { + fn next_match( + &self, + mode: &ParseMode, + _state: &ParserState, + cursor: &Cursor, + ) -> Option<(usize, Box)> { let content = cursor.source.content(); let mut found: Option<(usize, usize)> = None; self.regexes().iter().enumerate().for_each(|(id, re)| { + if !RegexRule::enabled(self, mode, id) { + return; + } if let Some(m) = re.find_at(content.as_str(), cursor.pos) { found = found .map(|(f_pos, f_id)| { diff --git a/src/parser/style.rs b/src/parser/style.rs index 331366c..7bc2e76 100644 --- a/src/parser/style.rs +++ b/src/parser/style.rs @@ -60,7 +60,8 @@ macro_rules! impl_elementstyle { serde_json::from_str::<$t>(json) .map_err(|e| e.to_string()) .map(|obj| { - std::rc::Rc::new(obj) as std::rc::Rc + std::rc::Rc::new(obj) + as std::rc::Rc }) } diff --git a/src/parser/util.rs b/src/parser/util.rs index 4132b66..ff612d2 100644 --- a/src/parser/util.rs +++ b/src/parser/util.rs @@ -8,6 +8,7 @@ use crate::document::document::DocumentAccessors; use crate::document::element::ElemKind; use crate::elements::paragraph::Paragraph; +use super::parser::ParseMode; use super::parser::ParserState; use super::source::Source; @@ -143,7 +144,7 @@ pub fn parse_paragraph<'a>( let parsed = state.with_state(|new_state| -> Box { new_state .parser - .parse(new_state, source.clone(), Some(document)) + .parse(new_state, source.clone(), Some(document), ParseMode { paragraph_only: true }) .0 }); if parsed.content().borrow().len() > 1 { diff --git a/src/server.rs b/src/server.rs index b7c332a..5eca473 100644 --- a/src/server.rs +++ b/src/server.rs @@ -10,6 +10,7 @@ use std::rc::Rc; use dashmap::DashMap; use parser::langparser::LangParser; +use parser::parser::ParseMode; use parser::parser::Parser; use parser::parser::ParserState; use parser::source::SourceFile; @@ -42,7 +43,7 @@ impl Backend { // Which will require a dyn Document to work let source = Rc::new(SourceFile::with_content(params.uri.to_string(), params.text.clone(), None)); let parser = LangParser::default(); - let (_doc, state) = parser.parse(ParserState::new_with_semantics(&parser, None), source.clone(), None); + let (_doc, state) = parser.parse(ParserState::new_with_semantics(&parser, None), source.clone(), None, ParseMode::default()); if let Some(sems) = state.shared.semantics.as_ref() {