From ce9effd46587ad5704d4b81d01e9467a51ab8376 Mon Sep 17 00:00:00 2001 From: ef3d0c3e Date: Tue, 6 Aug 2024 18:58:41 +0200 Subject: [PATCH] Refactor done --- src/document/langdocument.rs | 27 ++-- src/document/references.rs | 3 +- src/document/variable.rs | 9 +- src/elements/code.rs | 19 ++- src/elements/comment.rs | 18 ++- src/elements/customstyle.rs | 150 +++++++++++----------- src/elements/elemstyle.rs | 26 ++-- src/elements/graphviz.rs | 19 +-- src/elements/import.rs | 8 +- src/elements/layout.rs | 77 ++++++------ src/elements/link.rs | 14 +-- src/elements/list.rs | 8 +- src/elements/media.rs | 13 +- src/elements/paragraph.rs | 8 +- src/elements/raw.rs | 10 +- src/elements/reference.rs | 12 +- src/elements/script.rs | 61 ++++----- src/elements/section.rs | 27 ++-- src/elements/style.rs | 25 ++-- src/elements/tex.rs | 15 ++- src/elements/text.rs | 7 +- src/elements/variable.rs | 7 +- src/lua/kernel.rs | 16 +-- src/main.rs | 12 +- src/parser/customstyle.rs | 17 ++- src/parser/langparser.rs | 71 +++++------ src/parser/layout.rs | 4 +- src/parser/parser.rs | 237 +++++++++++++---------------------- src/parser/rule.rs | 13 +- src/parser/state.rs | 24 ++-- src/parser/style.rs | 6 +- src/parser/util.rs | 4 +- 32 files changed, 459 insertions(+), 508 deletions(-) diff --git a/src/document/langdocument.rs b/src/document/langdocument.rs index 60b7e14..69d0366 100644 --- a/src/document/langdocument.rs +++ b/src/document/langdocument.rs @@ -1,23 +1,24 @@ -use std::{cell::RefCell, rc::Rc}; +use std::cell::RefCell; +use std::rc::Rc; use crate::parser::source::Source; -use super::{document::{Document, Scope}, element::Element}; +use super::document::Document; +use super::document::Scope; +use super::element::Element; #[derive(Debug)] pub struct LangDocument<'a> { source: Rc, - parent: Option<&'a dyn Document<'a>>, /// Document's parent - + parent: Option<&'a dyn Document<'a>>, + /// Document's parent // FIXME: Render these fields private pub content: RefCell>>, pub scope: RefCell, } -impl<'a> LangDocument<'a> -{ - pub fn new(source: Rc, parent: Option<&'a dyn Document<'a>>) -> Self - { +impl<'a> LangDocument<'a> { + pub fn new(source: Rc, parent: Option<&'a dyn Document<'a>>) -> Self { Self { source: source, parent: parent, @@ -28,11 +29,13 @@ impl<'a> LangDocument<'a> } impl<'a> Document<'a> for LangDocument<'a> { - fn source(&self) -> Rc { self.source.clone() } + fn source(&self) -> Rc { self.source.clone() } - fn parent(&self) -> Option<&'a dyn Document<'a>> { self.parent.and_then(|p| Some(p as &dyn Document<'a>)) } + fn parent(&self) -> Option<&'a dyn Document<'a>> { + self.parent.and_then(|p| Some(p as &dyn Document<'a>)) + } - fn content(&self) -> &RefCell>> { &self.content } + fn content(&self) -> &RefCell>> { &self.content } - fn scope(&self) -> &RefCell { &self.scope } + fn scope(&self) -> &RefCell { &self.scope } } diff --git a/src/document/references.rs b/src/document/references.rs index 6ce161a..49a14b7 100644 --- a/src/document/references.rs +++ b/src/document/references.rs @@ -45,6 +45,7 @@ pub mod tests { use crate::parser::langparser::LangParser; use crate::parser::parser::Parser; use crate::parser::source::SourceFile; + use crate::ParserState; #[test] fn validate_refname_tests() { @@ -54,7 +55,7 @@ pub mod tests { None, )); let parser = LangParser::default(); - let doc = parser.parse(source, None); + let doc = parser.parse(ParserState::new(&parser, None), source, None); assert_eq!(validate_refname(&*doc, " abc ", true), Ok("abc")); assert_eq!( diff --git a/src/document/variable.rs b/src/document/variable.rs index 1cab322..2bfff30 100644 --- a/src/document/variable.rs +++ b/src/document/variable.rs @@ -1,6 +1,5 @@ use super::document::Document; use crate::elements::text::Text; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::source::Source; use crate::parser::source::Token; @@ -19,7 +18,7 @@ pub trait Variable { /// Converts variable to a string fn to_string(&self) -> String; - fn parse<'a>(&self, state: &mut ParserState, location: Token, document: &'a dyn Document<'a>); + fn parse<'a>(&self, state: &ParserState, location: Token, document: &'a dyn Document<'a>); } impl core::fmt::Debug for dyn Variable { @@ -57,7 +56,7 @@ impl Variable for BaseVariable { fn to_string(&self) -> String { self.value.clone() } - fn parse<'a>(&self, state: &mut ParserState, _location: Token, document: &'a dyn Document<'a>) { + fn parse<'a>(&self, state: &ParserState, _location: Token, document: &'a dyn Document<'a>) { let source = Rc::new(VirtualSource::new( self.location().clone(), self.name().to_string(), @@ -97,14 +96,14 @@ impl Variable for PathVariable { fn to_string(&self) -> String { self.path.to_str().unwrap().to_string() } - fn parse<'a>(&self, state: &mut ParserState, location: Token, document: &'a dyn Document) { + fn parse<'a>(&self, state: &ParserState, location: Token, document: &'a dyn Document) { let source = Rc::new(VirtualSource::new( location, self.name().to_string(), self.to_string(), )); - state.parser.push( + state.push( document, Box::new(Text::new( Token::new(0..source.content().len(), source), diff --git a/src/elements/code.rs b/src/elements/code.rs index 3b11e37..d192605 100644 --- a/src/elements/code.rs +++ b/src/elements/code.rs @@ -25,7 +25,6 @@ use crate::document::document::Document; use crate::document::element::ElemKind; use crate::document::element::Element; use crate::lua::kernel::CTX; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::rule::RegexRule; use crate::parser::source::Source; @@ -324,7 +323,7 @@ impl CodeRule { ) .unwrap(), ], - properties: PropertyParser{ properties: props }, + properties: PropertyParser { properties: props }, } } } @@ -337,7 +336,7 @@ impl RegexRule for CodeRule { fn on_regex_match<'a>( &self, index: usize, - state: &mut ParserState, + state: &ParserState, document: &'a dyn Document, token: Token, matches: Captures, @@ -505,7 +504,7 @@ impl RegexRule for CodeRule { } }; - state.parser.push( + state.push( document, Box::new(Code::new( token.clone(), @@ -526,7 +525,7 @@ impl RegexRule for CodeRule { CodeKind::Inline }; - state.parser.push( + state.push( document, Box::new(Code::new( token.clone(), @@ -555,7 +554,7 @@ impl RegexRule for CodeRule { .get_variable("code.theme") .and_then(|var| Some(var.to_string())); - ctx.parser.push( + ctx.state.push( ctx.document, Box::new(Code { location: ctx.location.clone(), @@ -586,7 +585,7 @@ impl RegexRule for CodeRule { .get_variable("code.theme") .and_then(|var| Some(var.to_string())); - ctx.parser.push( + ctx.state.push( ctx.document, Box::new(Code { location: ctx.location.clone(), @@ -624,7 +623,7 @@ impl RegexRule for CodeRule { .get_variable("code.theme") .and_then(|var| Some(var.to_string())); - ctx.parser.push( + ctx.state.push( ctx.document, Box::new(Code { location: ctx.location.clone(), @@ -653,6 +652,7 @@ impl RegexRule for CodeRule { mod tests { use super::*; use crate::parser::langparser::LangParser; + use crate::parser::parser::Parser; use crate::parser::source::SourceFile; #[test] @@ -726,8 +726,7 @@ fn fact(n: usize) -> usize None, )); let parser = LangParser::default(); - //let compiler = Compiler::new(Target::HTML, None); - let doc = parser.parse(source, None); + let doc = parser.parse(ParserState::new(&parser, None), source, None); let borrow = doc.content().borrow(); let found = borrow diff --git a/src/elements/comment.rs b/src/elements/comment.rs index 658c3bb..c1b0761 100644 --- a/src/elements/comment.rs +++ b/src/elements/comment.rs @@ -2,7 +2,6 @@ use crate::compiler::compiler::Compiler; use crate::document::document::Document; use crate::document::element::ElemKind; use crate::document::element::Element; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::rule::RegexRule; use crate::parser::source::Source; @@ -59,7 +58,7 @@ impl RegexRule for CommentRule { fn on_regex_match<'a>( &self, _: usize, - state: &mut ParserState, + state: &ParserState, document: &'a dyn Document, token: Token, matches: Captures, @@ -87,7 +86,13 @@ impl RegexRule for CommentRule { } }; - state.parser.push(document, Box::new(Comment::new(token.clone(), content))); + state.push( + document, + Box::new(Comment { + location: token.clone(), + content, + }), + ); return reports; } @@ -96,9 +101,10 @@ impl RegexRule for CommentRule { #[cfg(test)] mod tests { use crate::elements::paragraph::Paragraph; -use crate::elements::style::Style; -use crate::elements::text::Text; -use crate::parser::langparser::LangParser; + use crate::elements::style::Style; + use crate::elements::text::Text; + use crate::parser::langparser::LangParser; + use crate::parser::parser::Parser; use crate::parser::source::SourceFile; use crate::validate_document; diff --git a/src/elements/customstyle.rs b/src/elements/customstyle.rs index c87e3c6..4489a60 100644 --- a/src/elements/customstyle.rs +++ b/src/elements/customstyle.rs @@ -1,4 +1,6 @@ +use crate::lua::kernel::Kernel; use std::any::Any; +use std::cell::Ref; use std::cell::RefCell; use std::collections::HashMap; use std::ops::Range; @@ -19,7 +21,6 @@ use crate::lua::kernel::KernelContext; use crate::lua::kernel::CTX; use crate::parser::customstyle::CustomStyle; use crate::parser::customstyle::CustomStyleToken; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::rule::Rule; use crate::parser::source::Cursor; @@ -28,8 +29,6 @@ use crate::parser::source::Token; use crate::parser::state::RuleState; use crate::parser::state::Scope; -use lazy_static::lazy_static; - use super::paragraph::Paragraph; #[derive(Debug)] @@ -48,75 +47,78 @@ impl CustomStyle for LuaCustomStyle { fn on_start<'a>( &self, location: Token, - parser_state: &mut ParserState, + state: &ParserState, document: &'a dyn Document<'a>, ) -> Vec, Range)>> { - let kernel = parser_state.shared.kernels.get("main").unwrap(); + let kernel: Ref<'_, Kernel> = + Ref::map(state.shared.kernels.borrow(), |b| b.get("main").unwrap()); + //let kernel = RefMut::map(parser_state.shared.kernels.borrow(), |ker| ker.get("main").unwrap()); let ctx = KernelContext { location: location.clone(), - parser_state, + state, document, }; - let mut result = Ok(()); + let mut reports = vec![]; kernel.run_with_context(ctx, |lua| { let chunk = lua.load(self.start.as_str()); if let Err(err) = chunk.eval::<()>() { - result = Err( + reports.push( Report::build(ReportKind::Error, location.source(), location.start()) .with_message("Lua execution failed") .with_label( Label::new((location.source(), location.range.clone())) .with_message(err.to_string()) - .with_color(parser_state.parser.colors().error), + .with_color(state.parser.colors().error), ) .with_note(format!( "When trying to start custom style {}", - self.name().fg(parser_state.parser.colors().info) + self.name().fg(state.parser.colors().info) )) .finish(), ); } }); - result + reports } fn on_end<'a>( &self, location: Token, - parser_state: &mut ParserState, - document: &'a dyn Document<'a> + state: &ParserState, + document: &'a dyn Document<'a>, ) -> Vec, Range)>> { - let kernel = parser_state.shared.kernels.get("main").unwrap(); + let kernel: Ref<'_, Kernel> = + Ref::map(state.shared.kernels.borrow(), |b| b.get("main").unwrap()); let ctx = KernelContext { location: location.clone(), - parser_state, + state, document, }; - let mut result = Ok(()); + let mut reports = vec![]; kernel.run_with_context(ctx, |lua| { let chunk = lua.load(self.end.as_str()); if let Err(err) = chunk.eval::<()>() { - result = Err( + reports.push( Report::build(ReportKind::Error, location.source(), location.start()) .with_message("Lua execution failed") .with_label( Label::new((location.source(), location.range.clone())) .with_message(err.to_string()) - .with_color(parser_state.colors().error), + .with_color(state.parser.colors().error), ) .with_note(format!( "When trying to end custom style {}", - self.name().fg(parser_state.colors().info) + self.name().fg(state.parser.colors().info) )) .finish(), ); } }); - result + reports } } @@ -129,8 +131,8 @@ impl RuleState for CustomStyleState { fn on_remove<'a>( &self, - state: &mut ParserState, - document: &dyn Document + state: &ParserState, + document: &dyn Document, ) -> Vec, Range)>> { let mut reports = vec![]; @@ -189,6 +191,7 @@ impl Rule for CustomStyleRule { state .shared .custom_styles + .borrow() .iter() .for_each(|(_name, style)| match style.tokens() { CustomStyleToken::Toggle(s) => { @@ -228,67 +231,61 @@ impl Rule for CustomStyleRule { fn on_match<'a>( &self, - state: &mut ParserState, + state: &ParserState, document: &'a dyn Document<'a>, cursor: Cursor, - match_data: Option>, + match_data: Box, ) -> (Cursor, Vec, Range)>>) { let (style, end) = match_data - .as_ref() - .unwrap() .downcast_ref::<(Rc, bool)>() .unwrap(); - let query = state.shared.rule_state.get(STATE_NAME); - let rule_state = match query { - Some(state) => state, + let mut rule_state_borrow = state.shared.rule_state.borrow_mut(); + let style_state = match rule_state_borrow.get(STATE_NAME) { + Some(rule_state) => rule_state, + // Insert as a new state None => { - // Insert as a new state - match state.shared.rule_state.insert( + match rule_state_borrow.insert( STATE_NAME.into(), Rc::new(RefCell::new(CustomStyleState { toggled: HashMap::new(), })), ) { - Err(_) => panic!("Unknown error"), - Ok(state) => state, + Err(err) => panic!("{err}"), + Ok(rule_state) => rule_state, } } }; let (close, token) = match style.tokens() { CustomStyleToken::Toggle(s) => { - let mut borrow = rule_state.borrow_mut(); - let state = borrow.downcast_mut::().unwrap(); + let mut borrow = style_state.as_ref().borrow_mut(); + let style_state = borrow.downcast_mut::().unwrap(); - match state.toggled.get(style.name()) { - Some(_) => { - // Terminate style - let token = - Token::new(cursor.pos..cursor.pos + s.len(), cursor.source.clone()); + if style_state.toggled.get(style.name()).is_some() { + // Terminate style + let token = Token::new(cursor.pos..cursor.pos + s.len(), cursor.source.clone()); - state.toggled.remove(style.name()); - (true, token) - } - None => { - // Start style - let token = - Token::new(cursor.pos..cursor.pos + s.len(), cursor.source.clone()); + style_state.toggled.remove(style.name()); + (true, token) + } else { + // Start style + let token = Token::new(cursor.pos..cursor.pos + s.len(), cursor.source.clone()); - state.toggled.insert(style.name().into(), token.clone()); - (false, token) - } + style_state + .toggled + .insert(style.name().into(), token.clone()); + (false, token) } } CustomStyleToken::Pair(s_begin, s_end) => { - let mut borrow = rule_state.borrow_mut(); - let state = borrow.downcast_mut::().unwrap(); - + let mut borrow = style_state.borrow_mut(); + let style_state = borrow.downcast_mut::().unwrap(); if *end { // Terminate style let token = Token::new(cursor.pos..cursor.pos + s_end.len(), cursor.source.clone()); - if state.toggled.get(style.name()).is_none() { + if style_state.toggled.get(style.name()).is_none() { return ( cursor.at(cursor.pos + s_end.len()), vec![ @@ -308,7 +305,7 @@ impl Rule for CustomStyleRule { ); } - state.toggled.remove(style.name()); + style_state.toggled.remove(style.name()); (true, token) } else { // Start style @@ -316,7 +313,7 @@ impl Rule for CustomStyleRule { cursor.pos..cursor.pos + s_begin.len(), cursor.source.clone(), ); - if let Some(start_token) = state.toggled.get(style.name()) { + if let Some(start_token) = style_state.toggled.get(style.name()) { return ( cursor.at(cursor.pos + s_end.len()), vec![Report::build( @@ -347,27 +344,23 @@ impl Rule for CustomStyleRule { ); } - state.toggled.insert(style.name().into(), token.clone()); + style_state + .toggled + .insert(style.name().into(), token.clone()); (false, token) } } }; - if let Err(rep) = if close { + let reports = if close { style.on_end(token.clone(), state, document) } else { style.on_start(token.clone(), state, document) - } { - return ( - cursor.at(token.end()), - vec![unsafe { - // TODO - std::mem::transmute(rep) - }], - ); - } else { - (cursor.at(token.end()), vec![]) - } + }; + + (cursor.at(token.end()), unsafe { + std::mem::transmute(reports) + }) } fn register_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { @@ -388,7 +381,9 @@ impl Rule for CustomStyleRule { CTX.with_borrow(|ctx| { ctx.as_ref().map(|ctx| { - if let Some(_) = ctx.state.shared.custom_styles.get(name.as_str()) { + if let Some(_) = + ctx.state.shared.custom_styles.borrow().get(name.as_str()) + { result = Err(BadArgument { to: Some("define_toggled".to_string()), pos: 1, @@ -399,7 +394,11 @@ impl Rule for CustomStyleRule { }); return; } - ctx.state.shared.custom_styles.insert(Rc::new(style)); + ctx.state + .shared + .custom_styles + .borrow_mut() + .insert(Rc::new(style)); }); }); @@ -443,7 +442,7 @@ impl Rule for CustomStyleRule { CTX.with_borrow(|ctx| { ctx.as_ref().map(|ctx| { - if let Some(_) = ctx.state.shared.custom_styles.get(name.as_str()) { + if let Some(_) = ctx.state.shared.custom_styles.borrow().get(name.as_str()) { result = Err(BadArgument { to: Some("define_paired".to_string()), pos: 1, @@ -454,7 +453,7 @@ impl Rule for CustomStyleRule { }); return; } - ctx.state.shared.custom_styles.insert(Rc::new(style)); + ctx.state.shared.custom_styles.borrow_mut().insert(Rc::new(style)); }); }); @@ -473,6 +472,7 @@ mod tests { use crate::elements::raw::Raw; use crate::elements::text::Text; use crate::parser::langparser::LangParser; + use crate::parser::parser::Parser; use crate::parser::source::SourceFile; use crate::validate_document; @@ -505,7 +505,7 @@ pre |styled| post °Hello°. None, )); let parser = LangParser::default(); - let doc = parser.parse(source, None); + let doc = parser.parse(ParserState::new(&parser, None), source, None); validate_document!(doc.content().borrow(), 0, Paragraph { @@ -549,7 +549,7 @@ pre [styled] post (Hello). None, )); let parser = LangParser::default(); - let doc = parser.parse(source, None); + let doc = parser.parse(ParserState::new(&parser, None), source, None); validate_document!(doc.content().borrow(), 0, Paragraph { diff --git a/src/elements/elemstyle.rs b/src/elements/elemstyle.rs index 0aaa726..51a8dcd 100644 --- a/src/elements/elemstyle.rs +++ b/src/elements/elemstyle.rs @@ -1,3 +1,4 @@ +use crate::parser::style::ElementStyle; use std::any::Any; use std::ops::Range; use std::rc::Rc; @@ -15,7 +16,6 @@ use regex::Regex; use crate::document::document::Document; use crate::lua::kernel::CTX; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::rule::Rule; use crate::parser::source::Cursor; @@ -69,10 +69,10 @@ impl Rule for ElemStyleRule { fn on_match<'a>( &self, - state: &mut ParserState, + state: &ParserState, _document: &'a (dyn Document<'a> + 'a), cursor: Cursor, - _match_data: Option>, + _match_data: Box, ) -> (Cursor, Vec, Range)>>) { let mut reports = vec![]; let matches = self @@ -81,7 +81,7 @@ impl Rule for ElemStyleRule { .unwrap(); let mut cursor = cursor.at(matches.get(0).unwrap().end() - 1); - let style = if let Some(key) = matches.get(1) { + let style: Rc = if let Some(key) = matches.get(1) { let trimmed = key.as_str().trim_start().trim_end(); // Check if empty @@ -100,7 +100,7 @@ impl Rule for ElemStyleRule { } // Check if key exists - if !state.shared.style.is_registered(trimmed) { + if !state.shared.styles.borrow().is_registered(trimmed) { reports.push( Report::build(ReportKind::Error, cursor.source.clone(), key.start()) .with_message("Unknown Style Key") @@ -118,7 +118,7 @@ impl Rule for ElemStyleRule { return (cursor, reports); } - state.shared.style.current_style(trimmed) + state.shared.styles.borrow().current(trimmed) } else { panic!("Unknown error") }; @@ -172,7 +172,7 @@ impl Rule for ElemStyleRule { } }; - state.shared.styles.set_current(new_style); + state.shared.styles.borrow_mut().set_current(new_style); (cursor, reports) } @@ -186,7 +186,13 @@ impl Rule for ElemStyleRule { let mut result = Ok(()); CTX.with_borrow(|ctx| { ctx.as_ref().map(|ctx| { - if !ctx.parser.is_style_registered(style_key.as_str()) { + if !ctx + .state + .shared + .styles + .borrow() + .is_registered(style_key.as_str()) + { result = Err(BadArgument { to: Some("set".to_string()), pos: 1, @@ -198,7 +204,7 @@ impl Rule for ElemStyleRule { return; } - let style = ctx.parser.current_style(style_key.as_str()); + let style = ctx.state.shared.styles.borrow().current(style_key.as_str()); let new_style = match style.from_lua(lua, new_style) { Err(err) => { result = Err(err); @@ -207,7 +213,7 @@ impl Rule for ElemStyleRule { Ok(new_style) => new_style, }; - ctx.parser.set_current_style(new_style); + ctx.state.shared.styles.borrow_mut().set_current(new_style); }) }); diff --git a/src/elements/graphviz.rs b/src/elements/graphviz.rs index 103530d..c0ae45d 100644 --- a/src/elements/graphviz.rs +++ b/src/elements/graphviz.rs @@ -16,8 +16,6 @@ use crypto::sha2::Sha512; use graphviz_rust::cmd::Format; use graphviz_rust::cmd::Layout; use graphviz_rust::exec_dot; -use mlua::Function; -use mlua::Lua; use regex::Captures; use regex::Regex; @@ -28,7 +26,6 @@ use crate::compiler::compiler::Target; use crate::document::document::Document; use crate::document::element::ElemKind; use crate::document::element::Element; -use crate::parser::parser::Parser; use crate::parser::rule::RegexRule; use crate::parser::source::Source; use crate::parser::source::Token; @@ -71,7 +68,7 @@ impl Graphviz { let split_at = out.split_at(svg_start).1.find('\n').unwrap(); let mut result = format!(" panic!("Unknown error") + _ => panic!("Unknown error"), }, }; - state.parser.push( + state.push( document, Box::new(Graphviz { location: token, diff --git a/src/elements/import.rs b/src/elements/import.rs index b05a9db..2407d15 100644 --- a/src/elements/import.rs +++ b/src/elements/import.rs @@ -1,6 +1,5 @@ use crate::document::document::Document; use crate::document::document::DocumentAccessors; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::parser::ReportColors; use crate::parser::rule::RegexRule; @@ -47,7 +46,7 @@ impl RegexRule for ImportRule { fn on_regex_match<'a>( &self, _: usize, - state: &mut ParserState, + state: &ParserState, document: &'a dyn Document<'a>, token: Token, matches: Captures, @@ -120,7 +119,8 @@ impl RegexRule for ImportRule { // [Optional] import as let import_as = match matches.get(1) { - Some(as_name) => match ImportRule::validate_as(state.parser.colors(), as_name.as_str()) { + Some(as_name) => match ImportRule::validate_as(state.parser.colors(), as_name.as_str()) + { Ok(as_name) => as_name, Err(msg) => { result.push( @@ -168,7 +168,7 @@ impl RegexRule for ImportRule { // Close paragraph // TODO2: Check if this is safe to remove if document.last_element::().is_none() { - state.parser.push( + state.push( document, Box::new(Paragraph { location: Token::new(token.end()..token.end(), token.source()), diff --git a/src/elements/layout.rs b/src/elements/layout.rs index 8b88051..710768e 100644 --- a/src/elements/layout.rs +++ b/src/elements/layout.rs @@ -6,7 +6,6 @@ use crate::document::element::Element; use crate::lua::kernel::CTX; use crate::parser::layout::LayoutHolder; use crate::parser::layout::LayoutType; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::parser::ReportColors; use crate::parser::rule::RegexRule; @@ -56,7 +55,7 @@ impl FromStr for LayoutToken { mod default_layouts { use crate::parser::layout::LayoutType; -use crate::parser::util::Property; + use crate::parser::util::Property; use crate::parser::util::PropertyParser; use super::*; @@ -249,7 +248,7 @@ impl RuleState for LayoutState { fn on_remove<'a>( &self, - state: &mut ParserState, + state: &ParserState, document: &dyn Document, ) -> Vec, Range)>> { let mut reports = vec![]; @@ -315,17 +314,17 @@ impl LayoutRule { } } - pub fn initialize_state(state: &mut ParserState) -> Rc> { - let query = state.shared.rule_state.get(STATE_NAME); - match query { + pub fn initialize_state(state: &ParserState) -> Rc> { + let mut rule_state_borrow = state.shared.rule_state.borrow_mut(); + match rule_state_borrow.get(STATE_NAME) { Some(state) => state, None => { // Insert as a new state - match state.shared.rule_state.insert( + match rule_state_borrow.insert( STATE_NAME.into(), - Rc::new(LayoutState { stack: vec![] }), + Rc::new(RefCell::new(LayoutState { stack: vec![] })), ) { - Err(_) => panic!("Unknown error"), + Err(err) => panic!("{err}"), Ok(state) => state, } } @@ -385,7 +384,7 @@ impl RegexRule for LayoutRule { fn on_regex_match( &self, index: usize, - state: &mut ParserState, + state: &ParserState, document: &dyn Document, token: Token, matches: Captures, @@ -453,7 +452,7 @@ impl RegexRule for LayoutRule { } // Get layout - let layout_type = match state.shared.layouts.get(trimmed) { + let layout_type = match state.shared.layouts.borrow().get(trimmed) { None => { reports.push( Report::build(ReportKind::Error, token.source(), name.start()) @@ -487,7 +486,7 @@ impl RegexRule for LayoutRule { } }; - state.parser.push( + state.push( document, Box::new(Layout { location: token.clone(), @@ -498,11 +497,12 @@ impl RegexRule for LayoutRule { }), ); - state + rule_state + .as_ref() .borrow_mut() .downcast_mut::() .map_or_else( - || panic!("Invalid state at: `{}`", STATE_NAME.as_str()), + || panic!("Invalid state at: `{STATE_NAME}`"), |s| s.stack.push((vec![token.clone()], layout_type.clone())), ); } @@ -513,10 +513,10 @@ impl RegexRule for LayoutRule { let (id, token_type, layout_type, properties) = if index == 1 // LAYOUT_NEXT { - let mut state_borrow = state.borrow_mut(); - let state = state_borrow.downcast_mut::().unwrap(); + let mut rule_state_borrow = rule_state.as_ref().borrow_mut(); + let layout_state = rule_state_borrow.downcast_mut::().unwrap(); - let (tokens, layout_type) = match state.stack.last_mut() { + let (tokens, layout_type) = match layout_state.stack.last_mut() { None => { reports.push( Report::build(ReportKind::Error, token.source(), token.start()) @@ -576,10 +576,10 @@ impl RegexRule for LayoutRule { ) } else { // LAYOUT_END - let mut state_borrow = state.borrow_mut(); - let state = state_borrow.downcast_mut::().unwrap(); + let mut rule_state_borrow = rule_state.as_ref().borrow_mut(); + let layout_state = rule_state_borrow.downcast_mut::().unwrap(); - let (tokens, layout_type) = match state.stack.last_mut() { + let (tokens, layout_type) = match layout_state.stack.last_mut() { None => { reports.push( Report::build(ReportKind::Error, token.source(), token.start()) @@ -632,11 +632,11 @@ impl RegexRule for LayoutRule { let layout_type = layout_type.clone(); let id = tokens.len(); - state.stack.pop(); + layout_state.stack.pop(); (id, LayoutToken::End, layout_type, properties) }; - state.parser.push( + state.push( document, Box::new(Layout { location: token, @@ -676,11 +676,12 @@ impl RegexRule for LayoutRule { CTX.with_borrow(|ctx| { ctx.as_ref().map(|ctx| { - // Make sure the state has been initialized - let state = LayoutRule::initialize_state(ctx.parser); + // Make sure the rule state has been initialized + let rule_state = LayoutRule::initialize_state(ctx.state); // Get layout - let layout_type = match ctx.parser.get_layout(layout.as_str()) + // + let layout_type = match ctx.state.shared.layouts.borrow().get(layout.as_str()) { None => { result = Err(BadArgument { @@ -712,7 +713,7 @@ impl RegexRule for LayoutRule { let id = match layout_token { LayoutToken::Begin => { - ctx.parser.push( + ctx.state.push( ctx.document, Box::new(Layout { location: ctx.location.clone(), @@ -723,20 +724,21 @@ impl RegexRule for LayoutRule { }), ); - state + rule_state + .as_ref() .borrow_mut() .downcast_mut::() .map_or_else( - || panic!("Invalid state at: `{}`", STATE_NAME.as_str()), + || panic!("Invalid state at: `{STATE_NAME}`"), |s| s.stack.push((vec![ctx.location.clone()], layout_type.clone())), ); return; }, LayoutToken::Next => { - let mut state_borrow = state.borrow_mut(); - let state = state_borrow.downcast_mut::().unwrap(); + let mut state_borrow = rule_state.as_ref().borrow_mut(); + let layout_state = state_borrow.downcast_mut::().unwrap(); - let (tokens, current_layout_type) = match state.stack.last_mut() { + let (tokens, current_layout_type) = match layout_state.stack.last_mut() { None => { result = Err(BadArgument { to: Some("push".to_string()), @@ -781,10 +783,10 @@ impl RegexRule for LayoutRule { tokens.len() - 1 }, LayoutToken::End => { - let mut state_borrow = state.borrow_mut(); - let state = state_borrow.downcast_mut::().unwrap(); + let mut state_borrow = rule_state.as_ref().borrow_mut(); + let layout_state = state_borrow.downcast_mut::().unwrap(); - let (tokens, current_layout_type) = match state.stack.last_mut() { + let (tokens, current_layout_type) = match layout_state.stack.last_mut() { None => { result = Err(BadArgument { to: Some("push".to_string()), @@ -826,12 +828,12 @@ impl RegexRule for LayoutRule { } let id = tokens.len(); - state.stack.pop(); + layout_state.stack.pop(); id } }; - ctx.state.parser.push( + ctx.state.push( ctx.document, Box::new(Layout { location: ctx.location.clone(), @@ -854,7 +856,7 @@ impl RegexRule for LayoutRule { } fn register_layouts(&self, holder: &mut LayoutHolder) { - holder.insert(Rc::new(default_layouts::Centered::default())); + holder.insert(Rc::new(default_layouts::Centered::default())); holder.insert(Rc::new(default_layouts::Split::default())); } } @@ -864,6 +866,7 @@ mod tests { use crate::elements::paragraph::Paragraph; use crate::elements::text::Text; use crate::parser::langparser::LangParser; + use crate::parser::parser::Parser; use crate::parser::source::SourceFile; use crate::validate_document; diff --git a/src/elements/link.rs b/src/elements/link.rs index 98d37da..e56a6db 100644 --- a/src/elements/link.rs +++ b/src/elements/link.rs @@ -5,7 +5,6 @@ use crate::document::element::ContainerElement; use crate::document::element::ElemKind; use crate::document::element::Element; use crate::lua::kernel::CTX; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::rule::RegexRule; use crate::parser::source::Source; @@ -92,7 +91,7 @@ impl RegexRule for LinkRule { fn on_regex_match<'a>( &self, _: usize, - state: &mut ParserState, + state: &ParserState, document: &'a (dyn Document<'a> + 'a), token: Token, matches: Captures, @@ -197,7 +196,7 @@ impl RegexRule for LinkRule { _ => panic!("Empty link url"), }; - state.parser.push( + state.push( document, Box::new(Link { location: token, @@ -224,7 +223,7 @@ impl RegexRule for LinkRule { display, )); let display_content = - match util::parse_paragraph(ctx.parser, source, ctx.document) { + match util::parse_paragraph(ctx.state, source, ctx.document) { Err(err) => { result = Err(BadArgument { to: Some("push".to_string()), @@ -241,7 +240,7 @@ impl RegexRule for LinkRule { } }; - ctx.parser.push( + ctx.state.push( ctx.document, Box::new(Link { location: ctx.location.clone(), @@ -267,6 +266,7 @@ mod tests { use crate::elements::style::Style; use crate::elements::text::Text; use crate::parser::langparser::LangParser; + use crate::parser::parser::Parser; use crate::parser::source::SourceFile; use crate::validate_document; @@ -284,7 +284,7 @@ Some [link](url). None, )); let parser = LangParser::default(); - let doc = parser.parse(source, None); + let doc = parser.parse(ParserState::new(&parser, None), source, None); validate_document!(doc.content().borrow(), 0, Paragraph { @@ -314,7 +314,7 @@ nml.link.push("**BOLD link**", "another url") None, )); let parser = LangParser::default(); - let doc = parser.parse(source, None); + let doc = parser.parse(ParserState::new(&parser, None), source, None); validate_document!(doc.content().borrow(), 0, Paragraph { diff --git a/src/elements/list.rs b/src/elements/list.rs index e50efcd..cfd8623 100644 --- a/src/elements/list.rs +++ b/src/elements/list.rs @@ -150,7 +150,7 @@ impl ListRule { // Close for i in start_pos..current.len() { - state.parser.push( + state.push( document, Box::new(ListMarker { location: token.clone(), @@ -162,7 +162,7 @@ impl ListRule { // Open for i in start_pos..target.len() { - state.parser.push( + state.push( document, Box::new(ListMarker { location: token.clone(), @@ -260,7 +260,7 @@ impl Rule for ListRule { fn on_match<'a>( &self, - state: &mut ParserState, + state: &ParserState, document: &'a dyn Document<'a>, cursor: Cursor, _match_data: Box, @@ -403,7 +403,7 @@ impl Rule for ListRule { ListRule::push_markers(&token, state, document, &vec![], &depth); } - state.parser.push( + state.push( document, Box::new(ListEntry { location: Token::new( diff --git a/src/elements/media.rs b/src/elements/media.rs index 312f5d4..2f2dd56 100644 --- a/src/elements/media.rs +++ b/src/elements/media.rs @@ -7,8 +7,6 @@ use ariadne::Fmt; use ariadne::Label; use ariadne::Report; use ariadne::ReportKind; -use mlua::Function; -use mlua::Lua; use regex::Captures; use regex::Match; use regex::Regex; @@ -23,7 +21,6 @@ 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::Parser; use crate::parser::parser::ParserState; use crate::parser::parser::ReportColors; use crate::parser::rule::RegexRule; @@ -255,7 +252,7 @@ impl MediaRule { .multi_line(true) .build() .unwrap()], - properties: PropertyParser{ properties: props }, + properties: PropertyParser { properties: props }, } } @@ -334,7 +331,7 @@ impl RegexRule for MediaRule { fn on_regex_match<'a>( &self, _: usize, - state: &mut ParserState, + state: &ParserState, document: &'a (dyn Document<'a> + 'a), token: Token, matches: Captures, @@ -378,7 +375,8 @@ impl RegexRule for MediaRule { }; // Properties - let properties = match self.parse_properties(state.parser.colors(), &token, &matches.get(3)) { + let properties = match self.parse_properties(state.parser.colors(), &token, &matches.get(3)) + { Ok(pm) => pm, Err(report) => { reports.push(report); @@ -481,7 +479,7 @@ impl RegexRule for MediaRule { let mut group = match document.last_element_mut::() { Some(group) => group, None => { - state.parser.push( + state.push( document, Box::new(Media { location: token.clone(), @@ -521,6 +519,7 @@ impl RegexRule for MediaRule { #[cfg(test)] mod tests { use crate::parser::langparser::LangParser; + use crate::parser::parser::Parser; use crate::parser::source::SourceFile; use super::*; diff --git a/src/elements/paragraph.rs b/src/elements/paragraph.rs index 3e0e021..e480b2b 100644 --- a/src/elements/paragraph.rs +++ b/src/elements/paragraph.rs @@ -11,7 +11,6 @@ use crate::document::document::Document; use crate::document::element::ContainerElement; use crate::document::element::ElemKind; use crate::document::element::Element; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::rule::Rule; use crate::parser::source::Cursor; @@ -115,17 +114,17 @@ impl Rule for ParagraphRule { fn on_match( &self, - state: &mut ParserState, + state: &ParserState, document: &dyn Document, cursor: Cursor, - _match_data: Option>, + _match_data: Box, ) -> (Cursor, Vec, Range)>>) { let end_cursor = match self.re.captures_at(cursor.source.content(), cursor.pos) { None => panic!("Unknown error"), Some(capture) => cursor.at(capture.get(0).unwrap().end() - 1), }; - state.parser.push( + state.push( document, Box::new(Paragraph { location: Token::new(cursor.pos..end_cursor.pos, cursor.source.clone()), @@ -142,6 +141,7 @@ mod tests { use crate::elements::paragraph::Paragraph; use crate::elements::text::Text; use crate::parser::langparser::LangParser; + use crate::parser::parser::Parser; use crate::parser::source::SourceFile; use crate::validate_document; diff --git a/src/elements/raw.rs b/src/elements/raw.rs index 1c68ceb..1328b1f 100644 --- a/src/elements/raw.rs +++ b/src/elements/raw.rs @@ -3,7 +3,6 @@ use crate::document::document::Document; use crate::document::element::ElemKind; use crate::document::element::Element; use crate::lua::kernel::CTX; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::rule::RegexRule; use crate::parser::source::Source; @@ -79,7 +78,7 @@ impl RegexRule for RawRule { fn on_regex_match( &self, _index: usize, - state: &mut ParserState, + state: &ParserState, document: &dyn Document, token: Token, matches: Captures, @@ -208,7 +207,7 @@ impl RegexRule for RawRule { }, }; - state.parser.push( + state.push( document, Box::new(Raw { location: token.clone(), @@ -243,7 +242,7 @@ impl RegexRule for RawRule { CTX.with_borrow(|ctx| { ctx.as_ref().map(|ctx| { - ctx.state.parser.push( + ctx.state.push( ctx.document, Box::new(Raw { location: ctx.location.clone(), @@ -269,7 +268,8 @@ mod tests { use crate::elements::paragraph::Paragraph; use crate::elements::text::Text; use crate::parser::langparser::LangParser; - use crate::parser::source::SourceFile; + use crate::parser::parser::Parser; +use crate::parser::source::SourceFile; use crate::validate_document; #[test] diff --git a/src/elements/reference.rs b/src/elements/reference.rs index 41268e6..cd09186 100644 --- a/src/elements/reference.rs +++ b/src/elements/reference.rs @@ -6,8 +6,6 @@ use ariadne::Fmt; use ariadne::Label; use ariadne::Report; use ariadne::ReportKind; -use mlua::Function; -use mlua::Lua; use regex::Captures; use regex::Match; use regex::Regex; @@ -18,7 +16,6 @@ use crate::document::document::Document; use crate::document::element::ElemKind; use crate::document::element::Element; use crate::document::references::validate_refname; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::parser::ReportColors; use crate::parser::rule::RegexRule; @@ -83,7 +80,7 @@ impl ReferenceRule { ); Self { re: [Regex::new(r"§\{(.*?)\}(\[((?:\\.|[^\\\\])*?)\])?").unwrap()], - properties: PropertyParser{ properties: props }, + properties: PropertyParser { properties: props }, } } @@ -136,7 +133,7 @@ impl RegexRule for ReferenceRule { fn on_regex_match<'a>( &self, _: usize, - state: &mut ParserState, + state: &ParserState, document: &'a (dyn Document<'a> + 'a), token: Token, matches: Captures, @@ -179,7 +176,8 @@ impl RegexRule for ReferenceRule { } }; // Properties - let properties = match self.parse_properties(state.parser.colors(), &token, &matches.get(3)) { + let properties = match self.parse_properties(state.parser.colors(), &token, &matches.get(3)) + { Ok(pm) => pm, Err(report) => { reports.push(report); @@ -194,7 +192,7 @@ impl RegexRule for ReferenceRule { .ok() .and_then(|(_, s)| Some(s)); - state.parser.push( + state.push( document, Box::new(Reference { location: token, diff --git a/src/elements/script.rs b/src/elements/script.rs index 738718a..1eab65d 100644 --- a/src/elements/script.rs +++ b/src/elements/script.rs @@ -1,7 +1,6 @@ use crate::document::document::Document; use crate::lua::kernel::Kernel; use crate::lua::kernel::KernelContext; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::parser::ReportColors; use crate::parser::rule::RegexRule; @@ -13,7 +12,6 @@ use ariadne::Fmt; use ariadne::Label; use ariadne::Report; use ariadne::ReportKind; -use mlua::Function; use mlua::Lua; use regex::Captures; use regex::Regex; @@ -85,7 +83,7 @@ impl RegexRule for ScriptRule { fn on_regex_match<'a>( &self, index: usize, - state: &mut ParserState, + state: &ParserState, document: &'a dyn Document<'a>, token: Token, matches: Captures, @@ -94,29 +92,33 @@ impl RegexRule for ScriptRule { let kernel_name = match matches.get(1) { None => "main".to_string(), - Some(name) => match ScriptRule::validate_kernel_name(state.parser.colors(), name.as_str()) { - Ok(name) => name, - Err(e) => { - reports.push( - Report::build(ReportKind::Error, token.source(), name.start()) - .with_message("Invalid kernel name") - .with_label( - Label::new((token.source(), name.range())) - .with_message(e) - .with_color(state.parser.colors().error), - ) - .finish(), - ); - return reports; + Some(name) => { + match ScriptRule::validate_kernel_name(state.parser.colors(), name.as_str()) { + Ok(name) => name, + Err(e) => { + reports.push( + Report::build(ReportKind::Error, token.source(), name.start()) + .with_message("Invalid kernel name") + .with_label( + Label::new((token.source(), name.range())) + .with_message(e) + .with_color(state.parser.colors().error), + ) + .finish(), + ); + return reports; + } } - }, + } + }; + let mut kernels_borrow = state.shared.kernels.borrow_mut(); + let kernel = match kernels_borrow.get(kernel_name.as_str()) { + Some(kernel) => kernel, + None => { + kernels_borrow.insert(kernel_name.clone(), Kernel::new(state.parser)); + kernels_borrow.get(kernel_name.as_str()).unwrap() + } }; - let kernel = state.shared.kernels - .get(kernel_name.as_str()) - .unwrap_or_else(|| { - state.shared.kernels.insert(kernel_name.to_string(), Kernel::new(state)); - state.shared.kernels.get(kernel_name.as_str()).unwrap() - }); let kernel_data = matches .get(if index == 0 { 2 } else { 3 }) @@ -227,7 +229,7 @@ impl RegexRule for ScriptRule { // Eval to text { if !result.is_empty() { - state.parser.push( + state.push( document, Box::new(Text::new( Token::new(1..source.content().len(), source.clone()), @@ -245,7 +247,9 @@ 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); }) } } @@ -273,7 +277,7 @@ impl RegexRule for ScriptRule { let ctx = KernelContext { location: Token::new(0..source.content().len(), source.clone()), - parser_state: state, + state, document, }; @@ -290,6 +294,7 @@ mod tests { use crate::elements::paragraph::Paragraph; use crate::elements::style::Style; use crate::parser::langparser::LangParser; + use crate::parser::parser::Parser; use crate::parser::source::SourceFile; use crate::validate_document; @@ -315,7 +320,7 @@ Evaluation: %% None, )); let parser = LangParser::default(); - let doc = parser.parse(source, None); + let doc = parser.parse(ParserState::new(&parser, None), source, None); validate_document!(doc.content().borrow(), 0, Paragraph; diff --git a/src/elements/section.rs b/src/elements/section.rs index 02175c8..8a24961 100644 --- a/src/elements/section.rs +++ b/src/elements/section.rs @@ -5,7 +5,6 @@ use crate::document::element::ElemKind; use crate::document::element::Element; use crate::document::element::ReferenceableElement; use crate::lua::kernel::CTX; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::rule::RegexRule; use crate::parser::source::Source; @@ -162,7 +161,7 @@ impl RegexRule for SectionRule { fn on_regex_match( &self, _: usize, - state: &mut ParserState, + state: &ParserState, document: &dyn Document, token: Token, matches: regex::Captures, @@ -294,12 +293,15 @@ impl RegexRule for SectionRule { }; // Get style - let style = state.shared.styles - .current_style(section_style::STYLE_KEY) + let style = state + .shared + .styles + .borrow() + .current(section_style::STYLE_KEY) .downcast_rc::() .unwrap(); - state.parser.push( + state.push( document, Box::new(Section { location: token.clone(), @@ -342,12 +344,15 @@ impl RegexRule for SectionRule { ctx.as_ref().map(|ctx| { // Get style let style = ctx - .parser - .current_style(section_style::STYLE_KEY) + .state + .shared + .styles + .borrow() + .current(section_style::STYLE_KEY) .downcast_rc::() .unwrap(); - ctx.parser.push( + ctx.state.push( ctx.document, Box::new(Section { location: ctx.location.clone(), @@ -371,7 +376,7 @@ impl RegexRule for SectionRule { } fn register_styles(&self, holder: &mut StyleHolder) { - holder.set_current_style(Rc::new(SectionStyle::default())); + holder.set_current(Rc::new(SectionStyle::default())); } } @@ -411,6 +416,7 @@ mod section_style { #[cfg(test)] mod tests { use crate::parser::langparser::LangParser; + use crate::parser::parser::Parser; use crate::parser::source::SourceFile; use crate::validate_document; @@ -491,6 +497,8 @@ nml.section.push("6", 6, "", "refname") let state = ParserState::new(&parser, None); let _ = parser.parse(state, source, None); + // TODO2 + /* let style = state.shared .styles .current_style(section_style::STYLE_KEY) @@ -499,5 +507,6 @@ nml.section.push("6", 6, "", "refname") assert_eq!(style.link_pos, SectionLinkPos::None); assert_eq!(style.link, ["a".to_string(), "b".to_string(), "c".to_string()]); + */ } } diff --git a/src/elements/style.rs b/src/elements/style.rs index 01c215a..0291fa2 100644 --- a/src/elements/style.rs +++ b/src/elements/style.rs @@ -4,7 +4,6 @@ use crate::document::document::Document; use crate::document::document::DocumentAccessors; use crate::document::element::ElemKind; use crate::document::element::Element; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::rule::RegexRule; use crate::parser::source::Source; @@ -80,7 +79,7 @@ impl RuleState for StyleState { fn on_remove<'a>( &self, - state: &mut ParserState, + state: &ParserState, document: &dyn Document, ) -> Vec, Range)>> { let mut reports = vec![]; @@ -154,7 +153,7 @@ impl StyleRule { } } -static STATE_NAME : &'static str = "elements.style"; +static STATE_NAME: &'static str = "elements.style"; impl RegexRule for StyleRule { fn name(&self) -> &'static str { "Style" } @@ -164,17 +163,20 @@ impl RegexRule for StyleRule { fn on_regex_match( &self, index: usize, - state: &mut ParserState, + state: &ParserState, document: &dyn Document, token: Token, _matches: Captures, ) -> Vec, Range)>> { - let query = state.shared.rule_state.get(&STATE_NAME); - let state = match query { + let query = state.shared.rule_state.borrow().get(STATE_NAME); + let style_state = match query { Some(state) => state, None => { // Insert as a new state - match state.shared.rule_state + match state + .shared + .rule_state + .borrow_mut() .insert(STATE_NAME.into(), Rc::new(RefCell::new(StyleState::new()))) { Err(_) => panic!("Unknown error"), @@ -183,11 +185,11 @@ impl RegexRule for StyleRule { } }; - if let Some(style_state) = state.borrow_mut().downcast_mut::() { + if let Some(style_state) = style_state.borrow_mut().downcast_mut::() { style_state.toggled[index] = style_state.toggled[index] .clone() .map_or(Some(token.clone()), |_| None); - state.parser.push( + state.push( document, Box::new(Style::new( token.clone(), @@ -196,7 +198,7 @@ impl RegexRule for StyleRule { )), ); } else { - panic!("Invalid state at `{}`", STATE_NAME.as_str()); + panic!("Invalid state at `{STATE_NAME}`"); } return vec![]; @@ -207,6 +209,7 @@ impl RegexRule for StyleRule { mod tests { use crate::elements::text::Text; use crate::parser::langparser::LangParser; + use crate::parser::parser::Parser; use crate::parser::source::SourceFile; use crate::validate_document; @@ -227,7 +230,7 @@ __`UNDERLINE+EM`__ None, )); let parser = LangParser::default(); - let doc = parser.parse(source, None); + let doc = parser.parse(ParserState::new(&parser, None), source, None); validate_document!(doc.content().borrow(), 0, Paragraph { diff --git a/src/elements/tex.rs b/src/elements/tex.rs index 081e2eb..117a654 100644 --- a/src/elements/tex.rs +++ b/src/elements/tex.rs @@ -14,8 +14,6 @@ use ariadne::Report; use ariadne::ReportKind; use crypto::digest::Digest; use crypto::sha2::Sha512; -use mlua::Function; -use mlua::Lua; use regex::Captures; use regex::Match; use regex::Regex; @@ -27,7 +25,6 @@ use crate::compiler::compiler::Target; use crate::document::document::Document; use crate::document::element::ElemKind; use crate::document::element::Element; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::parser::ReportColors; use crate::parser::rule::RegexRule; @@ -305,7 +302,7 @@ impl RegexRule for TexRule { fn on_regex_match( &self, index: usize, - state: &mut ParserState, + state: &ParserState, document: &dyn Document, token: Token, matches: Captures, @@ -355,7 +352,8 @@ impl RegexRule for TexRule { }; // Properties - let properties = match self.parse_properties(state.parser.colors(), &token, &matches.get(1)) { + let properties = match self.parse_properties(state.parser.colors(), &token, &matches.get(1)) + { Ok(pm) => pm, Err(report) => { reports.push(report); @@ -413,7 +411,7 @@ impl RegexRule for TexRule { .and_then(|(_, value)| Some(value)) .unwrap(); - state.parser.push( + state.push( document, Box::new(Tex { mathmode: index == 1, @@ -433,6 +431,7 @@ impl RegexRule for TexRule { mod tests { use crate::elements::paragraph::Paragraph; use crate::parser::langparser::LangParser; + use crate::parser::parser::Parser; use crate::parser::source::SourceFile; use crate::validate_document; @@ -451,7 +450,7 @@ $[kind=block,env=another] e^{i\pi}=-1$ None, )); let parser = LangParser::default(); - let doc = parser.parse(source, None); + let doc = parser.parse(ParserState::new(&parser, None), source, None); validate_document!(doc.content().borrow(), 0, Tex { mathmode == true, tex == "1+1=2", env == "main", caption == Some("Some, text\\".to_string()) }; @@ -473,7 +472,7 @@ $[env=another] e^{i\pi}=-1$ None, )); let parser = LangParser::default(); - let doc = parser.parse(source, None); + let doc = parser.parse(ParserState::new(&parser, None), source, None); validate_document!(doc.content().borrow(), 0, Paragraph { diff --git a/src/elements/text.rs b/src/elements/text.rs index 169bae3..99f32cd 100644 --- a/src/elements/text.rs +++ b/src/elements/text.rs @@ -11,7 +11,6 @@ use crate::document::document::Document; use crate::document::element::ElemKind; use crate::document::element::Element; use crate::lua::kernel::CTX; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::rule::Rule; use crate::parser::source::Cursor; @@ -53,10 +52,10 @@ impl Rule for TextRule { fn on_match( &self, - _state: &mut ParserState, + _state: &ParserState, _document: &dyn Document, _cursor: Cursor, - _match_data: Option>, + _match_data: Box, ) -> (Cursor, Vec, Range)>>) { panic!("Text cannot match"); } @@ -68,7 +67,7 @@ impl Rule for TextRule { lua.create_function(|_, content: String| { CTX.with_borrow(|ctx| { ctx.as_ref().map(|ctx| { - ctx.state.parser.push( + ctx.state.push( ctx.document, Box::new(Text { location: ctx.location.clone(), diff --git a/src/elements/variable.rs b/src/elements/variable.rs index 402f4c8..5768eae 100644 --- a/src/elements/variable.rs +++ b/src/elements/variable.rs @@ -3,7 +3,6 @@ use crate::document::variable::BaseVariable; use crate::document::variable::PathVariable; use crate::document::variable::Variable; use crate::lua::kernel::CTX; -use crate::parser::parser::Parser; use crate::parser::parser::ParserState; use crate::parser::parser::ReportColors; use crate::parser::rule::RegexRule; @@ -124,7 +123,7 @@ impl RegexRule for VariableRule { fn on_regex_match<'a>( &self, _: usize, - state: &mut ParserState, + state: &ParserState, document: &'a dyn Document, token: Token, matches: regex::Captures, @@ -316,7 +315,7 @@ impl RegexRule for VariableSubstitutionRule { fn on_regex_match<'a>( &self, _index: usize, - state: &mut ParserState, + state: &ParserState, document: &'a dyn Document<'a>, token: Token, matches: regex::Captures, @@ -417,7 +416,7 @@ impl RegexRule for VariableSubstitutionRule { _ => panic!("Unknown error"), }; - variable.parse(token, state, document); + variable.parse(state, token, document); return result; } diff --git a/src/lua/kernel.rs b/src/lua/kernel.rs index 3e04505..54ab86a 100644 --- a/src/lua/kernel.rs +++ b/src/lua/kernel.rs @@ -1,11 +1,6 @@ use std::cell::RefCell; -use std::cell::RefMut; use std::collections::HashMap; -use mlua::Error; -use mlua::FromLuaMulti; -use mlua::Function; -use mlua::IntoLuaMulti; use mlua::Lua; use crate::document::document::Document; @@ -17,7 +12,6 @@ pub struct KernelContext<'a, 'b, 'c> { pub location: Token, pub state: &'a ParserState<'a, 'b>, pub document: &'c dyn Document<'c>, - //pub parser: &'a dyn Parser, } thread_local! { @@ -40,7 +34,7 @@ impl Kernel { let table = lua.create_table().unwrap(); // TODO: Export this so we can check for duplicate rules based on this name let name = rule.name().to_lowercase().replace(' ', "_"); - for (fun_name, fun) in rule.lua_bindings(&lua) { + for (fun_name, fun) in rule.register_bindings(&lua) { table.set(fun_name, fun).unwrap(); } nml_table.set(name, table).unwrap(); @@ -73,11 +67,9 @@ pub struct KernelHolder { } impl KernelHolder { - pub fn get(&self, kernel_name: &str) -> Option<&Kernel> { - self.kernels.get(kernel_name) - } + pub fn get(&self, kernel_name: &str) -> Option<&Kernel> { self.kernels.get(kernel_name) } - pub fn insert(&self, kernel_name: String, kernel: Kernel) { - self.kernels.insert(kernel_name, kernel) + pub fn insert(&mut self, kernel_name: String, kernel: Kernel) { + self.kernels.insert(kernel_name, kernel); } } diff --git a/src/main.rs b/src/main.rs index be96d30..14348ba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,13 +47,16 @@ NML version: 0.4\n" ); } -fn parse(parser: &LangParser, input: &str, debug_opts: &Vec) -> Result>, String> { +fn parse( + parser: &LangParser, + input: &str, + debug_opts: &Vec, +) -> Result>, String> { println!("Parsing {input}..."); - let parser = LangParser::default(); // Parse let source = SourceFile::new(input.to_string(), None).unwrap(); - let doc = parser.parse(ParserState::new(&parser, None), Rc::new(source), None); + let doc = parser.parse(ParserState::new(parser, None), Rc::new(source), None); if debug_opts.contains(&"ast".to_string()) { println!("-- BEGIN AST DEBUGGING --"); @@ -218,8 +221,7 @@ fn main() -> ExitCode { } match std::fs::metadata(&output) { Ok(output_meta) => { - if !output_meta.is_dir() - { + if !output_meta.is_dir() { eprintln!("Input is a directory, but ouput is not a directory, halting"); return ExitCode::FAILURE; } diff --git a/src/parser/customstyle.rs b/src/parser/customstyle.rs index e682a0a..8f02225 100644 --- a/src/parser/customstyle.rs +++ b/src/parser/customstyle.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use std::ops::Range; use std::rc::Rc; +use std::ops::Deref; use ariadne::Report; @@ -25,13 +26,13 @@ pub trait CustomStyle: core::fmt::Debug { fn on_start<'a>( &self, location: Token, - state: &mut ParserState, + state: &ParserState, document: &'a (dyn Document<'a> + 'a), ) -> Vec, Range)>>; fn on_end<'a>( &self, location: Token, - state: &mut ParserState, + state: &ParserState, document: &'a (dyn Document<'a> + 'a), ) -> Vec, Range)>>; } @@ -42,13 +43,21 @@ pub struct CustomStyleHolder { } impl CustomStyleHolder { - fn get(&self, style_name: &str) -> Option> { + pub fn get(&self, style_name: &str) -> Option> { self.custom_styles .get(style_name) .map(|style| style.clone()) } - fn insert(&mut self, style: Rc) { + pub fn insert(&mut self, style: Rc) { self.custom_styles.insert(style.name().into(), style); } } + +impl Deref for CustomStyleHolder { + type Target = HashMap>; + + fn deref(&self) -> &Self::Target { + &self.custom_styles + } +} diff --git a/src/parser/langparser.rs b/src/parser/langparser.rs index 0ef993e..b0ea1d2 100644 --- a/src/parser/langparser.rs +++ b/src/parser/langparser.rs @@ -1,23 +1,11 @@ use std::cell::RefCell; -use std::collections::HashSet; -use std::ops::Range; use std::rc::Rc; -use ariadne::Label; -use ariadne::Report; - use crate::document::document::Document; -use crate::document::document::DocumentAccessors; -use crate::document::element::ContainerElement; use crate::document::element::DocumentEnd; -use crate::document::element::ElemKind; -use crate::document::element::Element; use crate::document::langdocument::LangDocument; -use crate::elements::paragraph::Paragraph; use crate::elements::registrar::register; use crate::elements::text::Text; -use crate::parser::source::SourceFile; -use crate::parser::source::VirtualSource; use super::parser::Parser; use super::parser::ParserState; @@ -44,17 +32,11 @@ impl LangParser { rules: vec![], colors: ReportColors::with_colors(), err_flag: RefCell::new(false), - //matches: RefCell::new(Vec::new()), - //state: RefCell::new(StateHolder::new()), - //kernels: RefCell::new(HashMap::new()), - //styles: RefCell::new(HashMap::new()), - //layouts: RefCell::new(HashMap::new()), - //custom_styles: RefCell::new(HashMap::new()), }; - // Register rules - // TODO2: use https://docs.rs/inventory/latest/inventory/ - register(&mut s); + // Register rules + // TODO: use https://docs.rs/inventory/latest/inventory/ + register(&mut s); s } @@ -64,6 +46,7 @@ impl Parser for LangParser { fn colors(&self) -> &ReportColors { &self.colors } fn rules(&self) -> &Vec> { &self.rules } + fn rules_mut(&mut self) -> &mut Vec> { &mut self.rules } fn has_error(&self) -> bool { *self.err_flag.borrow() } @@ -81,11 +64,11 @@ impl Parser for LangParser { if let Some(parent) = parent // Terminate parent's paragraph state { - Parser::handle_reports(&self, - parent.source(), - state.shared.rule_state - .on_scope_end(self, parent, super::state::Scope::PARAGRAPH), - ); + self.handle_reports(state.shared.rule_state.borrow_mut().on_scope_end( + &state, + parent, + super::state::Scope::PARAGRAPH, + )); } loop { @@ -95,7 +78,7 @@ impl Parser for LangParser { let text_content = util::process_text(&doc, &content.as_str()[cursor.pos..rule_pos.pos]); if !text_content.is_empty() { - self.push( + state.push( &doc, Box::new(Text::new( Token::new(cursor.pos..rule_pos.pos, source.clone()), @@ -107,9 +90,10 @@ impl Parser for LangParser { if let Some((rule_index, match_data)) = result.take() { // Rule callback let dd: &'a dyn Document = unsafe { std::mem::transmute(&doc as &dyn Document) }; - let (new_cursor, reports) = self.rules[rule_index].on_match(self, dd, rule_pos, match_data); + let (new_cursor, reports) = + self.rules[rule_index].on_match(&state, dd, rule_pos, match_data); - self.handle_reports(doc.source(), reports); + self.handle_reports(reports); // Advance cursor = new_cursor; @@ -120,14 +104,15 @@ impl Parser for LangParser { } } - // State - self.handle_reports( - doc.source(), - state.shared.rule_state - .on_scope_end(&mut state, &doc, super::state::Scope::DOCUMENT), - ); + // Rule States - self.push( + self.handle_reports(state.shared.rule_state.borrow_mut().on_scope_end( + &state, + &doc, + super::state::Scope::DOCUMENT, + )); + + state.push( &doc, Box::new(DocumentEnd(Token::new( doc.source().content().len()..doc.source().content().len(), @@ -138,7 +123,12 @@ impl Parser for LangParser { return Box::new(doc); } - fn parse_into<'a>(&self, state: mut ParserState, source: Rc, document: &'a dyn Document<'a>) { + fn parse_into<'a>( + &self, + state: ParserState, + source: Rc, + document: &'a dyn Document<'a>, + ) { let content = source.content(); let mut cursor = Cursor::new(0usize, source.clone()); @@ -149,7 +139,7 @@ impl Parser for LangParser { let text_content = util::process_text(document, &content.as_str()[cursor.pos..rule_pos.pos]); if !text_content.is_empty() { - self.push( + state.push( document, Box::new(Text::new( Token::new(cursor.pos..rule_pos.pos, source.clone()), @@ -160,9 +150,10 @@ impl Parser for LangParser { if let Some((rule_index, match_data)) = result.take() { // Rule callback - let (new_cursor, reports) = self.rules[rule_index].on_match(&mut state, document, rule_pos, match_data); + let (new_cursor, reports) = + self.rules[rule_index].on_match(&state, document, rule_pos, match_data); - self.handle_reports(document.source(), reports); + self.handle_reports(reports); // Advance cursor = new_cursor; diff --git a/src/parser/layout.rs b/src/parser/layout.rs index 1965d86..c7ef1a5 100644 --- a/src/parser/layout.rs +++ b/src/parser/layout.rs @@ -1,6 +1,4 @@ use std::any::Any; -use std::cell::Ref; -use std::cell::RefMut; use std::collections::HashMap; use std::ops::Range; use std::rc::Rc; @@ -41,7 +39,7 @@ impl LayoutHolder { self.layouts.get(layout_name).map(|layout| layout.clone()) } - pub fn insert(&self, layout: Rc) { + pub fn insert(&mut self, layout: Rc) { self.layouts.insert(layout.name().into(), layout); } } diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 1173026..7a78823 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -3,6 +3,7 @@ use std::cell::RefCell; use std::collections::HashSet; use std::ops::Range; use std::rc::Rc; +use ariadne::Label; use ariadne::Report; use unicode_segmentation::UnicodeSegmentation; @@ -23,6 +24,7 @@ use crate::elements::paragraph::Paragraph; use crate::lua::kernel::Kernel; use crate::lua::kernel::KernelHolder; use crate::parser::source::SourceFile; +use crate::parser::source::VirtualSource; use ariadne::Color; #[derive(Debug)] @@ -55,39 +57,39 @@ impl ReportColors { /// The state that is shared with the state's children pub struct SharedState { - pub rule_state: RuleStateHolder, + pub rule_state: RefCell, /// The lua [`Kernel`]s - pub kernels: KernelHolder, + pub kernels: RefCell, /// The styles - pub styles: StyleHolder, + pub styles: RefCell, /// The layouts - pub layouts: LayoutHolder, + pub layouts: RefCell, /// The custom styles - pub custom_styles: CustomStyleHolder, + pub custom_styles: RefCell, } impl SharedState { /// Construct a new empty shared state pub(self) fn new(parser: &dyn Parser) -> Self { - let mut s = Self { - rule_state: RuleStateHolder::default(), - kernels: KernelHolder::default(), - styles: StyleHolder::default(), - layouts: LayoutHolder::default(), - custom_styles: CustomStyleHolder::default(), + let s = Self { + rule_state: RefCell::new(RuleStateHolder::default()), + kernels: RefCell::new(KernelHolder::default()), + styles: RefCell::new(StyleHolder::default()), + layouts: RefCell::new(LayoutHolder::default()), + custom_styles: RefCell::new(CustomStyleHolder::default()), }; // Register default kernel - s.kernels + s.kernels.borrow_mut() .insert("main".to_string(), Kernel::new(parser)); parser.rules().iter().for_each(|rule| { - rule.register_styles(&mut s.styles); - rule.register_layouts(&mut s.layouts); + rule.register_styles(&mut *s.styles.borrow_mut()); + rule.register_layouts(&mut *s.layouts.borrow_mut()); }); s @@ -106,9 +108,13 @@ pub struct ParserState<'a, 'b> { matches: RefCell>)>>, /// State shared among all states - pub shared: Rc>, + pub shared: Rc, } +/// Represents the state of the parser +/// +/// This state has some shared data from [`SharedState`] which gets shared +/// with the children of that state, see [`ParserState::with_state`] impl<'a, 'b> ParserState<'a, 'b> { /// Constructs a new state for a given parser with an optional parent /// @@ -121,7 +127,7 @@ impl<'a, 'b> ParserState<'a, 'b> { let shared = if let Some(parent) = &parent { parent.shared.clone() } else { - Rc::new(RefCell::new(SharedState::new(parser))) + Rc::new(SharedState::new(parser)) }; Self { @@ -132,76 +138,9 @@ impl<'a, 'b> ParserState<'a, 'b> { } } - /// Adds a new rule to the current state + /// Runs a procedure with a new state that inherits the [`SharedState`] state from [`self`] /// - /// This method will recursively modify the parent states's matches - /// - /// # Errors - /// - /// Will fail if: - /// * The name for the new rule clashes with an already existing rule - /// * If after is Some(..), not finding the rule to insert after - /// On failure, it is safe to continue using this state, however the added rule won't exists. - /* - pub fn add_rule( - &mut self, - rule: Box, - after: Option<&'static str>, - ) -> Result<(), String> { - // FIXME: This method should not modify the parser - // Instead we should have some sort of list of references to rules - // Also need to add a sorting key for rules, so they can be automatically registered, then sorted - - // TODO2: Should also check for duplicate rules name when creating bindings... - // Error on duplicate rule - if let Some(_) = self - .parser - .rules() - .iter() - .find(|other_rule| other_rule.name() == rule.name()) - { - return Err(format!( - "Attempted to introduce duplicate rule: `{}`", - rule.name() - )); - } - - // Try to insert after - if let Some(after) = after { - let index = - self.parser.rules() - .iter() - .enumerate() - .find(|(_, rule)| rule.name() == after) - .map(|(idx, _)| idx); - - if let Some(index) = index { - self.parser.rules_mut().insert(index, rule); - } else { - return Err(format!("Unable to find rule `{after}` to insert after")); - } - } else { - self.parser.rules_mut().push(rule); - } - - // Carry out the `matches` modification - fn carry(state: &ParserState) { - state.matches.borrow_mut().push((0, None)); - - if let Some(parent) = state.parent { - carry(parent); - } - } - carry(self); - - // TODO2: Carry on bindings, style, layouts registration... into self.shared - Ok(()) - } - */ - - /// Runs a procedure with a new state that inherits it's [`SharedState`] state from self - /// - /// Note: When parsing a new document, create a default state, then the parsing process + /// Note: When parsing a new document, create a new state, then the parsing process /// creates states using this method pub fn with_state(&self, f: F) -> R where @@ -211,63 +150,6 @@ impl<'a, 'b> ParserState<'a, 'b> { f(new_state) } - fn handle_reports( - &self, - source: Rc, - reports: Vec, Range)>>, - ) { - for mut report in reports { - let mut sources: HashSet> = HashSet::new(); - fn recurse_source(sources: &mut HashSet>, source: Rc) { - sources.insert(source.clone()); - match source.location() { - Some(parent) => { - let parent_source = parent.source(); - if sources.get(&parent_source).is_none() { - recurse_source(sources, parent_source); - } - } - None => {} - } - } - - report.labels.iter().for_each(|label| { - recurse_source(&mut sources, label.span.0.clone()); - }); - - let cache = sources - .iter() - .map(|source| (source.clone(), source.content().clone())) - .collect::, String)>>(); - - cache.iter().for_each(|(source, _)| { - if let Some(location) = source.location() { - if let Some(_s) = source.downcast_ref::() { - report.labels.push( - Label::new((location.source(), location.start() + 1..location.end())) - .with_message("In file included from here") - .with_order(-1), - ); - }; - - if let Some(_s) = source.downcast_ref::() { - let start = location.start() - + (location.source().content().as_bytes()[location.start()] - == '\n' as u8) - .then_some(1) - .unwrap_or(0); - report.labels.push( - Label::new((location.source(), start..location.end())) - .with_message("In evaluation of") - .with_order(-1), - ); - }; - } - }); - report.eprint(ariadne::sources(cache)).unwrap() - } - } - /// Updates matches from a given start position e.g [`Cursor`] /// /// # Return @@ -341,12 +223,11 @@ impl<'a, 'b> ParserState<'a, 'b> { } return (cursor.at(next_pos), - Some((winner, matches_borrow[0].1.take().unwrap()))) - + Some((winner, matches_borrow[winner].1.take().unwrap()))) } /// Add an [`Element`] to the [`Document`] - fn push(&mut self, doc: &dyn Document, elem: Box) { + pub fn push(&self, doc: &dyn Document, elem: Box) { if elem.kind() == ElemKind::Inline || elem.kind() == ElemKind::Invisible { let mut paragraph = doc .last_element_mut::() @@ -363,10 +244,9 @@ impl<'a, 'b> ParserState<'a, 'b> { } else { // Process paragraph events if doc.last_element::().is_some_and(|_| true) { - self.handle_reports( - doc.source(), - self.shared.rule_state - .on_scope_end(&mut self, doc, super::state::Scope::PARAGRAPH), + self.parser.handle_reports( + self.shared.rule_state.borrow_mut() + .on_scope_end(&self, doc, super::state::Scope::PARAGRAPH), ); } @@ -388,9 +268,6 @@ pub trait Parser { /// Whether the parser emitted an error during it's parsing process fn has_error(&self) -> bool; - - /// Add an [`Element`] to the [`Document`] - fn push<'a>(&self, doc: &dyn Document, elem: Box); /// Parse [`Source`] into a new [`Document`] /// @@ -453,4 +330,60 @@ pub trait Parser { Ok(()) } + + fn handle_reports( + &self, + reports: Vec, Range)>>, + ) { + for mut report in reports { + let mut sources: HashSet> = HashSet::new(); + fn recurse_source(sources: &mut HashSet>, source: Rc) { + sources.insert(source.clone()); + match source.location() { + Some(parent) => { + let parent_source = parent.source(); + if sources.get(&parent_source).is_none() { + recurse_source(sources, parent_source); + } + } + None => {} + } + } + + report.labels.iter().for_each(|label| { + recurse_source(&mut sources, label.span.0.clone()); + }); + + let cache = sources + .iter() + .map(|source| (source.clone(), source.content().clone())) + .collect::, String)>>(); + + cache.iter().for_each(|(source, _)| { + if let Some(location) = source.location() { + if let Some(_s) = source.downcast_ref::() { + report.labels.push( + Label::new((location.source(), location.start() + 1..location.end())) + .with_message("In file included from here") + .with_order(-1), + ); + }; + + if let Some(_s) = source.downcast_ref::() { + let start = location.start() + + (location.source().content().as_bytes()[location.start()] + == '\n' as u8) + .then_some(1) + .unwrap_or(0); + report.labels.push( + Label::new((location.source(), start..location.end())) + .with_message("In evaluation of") + .with_order(-1), + ); + }; + } + }); + report.eprint(ariadne::sources(cache)).unwrap() + } + } } diff --git a/src/parser/rule.rs b/src/parser/rule.rs index ed8d033..aeca59d 100644 --- a/src/parser/rule.rs +++ b/src/parser/rule.rs @@ -1,5 +1,4 @@ use super::layout::LayoutHolder; -use super::parser::Parser; use super::parser::ParserState; use super::source::Cursor; use super::source::Source; @@ -24,20 +23,20 @@ pub trait Rule: Downcast { /// Callback when rule matches fn on_match<'a>( &self, - state: &mut ParserState, + state: &ParserState, document: &'a (dyn Document<'a> + 'a), cursor: Cursor, match_data: Box, ) -> (Cursor, Vec, Range)>>); /// Registers lua bindings - fn register_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] } + fn register_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] } /// Registers default styles - fn register_styles(&self, holder: &mut StyleHolder) {} + fn register_styles(&self, _holder: &mut StyleHolder) {} /// Registers default layouts - fn register_layouts(&self, holder: &mut LayoutHolder) {} + fn register_layouts(&self, _holder: &mut LayoutHolder) {} } impl_downcast!(Rule); @@ -57,7 +56,7 @@ pub trait RegexRule { fn on_regex_match<'a>( &self, index: usize, - state: &mut ParserState, + state: &ParserState, document: &'a (dyn Document<'a> + 'a), token: Token, matches: regex::Captures, @@ -94,7 +93,7 @@ impl Rule for T { fn on_match<'a>( &self, - state: &mut ParserState, + state: &ParserState, document: &'a (dyn Document<'a> + 'a), cursor: Cursor, match_data: Box, diff --git a/src/parser/state.rs b/src/parser/state.rs index c541882..c7949b1 100644 --- a/src/parser/state.rs +++ b/src/parser/state.rs @@ -1,3 +1,4 @@ +use std::cell::RefCell; use std::collections::HashMap; use std::ops::Range; use std::rc::Rc; @@ -31,7 +32,7 @@ pub trait RuleState: Downcast { /// Callback called when state goes out of scope fn on_remove<'a>( &self, - state: &mut ParserState, + state: &ParserState, document: &dyn Document, ) -> Vec, Range)>>; } @@ -46,35 +47,38 @@ impl core::fmt::Debug for dyn RuleState { /// Object owning all the states #[derive(Default)] pub struct RuleStateHolder { - states: HashMap>, + states: HashMap>>, } impl RuleStateHolder { - // Attempts to push [`state`]. On collision, returns an error with the already present state pub fn insert( &mut self, name: String, - state: Rc, - ) { + state: Rc>, + ) -> Result>, String> { + if self.states.contains_key(name.as_str()) { + return Err(format!("Attempted to insert duplicate RuleState: {name}")); + } self.states.insert(name, state.clone()); + Ok(state) } - pub fn get(&self, state_name: &str) -> Option> { - self.states.get(state_name) - .map(|state| state.clone()) + pub fn get(&self, state_name: &str) -> Option>> { + self.states.get(state_name).map(|state| state.clone()) } pub fn on_scope_end( &mut self, - state: &mut ParserState, + state: &ParserState, document: &dyn Document, scope: Scope, ) -> Vec, Range)>> { let mut reports = vec![]; self.states.retain(|_name, rule_state| { - if rule_state.scope() >= scope { + if rule_state.borrow().scope() >= scope { rule_state + .borrow_mut() .on_remove(state, document) .drain(..) .for_each(|report| reports.push(report)); diff --git a/src/parser/style.rs b/src/parser/style.rs index 2a1053e..4a66951 100644 --- a/src/parser/style.rs +++ b/src/parser/style.rs @@ -32,17 +32,17 @@ pub struct StyleHolder { impl StyleHolder { /// Checks if a given style key is registered - fn is_registered(&self, style_key: &str) -> bool { self.styles.contains_key(style_key) } + pub fn is_registered(&self, style_key: &str) -> bool { self.styles.contains_key(style_key) } /// Gets the current active style for an element /// NOTE: Will panic if a style is not defined for a given element /// If you need to process user input, use [`is_registered`] - fn current(&self, style_key: &str) -> Rc { + pub fn current(&self, style_key: &str) -> Rc { self.styles.get(style_key).map(|rc| rc.clone()).unwrap() } /// Sets the [`style`] - fn set_current(&mut self, style: Rc) { + pub fn set_current(&mut self, style: Rc) { self.styles.insert(style.key().to_string(), style); } } diff --git a/src/parser/util.rs b/src/parser/util.rs index 8a875f8..f8d9668 100644 --- a/src/parser/util.rs +++ b/src/parser/util.rs @@ -141,7 +141,9 @@ pub fn parse_paragraph<'a>( document: &'a dyn Document<'a>, ) -> Result, &'static str> { let parsed = state.with_state(|new_state| -> Box { - new_state.parser.parse(new_state, source.clone(), Some(document)) + new_state + .parser + .parse(new_state, source.clone(), Some(document)) }); if parsed.content().borrow().len() > 1 { return Err("Parsed document contains more than a single paragraph");