Refactor done
This commit is contained in:
parent
84e4c17fda
commit
ce9effd465
32 changed files with 459 additions and 508 deletions
|
@ -1,23 +1,24 @@
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::parser::source::Source;
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct LangDocument<'a> {
|
pub struct LangDocument<'a> {
|
||||||
source: Rc<dyn Source>,
|
source: Rc<dyn Source>,
|
||||||
parent: Option<&'a dyn Document<'a>>, /// Document's parent
|
parent: Option<&'a dyn Document<'a>>,
|
||||||
|
/// Document's parent
|
||||||
// FIXME: Render these fields private
|
// FIXME: Render these fields private
|
||||||
pub content: RefCell<Vec<Box<dyn Element>>>,
|
pub content: RefCell<Vec<Box<dyn Element>>>,
|
||||||
pub scope: RefCell<Scope>,
|
pub scope: RefCell<Scope>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LangDocument<'a>
|
impl<'a> LangDocument<'a> {
|
||||||
{
|
pub fn new(source: Rc<dyn Source>, parent: Option<&'a dyn Document<'a>>) -> Self {
|
||||||
pub fn new(source: Rc<dyn Source>, parent: Option<&'a dyn Document<'a>>) -> Self
|
|
||||||
{
|
|
||||||
Self {
|
Self {
|
||||||
source: source,
|
source: source,
|
||||||
parent: parent,
|
parent: parent,
|
||||||
|
@ -30,7 +31,9 @@ impl<'a> LangDocument<'a>
|
||||||
impl<'a> Document<'a> for LangDocument<'a> {
|
impl<'a> Document<'a> for LangDocument<'a> {
|
||||||
fn source(&self) -> Rc<dyn Source> { self.source.clone() }
|
fn source(&self) -> Rc<dyn Source> { 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<Vec<Box<dyn Element>>> { &self.content }
|
fn content(&self) -> &RefCell<Vec<Box<dyn Element>>> { &self.content }
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ pub mod tests {
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
use crate::parser::parser::Parser;
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
|
use crate::ParserState;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn validate_refname_tests() {
|
fn validate_refname_tests() {
|
||||||
|
@ -54,7 +55,7 @@ pub mod tests {
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
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!(validate_refname(&*doc, " abc ", true), Ok("abc"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use super::document::Document;
|
use super::document::Document;
|
||||||
use crate::elements::text::Text;
|
use crate::elements::text::Text;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
use crate::parser::source::Token;
|
use crate::parser::source::Token;
|
||||||
|
@ -19,7 +18,7 @@ pub trait Variable {
|
||||||
/// Converts variable to a string
|
/// Converts variable to a string
|
||||||
fn to_string(&self) -> 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 {
|
impl core::fmt::Debug for dyn Variable {
|
||||||
|
@ -57,7 +56,7 @@ impl Variable for BaseVariable {
|
||||||
|
|
||||||
fn to_string(&self) -> String { self.value.clone() }
|
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(
|
let source = Rc::new(VirtualSource::new(
|
||||||
self.location().clone(),
|
self.location().clone(),
|
||||||
self.name().to_string(),
|
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 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(
|
let source = Rc::new(VirtualSource::new(
|
||||||
location,
|
location,
|
||||||
self.name().to_string(),
|
self.name().to_string(),
|
||||||
self.to_string(),
|
self.to_string(),
|
||||||
));
|
));
|
||||||
|
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Text::new(
|
Box::new(Text::new(
|
||||||
Token::new(0..source.content().len(), source),
|
Token::new(0..source.content().len(), source),
|
||||||
|
|
|
@ -25,7 +25,6 @@ use crate::document::document::Document;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
|
@ -337,7 +336,7 @@ impl RegexRule for CodeRule {
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
index: usize,
|
index: usize,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a dyn Document,
|
document: &'a dyn Document,
|
||||||
token: Token,
|
token: Token,
|
||||||
matches: Captures,
|
matches: Captures,
|
||||||
|
@ -505,7 +504,7 @@ impl RegexRule for CodeRule {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Code::new(
|
Box::new(Code::new(
|
||||||
token.clone(),
|
token.clone(),
|
||||||
|
@ -526,7 +525,7 @@ impl RegexRule for CodeRule {
|
||||||
CodeKind::Inline
|
CodeKind::Inline
|
||||||
};
|
};
|
||||||
|
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Code::new(
|
Box::new(Code::new(
|
||||||
token.clone(),
|
token.clone(),
|
||||||
|
@ -555,7 +554,7 @@ impl RegexRule for CodeRule {
|
||||||
.get_variable("code.theme")
|
.get_variable("code.theme")
|
||||||
.and_then(|var| Some(var.to_string()));
|
.and_then(|var| Some(var.to_string()));
|
||||||
|
|
||||||
ctx.parser.push(
|
ctx.state.push(
|
||||||
ctx.document,
|
ctx.document,
|
||||||
Box::new(Code {
|
Box::new(Code {
|
||||||
location: ctx.location.clone(),
|
location: ctx.location.clone(),
|
||||||
|
@ -586,7 +585,7 @@ impl RegexRule for CodeRule {
|
||||||
.get_variable("code.theme")
|
.get_variable("code.theme")
|
||||||
.and_then(|var| Some(var.to_string()));
|
.and_then(|var| Some(var.to_string()));
|
||||||
|
|
||||||
ctx.parser.push(
|
ctx.state.push(
|
||||||
ctx.document,
|
ctx.document,
|
||||||
Box::new(Code {
|
Box::new(Code {
|
||||||
location: ctx.location.clone(),
|
location: ctx.location.clone(),
|
||||||
|
@ -624,7 +623,7 @@ impl RegexRule for CodeRule {
|
||||||
.get_variable("code.theme")
|
.get_variable("code.theme")
|
||||||
.and_then(|var| Some(var.to_string()));
|
.and_then(|var| Some(var.to_string()));
|
||||||
|
|
||||||
ctx.parser.push(
|
ctx.state.push(
|
||||||
ctx.document,
|
ctx.document,
|
||||||
Box::new(Code {
|
Box::new(Code {
|
||||||
location: ctx.location.clone(),
|
location: ctx.location.clone(),
|
||||||
|
@ -653,6 +652,7 @@ impl RegexRule for CodeRule {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -726,8 +726,7 @@ fn fact(n: usize) -> usize
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
let parser = LangParser::default();
|
||||||
//let compiler = Compiler::new(Target::HTML, None);
|
let doc = parser.parse(ParserState::new(&parser, None), source, None);
|
||||||
let doc = parser.parse(source, None);
|
|
||||||
|
|
||||||
let borrow = doc.content().borrow();
|
let borrow = doc.content().borrow();
|
||||||
let found = borrow
|
let found = borrow
|
||||||
|
|
|
@ -2,7 +2,6 @@ use crate::compiler::compiler::Compiler;
|
||||||
use crate::document::document::Document;
|
use crate::document::document::Document;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
|
@ -59,7 +58,7 @@ impl RegexRule for CommentRule {
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a dyn Document,
|
document: &'a dyn Document,
|
||||||
token: Token,
|
token: Token,
|
||||||
matches: Captures,
|
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;
|
return reports;
|
||||||
}
|
}
|
||||||
|
@ -99,6 +104,7 @@ mod tests {
|
||||||
use crate::elements::style::Style;
|
use crate::elements::style::Style;
|
||||||
use crate::elements::text::Text;
|
use crate::elements::text::Text;
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
use crate::validate_document;
|
use crate::validate_document;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
use crate::lua::kernel::Kernel;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
use std::cell::Ref;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
@ -19,7 +21,6 @@ use crate::lua::kernel::KernelContext;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
use crate::parser::customstyle::CustomStyle;
|
use crate::parser::customstyle::CustomStyle;
|
||||||
use crate::parser::customstyle::CustomStyleToken;
|
use crate::parser::customstyle::CustomStyleToken;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::Rule;
|
use crate::parser::rule::Rule;
|
||||||
use crate::parser::source::Cursor;
|
use crate::parser::source::Cursor;
|
||||||
|
@ -28,8 +29,6 @@ use crate::parser::source::Token;
|
||||||
use crate::parser::state::RuleState;
|
use crate::parser::state::RuleState;
|
||||||
use crate::parser::state::Scope;
|
use crate::parser::state::Scope;
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
|
||||||
|
|
||||||
use super::paragraph::Paragraph;
|
use super::paragraph::Paragraph;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -48,75 +47,78 @@ impl CustomStyle for LuaCustomStyle {
|
||||||
fn on_start<'a>(
|
fn on_start<'a>(
|
||||||
&self,
|
&self,
|
||||||
location: Token,
|
location: Token,
|
||||||
parser_state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a dyn Document<'a>,
|
document: &'a dyn Document<'a>,
|
||||||
) -> Vec<Report<(Rc<dyn Source>, Range<usize>)>> {
|
) -> Vec<Report<(Rc<dyn Source>, Range<usize>)>> {
|
||||||
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 {
|
let ctx = KernelContext {
|
||||||
location: location.clone(),
|
location: location.clone(),
|
||||||
parser_state,
|
state,
|
||||||
document,
|
document,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = Ok(());
|
let mut reports = vec![];
|
||||||
kernel.run_with_context(ctx, |lua| {
|
kernel.run_with_context(ctx, |lua| {
|
||||||
let chunk = lua.load(self.start.as_str());
|
let chunk = lua.load(self.start.as_str());
|
||||||
if let Err(err) = chunk.eval::<()>() {
|
if let Err(err) = chunk.eval::<()>() {
|
||||||
result = Err(
|
reports.push(
|
||||||
Report::build(ReportKind::Error, location.source(), location.start())
|
Report::build(ReportKind::Error, location.source(), location.start())
|
||||||
.with_message("Lua execution failed")
|
.with_message("Lua execution failed")
|
||||||
.with_label(
|
.with_label(
|
||||||
Label::new((location.source(), location.range.clone()))
|
Label::new((location.source(), location.range.clone()))
|
||||||
.with_message(err.to_string())
|
.with_message(err.to_string())
|
||||||
.with_color(parser_state.parser.colors().error),
|
.with_color(state.parser.colors().error),
|
||||||
)
|
)
|
||||||
.with_note(format!(
|
.with_note(format!(
|
||||||
"When trying to start custom style {}",
|
"When trying to start custom style {}",
|
||||||
self.name().fg(parser_state.parser.colors().info)
|
self.name().fg(state.parser.colors().info)
|
||||||
))
|
))
|
||||||
.finish(),
|
.finish(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
result
|
reports
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_end<'a>(
|
fn on_end<'a>(
|
||||||
&self,
|
&self,
|
||||||
location: Token,
|
location: Token,
|
||||||
parser_state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a dyn Document<'a>
|
document: &'a dyn Document<'a>,
|
||||||
) -> Vec<Report<(Rc<dyn Source>, Range<usize>)>> {
|
) -> Vec<Report<(Rc<dyn Source>, Range<usize>)>> {
|
||||||
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 {
|
let ctx = KernelContext {
|
||||||
location: location.clone(),
|
location: location.clone(),
|
||||||
parser_state,
|
state,
|
||||||
document,
|
document,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = Ok(());
|
let mut reports = vec![];
|
||||||
kernel.run_with_context(ctx, |lua| {
|
kernel.run_with_context(ctx, |lua| {
|
||||||
let chunk = lua.load(self.end.as_str());
|
let chunk = lua.load(self.end.as_str());
|
||||||
if let Err(err) = chunk.eval::<()>() {
|
if let Err(err) = chunk.eval::<()>() {
|
||||||
result = Err(
|
reports.push(
|
||||||
Report::build(ReportKind::Error, location.source(), location.start())
|
Report::build(ReportKind::Error, location.source(), location.start())
|
||||||
.with_message("Lua execution failed")
|
.with_message("Lua execution failed")
|
||||||
.with_label(
|
.with_label(
|
||||||
Label::new((location.source(), location.range.clone()))
|
Label::new((location.source(), location.range.clone()))
|
||||||
.with_message(err.to_string())
|
.with_message(err.to_string())
|
||||||
.with_color(parser_state.colors().error),
|
.with_color(state.parser.colors().error),
|
||||||
)
|
)
|
||||||
.with_note(format!(
|
.with_note(format!(
|
||||||
"When trying to end custom style {}",
|
"When trying to end custom style {}",
|
||||||
self.name().fg(parser_state.colors().info)
|
self.name().fg(state.parser.colors().info)
|
||||||
))
|
))
|
||||||
.finish(),
|
.finish(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
result
|
reports
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,8 +131,8 @@ impl RuleState for CustomStyleState {
|
||||||
|
|
||||||
fn on_remove<'a>(
|
fn on_remove<'a>(
|
||||||
&self,
|
&self,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &dyn Document
|
document: &dyn Document,
|
||||||
) -> Vec<Report<'a, (Rc<dyn Source>, Range<usize>)>> {
|
) -> Vec<Report<'a, (Rc<dyn Source>, Range<usize>)>> {
|
||||||
let mut reports = vec![];
|
let mut reports = vec![];
|
||||||
|
|
||||||
|
@ -189,6 +191,7 @@ impl Rule for CustomStyleRule {
|
||||||
state
|
state
|
||||||
.shared
|
.shared
|
||||||
.custom_styles
|
.custom_styles
|
||||||
|
.borrow()
|
||||||
.iter()
|
.iter()
|
||||||
.for_each(|(_name, style)| match style.tokens() {
|
.for_each(|(_name, style)| match style.tokens() {
|
||||||
CustomStyleToken::Toggle(s) => {
|
CustomStyleToken::Toggle(s) => {
|
||||||
|
@ -228,67 +231,61 @@ impl Rule for CustomStyleRule {
|
||||||
|
|
||||||
fn on_match<'a>(
|
fn on_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a dyn Document<'a>,
|
document: &'a dyn Document<'a>,
|
||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
match_data: Option<Box<dyn Any>>,
|
match_data: Box<dyn Any>,
|
||||||
) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
|
) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
|
||||||
let (style, end) = match_data
|
let (style, end) = match_data
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.downcast_ref::<(Rc<dyn CustomStyle>, bool)>()
|
.downcast_ref::<(Rc<dyn CustomStyle>, bool)>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let query = state.shared.rule_state.get(STATE_NAME);
|
let mut rule_state_borrow = state.shared.rule_state.borrow_mut();
|
||||||
let rule_state = match query {
|
let style_state = match rule_state_borrow.get(STATE_NAME) {
|
||||||
Some(state) => state,
|
Some(rule_state) => rule_state,
|
||||||
None => {
|
|
||||||
// Insert as a new state
|
// Insert as a new state
|
||||||
match state.shared.rule_state.insert(
|
None => {
|
||||||
|
match rule_state_borrow.insert(
|
||||||
STATE_NAME.into(),
|
STATE_NAME.into(),
|
||||||
Rc::new(RefCell::new(CustomStyleState {
|
Rc::new(RefCell::new(CustomStyleState {
|
||||||
toggled: HashMap::new(),
|
toggled: HashMap::new(),
|
||||||
})),
|
})),
|
||||||
) {
|
) {
|
||||||
Err(_) => panic!("Unknown error"),
|
Err(err) => panic!("{err}"),
|
||||||
Ok(state) => state,
|
Ok(rule_state) => rule_state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (close, token) = match style.tokens() {
|
let (close, token) = match style.tokens() {
|
||||||
CustomStyleToken::Toggle(s) => {
|
CustomStyleToken::Toggle(s) => {
|
||||||
let mut borrow = rule_state.borrow_mut();
|
let mut borrow = style_state.as_ref().borrow_mut();
|
||||||
let state = borrow.downcast_mut::<CustomStyleState>().unwrap();
|
let style_state = borrow.downcast_mut::<CustomStyleState>().unwrap();
|
||||||
|
|
||||||
match state.toggled.get(style.name()) {
|
if style_state.toggled.get(style.name()).is_some() {
|
||||||
Some(_) => {
|
|
||||||
// Terminate style
|
// Terminate style
|
||||||
let token =
|
let token = Token::new(cursor.pos..cursor.pos + s.len(), cursor.source.clone());
|
||||||
Token::new(cursor.pos..cursor.pos + s.len(), cursor.source.clone());
|
|
||||||
|
|
||||||
state.toggled.remove(style.name());
|
style_state.toggled.remove(style.name());
|
||||||
(true, token)
|
(true, token)
|
||||||
}
|
} else {
|
||||||
None => {
|
|
||||||
// Start style
|
// Start style
|
||||||
let token =
|
let token = Token::new(cursor.pos..cursor.pos + s.len(), cursor.source.clone());
|
||||||
Token::new(cursor.pos..cursor.pos + s.len(), cursor.source.clone());
|
|
||||||
|
|
||||||
state.toggled.insert(style.name().into(), token.clone());
|
style_state
|
||||||
|
.toggled
|
||||||
|
.insert(style.name().into(), token.clone());
|
||||||
(false, token)
|
(false, token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
CustomStyleToken::Pair(s_begin, s_end) => {
|
CustomStyleToken::Pair(s_begin, s_end) => {
|
||||||
let mut borrow = rule_state.borrow_mut();
|
let mut borrow = style_state.borrow_mut();
|
||||||
let state = borrow.downcast_mut::<CustomStyleState>().unwrap();
|
let style_state = borrow.downcast_mut::<CustomStyleState>().unwrap();
|
||||||
|
|
||||||
if *end {
|
if *end {
|
||||||
// Terminate style
|
// Terminate style
|
||||||
let token =
|
let token =
|
||||||
Token::new(cursor.pos..cursor.pos + s_end.len(), cursor.source.clone());
|
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 (
|
return (
|
||||||
cursor.at(cursor.pos + s_end.len()),
|
cursor.at(cursor.pos + s_end.len()),
|
||||||
vec![
|
vec![
|
||||||
|
@ -308,7 +305,7 @@ impl Rule for CustomStyleRule {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.toggled.remove(style.name());
|
style_state.toggled.remove(style.name());
|
||||||
(true, token)
|
(true, token)
|
||||||
} else {
|
} else {
|
||||||
// Start style
|
// Start style
|
||||||
|
@ -316,7 +313,7 @@ impl Rule for CustomStyleRule {
|
||||||
cursor.pos..cursor.pos + s_begin.len(),
|
cursor.pos..cursor.pos + s_begin.len(),
|
||||||
cursor.source.clone(),
|
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 (
|
return (
|
||||||
cursor.at(cursor.pos + s_end.len()),
|
cursor.at(cursor.pos + s_end.len()),
|
||||||
vec![Report::build(
|
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)
|
(false, token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(rep) = if close {
|
let reports = if close {
|
||||||
style.on_end(token.clone(), state, document)
|
style.on_end(token.clone(), state, document)
|
||||||
} else {
|
} else {
|
||||||
style.on_start(token.clone(), state, document)
|
style.on_start(token.clone(), state, document)
|
||||||
} {
|
};
|
||||||
return (
|
|
||||||
cursor.at(token.end()),
|
(cursor.at(token.end()), unsafe {
|
||||||
vec![unsafe {
|
std::mem::transmute(reports)
|
||||||
// TODO
|
})
|
||||||
std::mem::transmute(rep)
|
|
||||||
}],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
(cursor.at(token.end()), vec![])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> {
|
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.with_borrow(|ctx| {
|
||||||
ctx.as_ref().map(|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 {
|
result = Err(BadArgument {
|
||||||
to: Some("define_toggled".to_string()),
|
to: Some("define_toggled".to_string()),
|
||||||
pos: 1,
|
pos: 1,
|
||||||
|
@ -399,7 +394,11 @@ impl Rule for CustomStyleRule {
|
||||||
});
|
});
|
||||||
return;
|
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.with_borrow(|ctx| {
|
||||||
ctx.as_ref().map(|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 {
|
result = Err(BadArgument {
|
||||||
to: Some("define_paired".to_string()),
|
to: Some("define_paired".to_string()),
|
||||||
pos: 1,
|
pos: 1,
|
||||||
|
@ -454,7 +453,7 @@ impl Rule for CustomStyleRule {
|
||||||
});
|
});
|
||||||
return;
|
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::raw::Raw;
|
||||||
use crate::elements::text::Text;
|
use crate::elements::text::Text;
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
use crate::validate_document;
|
use crate::validate_document;
|
||||||
|
|
||||||
|
@ -505,7 +505,7 @@ pre |styled| post °Hello°.
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
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,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph {
|
Paragraph {
|
||||||
|
@ -549,7 +549,7 @@ pre [styled] post (Hello).
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
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,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph {
|
Paragraph {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::parser::style::ElementStyle;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -15,7 +16,6 @@ use regex::Regex;
|
||||||
|
|
||||||
use crate::document::document::Document;
|
use crate::document::document::Document;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::Rule;
|
use crate::parser::rule::Rule;
|
||||||
use crate::parser::source::Cursor;
|
use crate::parser::source::Cursor;
|
||||||
|
@ -69,10 +69,10 @@ impl Rule for ElemStyleRule {
|
||||||
|
|
||||||
fn on_match<'a>(
|
fn on_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
_document: &'a (dyn Document<'a> + 'a),
|
_document: &'a (dyn Document<'a> + 'a),
|
||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
_match_data: Option<Box<dyn Any>>,
|
_match_data: Box<dyn Any>,
|
||||||
) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
|
) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
|
||||||
let mut reports = vec![];
|
let mut reports = vec![];
|
||||||
let matches = self
|
let matches = self
|
||||||
|
@ -81,7 +81,7 @@ impl Rule for ElemStyleRule {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut cursor = cursor.at(matches.get(0).unwrap().end() - 1);
|
let mut cursor = cursor.at(matches.get(0).unwrap().end() - 1);
|
||||||
|
|
||||||
let style = if let Some(key) = matches.get(1) {
|
let style: Rc<dyn ElementStyle> = if let Some(key) = matches.get(1) {
|
||||||
let trimmed = key.as_str().trim_start().trim_end();
|
let trimmed = key.as_str().trim_start().trim_end();
|
||||||
|
|
||||||
// Check if empty
|
// Check if empty
|
||||||
|
@ -100,7 +100,7 @@ impl Rule for ElemStyleRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if key exists
|
// Check if key exists
|
||||||
if !state.shared.style.is_registered(trimmed) {
|
if !state.shared.styles.borrow().is_registered(trimmed) {
|
||||||
reports.push(
|
reports.push(
|
||||||
Report::build(ReportKind::Error, cursor.source.clone(), key.start())
|
Report::build(ReportKind::Error, cursor.source.clone(), key.start())
|
||||||
.with_message("Unknown Style Key")
|
.with_message("Unknown Style Key")
|
||||||
|
@ -118,7 +118,7 @@ impl Rule for ElemStyleRule {
|
||||||
return (cursor, reports);
|
return (cursor, reports);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.shared.style.current_style(trimmed)
|
state.shared.styles.borrow().current(trimmed)
|
||||||
} else {
|
} else {
|
||||||
panic!("Unknown error")
|
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)
|
(cursor, reports)
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,13 @@ impl Rule for ElemStyleRule {
|
||||||
let mut result = Ok(());
|
let mut result = Ok(());
|
||||||
CTX.with_borrow(|ctx| {
|
CTX.with_borrow(|ctx| {
|
||||||
ctx.as_ref().map(|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 {
|
result = Err(BadArgument {
|
||||||
to: Some("set".to_string()),
|
to: Some("set".to_string()),
|
||||||
pos: 1,
|
pos: 1,
|
||||||
|
@ -198,7 +204,7 @@ impl Rule for ElemStyleRule {
|
||||||
return;
|
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) {
|
let new_style = match style.from_lua(lua, new_style) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
result = Err(err);
|
result = Err(err);
|
||||||
|
@ -207,7 +213,7 @@ impl Rule for ElemStyleRule {
|
||||||
Ok(new_style) => new_style,
|
Ok(new_style) => new_style,
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx.parser.set_current_style(new_style);
|
ctx.state.shared.styles.borrow_mut().set_current(new_style);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,6 @@ use crypto::sha2::Sha512;
|
||||||
use graphviz_rust::cmd::Format;
|
use graphviz_rust::cmd::Format;
|
||||||
use graphviz_rust::cmd::Layout;
|
use graphviz_rust::cmd::Layout;
|
||||||
use graphviz_rust::exec_dot;
|
use graphviz_rust::exec_dot;
|
||||||
use mlua::Function;
|
|
||||||
use mlua::Lua;
|
|
||||||
use regex::Captures;
|
use regex::Captures;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
|
@ -28,7 +26,6 @@ use crate::compiler::compiler::Target;
|
||||||
use crate::document::document::Document;
|
use crate::document::document::Document;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
use crate::parser::source::Token;
|
use crate::parser::source::Token;
|
||||||
|
@ -167,11 +164,7 @@ impl GraphRule {
|
||||||
);
|
);
|
||||||
props.insert(
|
props.insert(
|
||||||
"width".to_string(),
|
"width".to_string(),
|
||||||
Property::new(
|
Property::new(true, "SVG width".to_string(), Some("100%".to_string())),
|
||||||
true,
|
|
||||||
"SVG width".to_string(),
|
|
||||||
Some("100%".to_string()),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
Self {
|
Self {
|
||||||
re: [Regex::new(
|
re: [Regex::new(
|
||||||
|
@ -191,7 +184,7 @@ impl RegexRule for GraphRule {
|
||||||
fn on_regex_match(
|
fn on_regex_match(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &dyn Document,
|
document: &dyn Document,
|
||||||
token: Token,
|
token: Token,
|
||||||
matches: Captures,
|
matches: Captures,
|
||||||
|
@ -349,11 +342,11 @@ impl RegexRule for GraphRule {
|
||||||
);
|
);
|
||||||
return reports;
|
return reports;
|
||||||
}
|
}
|
||||||
_ => panic!("Unknown error")
|
_ => panic!("Unknown error"),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Graphviz {
|
Box::new(Graphviz {
|
||||||
location: token,
|
location: token,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::document::document::Document;
|
use crate::document::document::Document;
|
||||||
use crate::document::document::DocumentAccessors;
|
use crate::document::document::DocumentAccessors;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::parser::ReportColors;
|
use crate::parser::parser::ReportColors;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
|
@ -47,7 +46,7 @@ impl RegexRule for ImportRule {
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a dyn Document<'a>,
|
document: &'a dyn Document<'a>,
|
||||||
token: Token,
|
token: Token,
|
||||||
matches: Captures,
|
matches: Captures,
|
||||||
|
@ -120,7 +119,8 @@ impl RegexRule for ImportRule {
|
||||||
|
|
||||||
// [Optional] import as
|
// [Optional] import as
|
||||||
let import_as = match matches.get(1) {
|
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,
|
Ok(as_name) => as_name,
|
||||||
Err(msg) => {
|
Err(msg) => {
|
||||||
result.push(
|
result.push(
|
||||||
|
@ -168,7 +168,7 @@ impl RegexRule for ImportRule {
|
||||||
// Close paragraph
|
// Close paragraph
|
||||||
// TODO2: Check if this is safe to remove
|
// TODO2: Check if this is safe to remove
|
||||||
if document.last_element::<Paragraph>().is_none() {
|
if document.last_element::<Paragraph>().is_none() {
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Paragraph {
|
Box::new(Paragraph {
|
||||||
location: Token::new(token.end()..token.end(), token.source()),
|
location: Token::new(token.end()..token.end(), token.source()),
|
||||||
|
|
|
@ -6,7 +6,6 @@ use crate::document::element::Element;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
use crate::parser::layout::LayoutHolder;
|
use crate::parser::layout::LayoutHolder;
|
||||||
use crate::parser::layout::LayoutType;
|
use crate::parser::layout::LayoutType;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::parser::ReportColors;
|
use crate::parser::parser::ReportColors;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
|
@ -249,7 +248,7 @@ impl RuleState for LayoutState {
|
||||||
|
|
||||||
fn on_remove<'a>(
|
fn on_remove<'a>(
|
||||||
&self,
|
&self,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &dyn Document,
|
document: &dyn Document,
|
||||||
) -> Vec<Report<'a, (Rc<dyn Source>, Range<usize>)>> {
|
) -> Vec<Report<'a, (Rc<dyn Source>, Range<usize>)>> {
|
||||||
let mut reports = vec![];
|
let mut reports = vec![];
|
||||||
|
@ -315,17 +314,17 @@ impl LayoutRule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize_state(state: &mut ParserState) -> Rc<RefCell<dyn RuleState>> {
|
pub fn initialize_state(state: &ParserState) -> Rc<RefCell<dyn RuleState>> {
|
||||||
let query = state.shared.rule_state.get(STATE_NAME);
|
let mut rule_state_borrow = state.shared.rule_state.borrow_mut();
|
||||||
match query {
|
match rule_state_borrow.get(STATE_NAME) {
|
||||||
Some(state) => state,
|
Some(state) => state,
|
||||||
None => {
|
None => {
|
||||||
// Insert as a new state
|
// Insert as a new state
|
||||||
match state.shared.rule_state.insert(
|
match rule_state_borrow.insert(
|
||||||
STATE_NAME.into(),
|
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,
|
Ok(state) => state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385,7 +384,7 @@ impl RegexRule for LayoutRule {
|
||||||
fn on_regex_match(
|
fn on_regex_match(
|
||||||
&self,
|
&self,
|
||||||
index: usize,
|
index: usize,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &dyn Document,
|
document: &dyn Document,
|
||||||
token: Token,
|
token: Token,
|
||||||
matches: Captures,
|
matches: Captures,
|
||||||
|
@ -453,7 +452,7 @@ impl RegexRule for LayoutRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get layout
|
// Get layout
|
||||||
let layout_type = match state.shared.layouts.get(trimmed) {
|
let layout_type = match state.shared.layouts.borrow().get(trimmed) {
|
||||||
None => {
|
None => {
|
||||||
reports.push(
|
reports.push(
|
||||||
Report::build(ReportKind::Error, token.source(), name.start())
|
Report::build(ReportKind::Error, token.source(), name.start())
|
||||||
|
@ -487,7 +486,7 @@ impl RegexRule for LayoutRule {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Layout {
|
Box::new(Layout {
|
||||||
location: token.clone(),
|
location: token.clone(),
|
||||||
|
@ -498,11 +497,12 @@ impl RegexRule for LayoutRule {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
state
|
rule_state
|
||||||
|
.as_ref()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.downcast_mut::<LayoutState>()
|
.downcast_mut::<LayoutState>()
|
||||||
.map_or_else(
|
.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())),
|
|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
|
let (id, token_type, layout_type, properties) = if index == 1
|
||||||
// LAYOUT_NEXT
|
// LAYOUT_NEXT
|
||||||
{
|
{
|
||||||
let mut state_borrow = state.borrow_mut();
|
let mut rule_state_borrow = rule_state.as_ref().borrow_mut();
|
||||||
let state = state_borrow.downcast_mut::<LayoutState>().unwrap();
|
let layout_state = rule_state_borrow.downcast_mut::<LayoutState>().unwrap();
|
||||||
|
|
||||||
let (tokens, layout_type) = match state.stack.last_mut() {
|
let (tokens, layout_type) = match layout_state.stack.last_mut() {
|
||||||
None => {
|
None => {
|
||||||
reports.push(
|
reports.push(
|
||||||
Report::build(ReportKind::Error, token.source(), token.start())
|
Report::build(ReportKind::Error, token.source(), token.start())
|
||||||
|
@ -576,10 +576,10 @@ impl RegexRule for LayoutRule {
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// LAYOUT_END
|
// LAYOUT_END
|
||||||
let mut state_borrow = state.borrow_mut();
|
let mut rule_state_borrow = rule_state.as_ref().borrow_mut();
|
||||||
let state = state_borrow.downcast_mut::<LayoutState>().unwrap();
|
let layout_state = rule_state_borrow.downcast_mut::<LayoutState>().unwrap();
|
||||||
|
|
||||||
let (tokens, layout_type) = match state.stack.last_mut() {
|
let (tokens, layout_type) = match layout_state.stack.last_mut() {
|
||||||
None => {
|
None => {
|
||||||
reports.push(
|
reports.push(
|
||||||
Report::build(ReportKind::Error, token.source(), token.start())
|
Report::build(ReportKind::Error, token.source(), token.start())
|
||||||
|
@ -632,11 +632,11 @@ impl RegexRule for LayoutRule {
|
||||||
|
|
||||||
let layout_type = layout_type.clone();
|
let layout_type = layout_type.clone();
|
||||||
let id = tokens.len();
|
let id = tokens.len();
|
||||||
state.stack.pop();
|
layout_state.stack.pop();
|
||||||
(id, LayoutToken::End, layout_type, properties)
|
(id, LayoutToken::End, layout_type, properties)
|
||||||
};
|
};
|
||||||
|
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Layout {
|
Box::new(Layout {
|
||||||
location: token,
|
location: token,
|
||||||
|
@ -676,11 +676,12 @@ impl RegexRule for LayoutRule {
|
||||||
|
|
||||||
CTX.with_borrow(|ctx| {
|
CTX.with_borrow(|ctx| {
|
||||||
ctx.as_ref().map(|ctx| {
|
ctx.as_ref().map(|ctx| {
|
||||||
// Make sure the state has been initialized
|
// Make sure the rule state has been initialized
|
||||||
let state = LayoutRule::initialize_state(ctx.parser);
|
let rule_state = LayoutRule::initialize_state(ctx.state);
|
||||||
|
|
||||||
// Get layout
|
// 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 => {
|
None => {
|
||||||
result = Err(BadArgument {
|
result = Err(BadArgument {
|
||||||
|
@ -712,7 +713,7 @@ impl RegexRule for LayoutRule {
|
||||||
|
|
||||||
let id = match layout_token {
|
let id = match layout_token {
|
||||||
LayoutToken::Begin => {
|
LayoutToken::Begin => {
|
||||||
ctx.parser.push(
|
ctx.state.push(
|
||||||
ctx.document,
|
ctx.document,
|
||||||
Box::new(Layout {
|
Box::new(Layout {
|
||||||
location: ctx.location.clone(),
|
location: ctx.location.clone(),
|
||||||
|
@ -723,20 +724,21 @@ impl RegexRule for LayoutRule {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
state
|
rule_state
|
||||||
|
.as_ref()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.downcast_mut::<LayoutState>()
|
.downcast_mut::<LayoutState>()
|
||||||
.map_or_else(
|
.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())),
|
|s| s.stack.push((vec![ctx.location.clone()], layout_type.clone())),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
LayoutToken::Next => {
|
LayoutToken::Next => {
|
||||||
let mut state_borrow = state.borrow_mut();
|
let mut state_borrow = rule_state.as_ref().borrow_mut();
|
||||||
let state = state_borrow.downcast_mut::<LayoutState>().unwrap();
|
let layout_state = state_borrow.downcast_mut::<LayoutState>().unwrap();
|
||||||
|
|
||||||
let (tokens, current_layout_type) = match state.stack.last_mut() {
|
let (tokens, current_layout_type) = match layout_state.stack.last_mut() {
|
||||||
None => {
|
None => {
|
||||||
result = Err(BadArgument {
|
result = Err(BadArgument {
|
||||||
to: Some("push".to_string()),
|
to: Some("push".to_string()),
|
||||||
|
@ -781,10 +783,10 @@ impl RegexRule for LayoutRule {
|
||||||
tokens.len() - 1
|
tokens.len() - 1
|
||||||
},
|
},
|
||||||
LayoutToken::End => {
|
LayoutToken::End => {
|
||||||
let mut state_borrow = state.borrow_mut();
|
let mut state_borrow = rule_state.as_ref().borrow_mut();
|
||||||
let state = state_borrow.downcast_mut::<LayoutState>().unwrap();
|
let layout_state = state_borrow.downcast_mut::<LayoutState>().unwrap();
|
||||||
|
|
||||||
let (tokens, current_layout_type) = match state.stack.last_mut() {
|
let (tokens, current_layout_type) = match layout_state.stack.last_mut() {
|
||||||
None => {
|
None => {
|
||||||
result = Err(BadArgument {
|
result = Err(BadArgument {
|
||||||
to: Some("push".to_string()),
|
to: Some("push".to_string()),
|
||||||
|
@ -826,12 +828,12 @@ impl RegexRule for LayoutRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = tokens.len();
|
let id = tokens.len();
|
||||||
state.stack.pop();
|
layout_state.stack.pop();
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx.state.parser.push(
|
ctx.state.push(
|
||||||
ctx.document,
|
ctx.document,
|
||||||
Box::new(Layout {
|
Box::new(Layout {
|
||||||
location: ctx.location.clone(),
|
location: ctx.location.clone(),
|
||||||
|
@ -864,6 +866,7 @@ mod tests {
|
||||||
use crate::elements::paragraph::Paragraph;
|
use crate::elements::paragraph::Paragraph;
|
||||||
use crate::elements::text::Text;
|
use crate::elements::text::Text;
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
use crate::validate_document;
|
use crate::validate_document;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ use crate::document::element::ContainerElement;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
|
@ -92,7 +91,7 @@ impl RegexRule for LinkRule {
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a (dyn Document<'a> + 'a),
|
document: &'a (dyn Document<'a> + 'a),
|
||||||
token: Token,
|
token: Token,
|
||||||
matches: Captures,
|
matches: Captures,
|
||||||
|
@ -197,7 +196,7 @@ impl RegexRule for LinkRule {
|
||||||
_ => panic!("Empty link url"),
|
_ => panic!("Empty link url"),
|
||||||
};
|
};
|
||||||
|
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Link {
|
Box::new(Link {
|
||||||
location: token,
|
location: token,
|
||||||
|
@ -224,7 +223,7 @@ impl RegexRule for LinkRule {
|
||||||
display,
|
display,
|
||||||
));
|
));
|
||||||
let display_content =
|
let display_content =
|
||||||
match util::parse_paragraph(ctx.parser, source, ctx.document) {
|
match util::parse_paragraph(ctx.state, source, ctx.document) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
result = Err(BadArgument {
|
result = Err(BadArgument {
|
||||||
to: Some("push".to_string()),
|
to: Some("push".to_string()),
|
||||||
|
@ -241,7 +240,7 @@ impl RegexRule for LinkRule {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx.parser.push(
|
ctx.state.push(
|
||||||
ctx.document,
|
ctx.document,
|
||||||
Box::new(Link {
|
Box::new(Link {
|
||||||
location: ctx.location.clone(),
|
location: ctx.location.clone(),
|
||||||
|
@ -267,6 +266,7 @@ mod tests {
|
||||||
use crate::elements::style::Style;
|
use crate::elements::style::Style;
|
||||||
use crate::elements::text::Text;
|
use crate::elements::text::Text;
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
use crate::validate_document;
|
use crate::validate_document;
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ Some [link](url).
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
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,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph {
|
Paragraph {
|
||||||
|
@ -314,7 +314,7 @@ nml.link.push("**BOLD link**", "another url")
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
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,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph {
|
Paragraph {
|
||||||
|
|
|
@ -150,7 +150,7 @@ impl ListRule {
|
||||||
|
|
||||||
// Close
|
// Close
|
||||||
for i in start_pos..current.len() {
|
for i in start_pos..current.len() {
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(ListMarker {
|
Box::new(ListMarker {
|
||||||
location: token.clone(),
|
location: token.clone(),
|
||||||
|
@ -162,7 +162,7 @@ impl ListRule {
|
||||||
|
|
||||||
// Open
|
// Open
|
||||||
for i in start_pos..target.len() {
|
for i in start_pos..target.len() {
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(ListMarker {
|
Box::new(ListMarker {
|
||||||
location: token.clone(),
|
location: token.clone(),
|
||||||
|
@ -260,7 +260,7 @@ impl Rule for ListRule {
|
||||||
|
|
||||||
fn on_match<'a>(
|
fn on_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a dyn Document<'a>,
|
document: &'a dyn Document<'a>,
|
||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
_match_data: Box<dyn Any>,
|
_match_data: Box<dyn Any>,
|
||||||
|
@ -403,7 +403,7 @@ impl Rule for ListRule {
|
||||||
ListRule::push_markers(&token, state, document, &vec![], &depth);
|
ListRule::push_markers(&token, state, document, &vec![], &depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(ListEntry {
|
Box::new(ListEntry {
|
||||||
location: Token::new(
|
location: Token::new(
|
||||||
|
|
|
@ -7,8 +7,6 @@ use ariadne::Fmt;
|
||||||
use ariadne::Label;
|
use ariadne::Label;
|
||||||
use ariadne::Report;
|
use ariadne::Report;
|
||||||
use ariadne::ReportKind;
|
use ariadne::ReportKind;
|
||||||
use mlua::Function;
|
|
||||||
use mlua::Lua;
|
|
||||||
use regex::Captures;
|
use regex::Captures;
|
||||||
use regex::Match;
|
use regex::Match;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
@ -23,7 +21,6 @@ use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::document::element::ReferenceableElement;
|
use crate::document::element::ReferenceableElement;
|
||||||
use crate::document::references::validate_refname;
|
use crate::document::references::validate_refname;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::parser::ReportColors;
|
use crate::parser::parser::ReportColors;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
|
@ -334,7 +331,7 @@ impl RegexRule for MediaRule {
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a (dyn Document<'a> + 'a),
|
document: &'a (dyn Document<'a> + 'a),
|
||||||
token: Token,
|
token: Token,
|
||||||
matches: Captures,
|
matches: Captures,
|
||||||
|
@ -378,7 +375,8 @@ impl RegexRule for MediaRule {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Properties
|
// 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,
|
Ok(pm) => pm,
|
||||||
Err(report) => {
|
Err(report) => {
|
||||||
reports.push(report);
|
reports.push(report);
|
||||||
|
@ -481,7 +479,7 @@ impl RegexRule for MediaRule {
|
||||||
let mut group = match document.last_element_mut::<Media>() {
|
let mut group = match document.last_element_mut::<Media>() {
|
||||||
Some(group) => group,
|
Some(group) => group,
|
||||||
None => {
|
None => {
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Media {
|
Box::new(Media {
|
||||||
location: token.clone(),
|
location: token.clone(),
|
||||||
|
@ -521,6 +519,7 @@ impl RegexRule for MediaRule {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -11,7 +11,6 @@ use crate::document::document::Document;
|
||||||
use crate::document::element::ContainerElement;
|
use crate::document::element::ContainerElement;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::Rule;
|
use crate::parser::rule::Rule;
|
||||||
use crate::parser::source::Cursor;
|
use crate::parser::source::Cursor;
|
||||||
|
@ -115,17 +114,17 @@ impl Rule for ParagraphRule {
|
||||||
|
|
||||||
fn on_match(
|
fn on_match(
|
||||||
&self,
|
&self,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &dyn Document,
|
document: &dyn Document,
|
||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
_match_data: Option<Box<dyn Any>>,
|
_match_data: Box<dyn Any>,
|
||||||
) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
|
) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
|
||||||
let end_cursor = match self.re.captures_at(cursor.source.content(), cursor.pos) {
|
let end_cursor = match self.re.captures_at(cursor.source.content(), cursor.pos) {
|
||||||
None => panic!("Unknown error"),
|
None => panic!("Unknown error"),
|
||||||
Some(capture) => cursor.at(capture.get(0).unwrap().end() - 1),
|
Some(capture) => cursor.at(capture.get(0).unwrap().end() - 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Paragraph {
|
Box::new(Paragraph {
|
||||||
location: Token::new(cursor.pos..end_cursor.pos, cursor.source.clone()),
|
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::paragraph::Paragraph;
|
||||||
use crate::elements::text::Text;
|
use crate::elements::text::Text;
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
use crate::validate_document;
|
use crate::validate_document;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ use crate::document::document::Document;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
|
@ -79,7 +78,7 @@ impl RegexRule for RawRule {
|
||||||
fn on_regex_match(
|
fn on_regex_match(
|
||||||
&self,
|
&self,
|
||||||
_index: usize,
|
_index: usize,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &dyn Document,
|
document: &dyn Document,
|
||||||
token: Token,
|
token: Token,
|
||||||
matches: Captures,
|
matches: Captures,
|
||||||
|
@ -208,7 +207,7 @@ impl RegexRule for RawRule {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Raw {
|
Box::new(Raw {
|
||||||
location: token.clone(),
|
location: token.clone(),
|
||||||
|
@ -243,7 +242,7 @@ impl RegexRule for RawRule {
|
||||||
|
|
||||||
CTX.with_borrow(|ctx| {
|
CTX.with_borrow(|ctx| {
|
||||||
ctx.as_ref().map(|ctx| {
|
ctx.as_ref().map(|ctx| {
|
||||||
ctx.state.parser.push(
|
ctx.state.push(
|
||||||
ctx.document,
|
ctx.document,
|
||||||
Box::new(Raw {
|
Box::new(Raw {
|
||||||
location: ctx.location.clone(),
|
location: ctx.location.clone(),
|
||||||
|
@ -269,6 +268,7 @@ mod tests {
|
||||||
use crate::elements::paragraph::Paragraph;
|
use crate::elements::paragraph::Paragraph;
|
||||||
use crate::elements::text::Text;
|
use crate::elements::text::Text;
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
use crate::validate_document;
|
use crate::validate_document;
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,6 @@ use ariadne::Fmt;
|
||||||
use ariadne::Label;
|
use ariadne::Label;
|
||||||
use ariadne::Report;
|
use ariadne::Report;
|
||||||
use ariadne::ReportKind;
|
use ariadne::ReportKind;
|
||||||
use mlua::Function;
|
|
||||||
use mlua::Lua;
|
|
||||||
use regex::Captures;
|
use regex::Captures;
|
||||||
use regex::Match;
|
use regex::Match;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
@ -18,7 +16,6 @@ use crate::document::document::Document;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::document::references::validate_refname;
|
use crate::document::references::validate_refname;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::parser::ReportColors;
|
use crate::parser::parser::ReportColors;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
|
@ -136,7 +133,7 @@ impl RegexRule for ReferenceRule {
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a (dyn Document<'a> + 'a),
|
document: &'a (dyn Document<'a> + 'a),
|
||||||
token: Token,
|
token: Token,
|
||||||
matches: Captures,
|
matches: Captures,
|
||||||
|
@ -179,7 +176,8 @@ impl RegexRule for ReferenceRule {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Properties
|
// 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,
|
Ok(pm) => pm,
|
||||||
Err(report) => {
|
Err(report) => {
|
||||||
reports.push(report);
|
reports.push(report);
|
||||||
|
@ -194,7 +192,7 @@ impl RegexRule for ReferenceRule {
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|(_, s)| Some(s));
|
.and_then(|(_, s)| Some(s));
|
||||||
|
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Reference {
|
Box::new(Reference {
|
||||||
location: token,
|
location: token,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::document::document::Document;
|
use crate::document::document::Document;
|
||||||
use crate::lua::kernel::Kernel;
|
use crate::lua::kernel::Kernel;
|
||||||
use crate::lua::kernel::KernelContext;
|
use crate::lua::kernel::KernelContext;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::parser::ReportColors;
|
use crate::parser::parser::ReportColors;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
|
@ -13,7 +12,6 @@ use ariadne::Fmt;
|
||||||
use ariadne::Label;
|
use ariadne::Label;
|
||||||
use ariadne::Report;
|
use ariadne::Report;
|
||||||
use ariadne::ReportKind;
|
use ariadne::ReportKind;
|
||||||
use mlua::Function;
|
|
||||||
use mlua::Lua;
|
use mlua::Lua;
|
||||||
use regex::Captures;
|
use regex::Captures;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
@ -85,7 +83,7 @@ impl RegexRule for ScriptRule {
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
index: usize,
|
index: usize,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a dyn Document<'a>,
|
document: &'a dyn Document<'a>,
|
||||||
token: Token,
|
token: Token,
|
||||||
matches: Captures,
|
matches: Captures,
|
||||||
|
@ -94,7 +92,8 @@ impl RegexRule for ScriptRule {
|
||||||
|
|
||||||
let kernel_name = match matches.get(1) {
|
let kernel_name = match matches.get(1) {
|
||||||
None => "main".to_string(),
|
None => "main".to_string(),
|
||||||
Some(name) => match ScriptRule::validate_kernel_name(state.parser.colors(), name.as_str()) {
|
Some(name) => {
|
||||||
|
match ScriptRule::validate_kernel_name(state.parser.colors(), name.as_str()) {
|
||||||
Ok(name) => name,
|
Ok(name) => name,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
reports.push(
|
reports.push(
|
||||||
|
@ -109,14 +108,17 @@ impl RegexRule for ScriptRule {
|
||||||
);
|
);
|
||||||
return reports;
|
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
|
let kernel_data = matches
|
||||||
.get(if index == 0 { 2 } else { 3 })
|
.get(if index == 0 { 2 } else { 3 })
|
||||||
|
@ -227,7 +229,7 @@ impl RegexRule for ScriptRule {
|
||||||
// Eval to text
|
// Eval to text
|
||||||
{
|
{
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Text::new(
|
Box::new(Text::new(
|
||||||
Token::new(1..source.content().len(), source.clone()),
|
Token::new(1..source.content().len(), source.clone()),
|
||||||
|
@ -245,7 +247,9 @@ impl RegexRule for ScriptRule {
|
||||||
)) as Rc<dyn Source>;
|
)) as Rc<dyn Source>;
|
||||||
|
|
||||||
state.with_state(|new_state| {
|
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 {
|
let ctx = KernelContext {
|
||||||
location: Token::new(0..source.content().len(), source.clone()),
|
location: Token::new(0..source.content().len(), source.clone()),
|
||||||
parser_state: state,
|
state,
|
||||||
document,
|
document,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -290,6 +294,7 @@ mod tests {
|
||||||
use crate::elements::paragraph::Paragraph;
|
use crate::elements::paragraph::Paragraph;
|
||||||
use crate::elements::style::Style;
|
use crate::elements::style::Style;
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
use crate::validate_document;
|
use crate::validate_document;
|
||||||
|
|
||||||
|
@ -315,7 +320,7 @@ Evaluation: %<! make_ref("hello", "id")>%
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
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,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph;
|
Paragraph;
|
||||||
|
|
|
@ -5,7 +5,6 @@ use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::document::element::ReferenceableElement;
|
use crate::document::element::ReferenceableElement;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
|
@ -162,7 +161,7 @@ impl RegexRule for SectionRule {
|
||||||
fn on_regex_match(
|
fn on_regex_match(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &dyn Document,
|
document: &dyn Document,
|
||||||
token: Token,
|
token: Token,
|
||||||
matches: regex::Captures,
|
matches: regex::Captures,
|
||||||
|
@ -294,12 +293,15 @@ impl RegexRule for SectionRule {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get style
|
// Get style
|
||||||
let style = state.shared.styles
|
let style = state
|
||||||
.current_style(section_style::STYLE_KEY)
|
.shared
|
||||||
|
.styles
|
||||||
|
.borrow()
|
||||||
|
.current(section_style::STYLE_KEY)
|
||||||
.downcast_rc::<SectionStyle>()
|
.downcast_rc::<SectionStyle>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Section {
|
Box::new(Section {
|
||||||
location: token.clone(),
|
location: token.clone(),
|
||||||
|
@ -342,12 +344,15 @@ impl RegexRule for SectionRule {
|
||||||
ctx.as_ref().map(|ctx| {
|
ctx.as_ref().map(|ctx| {
|
||||||
// Get style
|
// Get style
|
||||||
let style = ctx
|
let style = ctx
|
||||||
.parser
|
.state
|
||||||
.current_style(section_style::STYLE_KEY)
|
.shared
|
||||||
|
.styles
|
||||||
|
.borrow()
|
||||||
|
.current(section_style::STYLE_KEY)
|
||||||
.downcast_rc::<SectionStyle>()
|
.downcast_rc::<SectionStyle>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
ctx.parser.push(
|
ctx.state.push(
|
||||||
ctx.document,
|
ctx.document,
|
||||||
Box::new(Section {
|
Box::new(Section {
|
||||||
location: ctx.location.clone(),
|
location: ctx.location.clone(),
|
||||||
|
@ -371,7 +376,7 @@ impl RegexRule for SectionRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_styles(&self, holder: &mut StyleHolder) {
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
use crate::validate_document;
|
use crate::validate_document;
|
||||||
|
|
||||||
|
@ -491,6 +497,8 @@ nml.section.push("6", 6, "", "refname")
|
||||||
let state = ParserState::new(&parser, None);
|
let state = ParserState::new(&parser, None);
|
||||||
let _ = parser.parse(state, source, None);
|
let _ = parser.parse(state, source, None);
|
||||||
|
|
||||||
|
// TODO2
|
||||||
|
/*
|
||||||
let style = state.shared
|
let style = state.shared
|
||||||
.styles
|
.styles
|
||||||
.current_style(section_style::STYLE_KEY)
|
.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_pos, SectionLinkPos::None);
|
||||||
assert_eq!(style.link, ["a".to_string(), "b".to_string(), "c".to_string()]);
|
assert_eq!(style.link, ["a".to_string(), "b".to_string(), "c".to_string()]);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ use crate::document::document::Document;
|
||||||
use crate::document::document::DocumentAccessors;
|
use crate::document::document::DocumentAccessors;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
|
@ -80,7 +79,7 @@ impl RuleState for StyleState {
|
||||||
|
|
||||||
fn on_remove<'a>(
|
fn on_remove<'a>(
|
||||||
&self,
|
&self,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &dyn Document,
|
document: &dyn Document,
|
||||||
) -> Vec<Report<'a, (Rc<dyn Source>, Range<usize>)>> {
|
) -> Vec<Report<'a, (Rc<dyn Source>, Range<usize>)>> {
|
||||||
let mut reports = vec![];
|
let mut reports = vec![];
|
||||||
|
@ -164,17 +163,20 @@ impl RegexRule for StyleRule {
|
||||||
fn on_regex_match(
|
fn on_regex_match(
|
||||||
&self,
|
&self,
|
||||||
index: usize,
|
index: usize,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &dyn Document,
|
document: &dyn Document,
|
||||||
token: Token,
|
token: Token,
|
||||||
_matches: Captures,
|
_matches: Captures,
|
||||||
) -> Vec<Report<(Rc<dyn Source>, Range<usize>)>> {
|
) -> Vec<Report<(Rc<dyn Source>, Range<usize>)>> {
|
||||||
let query = state.shared.rule_state.get(&STATE_NAME);
|
let query = state.shared.rule_state.borrow().get(STATE_NAME);
|
||||||
let state = match query {
|
let style_state = match query {
|
||||||
Some(state) => state,
|
Some(state) => state,
|
||||||
None => {
|
None => {
|
||||||
// Insert as a new state
|
// 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())))
|
.insert(STATE_NAME.into(), Rc::new(RefCell::new(StyleState::new())))
|
||||||
{
|
{
|
||||||
Err(_) => panic!("Unknown error"),
|
Err(_) => panic!("Unknown error"),
|
||||||
|
@ -183,11 +185,11 @@ impl RegexRule for StyleRule {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(style_state) = state.borrow_mut().downcast_mut::<StyleState>() {
|
if let Some(style_state) = style_state.borrow_mut().downcast_mut::<StyleState>() {
|
||||||
style_state.toggled[index] = style_state.toggled[index]
|
style_state.toggled[index] = style_state.toggled[index]
|
||||||
.clone()
|
.clone()
|
||||||
.map_or(Some(token.clone()), |_| None);
|
.map_or(Some(token.clone()), |_| None);
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Style::new(
|
Box::new(Style::new(
|
||||||
token.clone(),
|
token.clone(),
|
||||||
|
@ -196,7 +198,7 @@ impl RegexRule for StyleRule {
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
panic!("Invalid state at `{}`", STATE_NAME.as_str());
|
panic!("Invalid state at `{STATE_NAME}`");
|
||||||
}
|
}
|
||||||
|
|
||||||
return vec![];
|
return vec![];
|
||||||
|
@ -207,6 +209,7 @@ impl RegexRule for StyleRule {
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::elements::text::Text;
|
use crate::elements::text::Text;
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
use crate::validate_document;
|
use crate::validate_document;
|
||||||
|
|
||||||
|
@ -227,7 +230,7 @@ __`UNDERLINE+EM`__
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
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,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph {
|
Paragraph {
|
||||||
|
|
|
@ -14,8 +14,6 @@ use ariadne::Report;
|
||||||
use ariadne::ReportKind;
|
use ariadne::ReportKind;
|
||||||
use crypto::digest::Digest;
|
use crypto::digest::Digest;
|
||||||
use crypto::sha2::Sha512;
|
use crypto::sha2::Sha512;
|
||||||
use mlua::Function;
|
|
||||||
use mlua::Lua;
|
|
||||||
use regex::Captures;
|
use regex::Captures;
|
||||||
use regex::Match;
|
use regex::Match;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
@ -27,7 +25,6 @@ use crate::compiler::compiler::Target;
|
||||||
use crate::document::document::Document;
|
use crate::document::document::Document;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::parser::ReportColors;
|
use crate::parser::parser::ReportColors;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
|
@ -305,7 +302,7 @@ impl RegexRule for TexRule {
|
||||||
fn on_regex_match(
|
fn on_regex_match(
|
||||||
&self,
|
&self,
|
||||||
index: usize,
|
index: usize,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &dyn Document,
|
document: &dyn Document,
|
||||||
token: Token,
|
token: Token,
|
||||||
matches: Captures,
|
matches: Captures,
|
||||||
|
@ -355,7 +352,8 @@ impl RegexRule for TexRule {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Properties
|
// 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,
|
Ok(pm) => pm,
|
||||||
Err(report) => {
|
Err(report) => {
|
||||||
reports.push(report);
|
reports.push(report);
|
||||||
|
@ -413,7 +411,7 @@ impl RegexRule for TexRule {
|
||||||
.and_then(|(_, value)| Some(value))
|
.and_then(|(_, value)| Some(value))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
state.parser.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Tex {
|
Box::new(Tex {
|
||||||
mathmode: index == 1,
|
mathmode: index == 1,
|
||||||
|
@ -433,6 +431,7 @@ impl RegexRule for TexRule {
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::elements::paragraph::Paragraph;
|
use crate::elements::paragraph::Paragraph;
|
||||||
use crate::parser::langparser::LangParser;
|
use crate::parser::langparser::LangParser;
|
||||||
|
use crate::parser::parser::Parser;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
use crate::validate_document;
|
use crate::validate_document;
|
||||||
|
|
||||||
|
@ -451,7 +450,7 @@ $[kind=block,env=another] e^{i\pi}=-1$
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
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,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Tex { mathmode == true, tex == "1+1=2", env == "main", caption == Some("Some, text\\".to_string()) };
|
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,
|
None,
|
||||||
));
|
));
|
||||||
let parser = LangParser::default();
|
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,
|
validate_document!(doc.content().borrow(), 0,
|
||||||
Paragraph {
|
Paragraph {
|
||||||
|
|
|
@ -11,7 +11,6 @@ use crate::document::document::Document;
|
||||||
use crate::document::element::ElemKind;
|
use crate::document::element::ElemKind;
|
||||||
use crate::document::element::Element;
|
use crate::document::element::Element;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::rule::Rule;
|
use crate::parser::rule::Rule;
|
||||||
use crate::parser::source::Cursor;
|
use crate::parser::source::Cursor;
|
||||||
|
@ -53,10 +52,10 @@ impl Rule for TextRule {
|
||||||
|
|
||||||
fn on_match(
|
fn on_match(
|
||||||
&self,
|
&self,
|
||||||
_state: &mut ParserState,
|
_state: &ParserState,
|
||||||
_document: &dyn Document,
|
_document: &dyn Document,
|
||||||
_cursor: Cursor,
|
_cursor: Cursor,
|
||||||
_match_data: Option<Box<dyn Any>>,
|
_match_data: Box<dyn Any>,
|
||||||
) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
|
) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
|
||||||
panic!("Text cannot match");
|
panic!("Text cannot match");
|
||||||
}
|
}
|
||||||
|
@ -68,7 +67,7 @@ impl Rule for TextRule {
|
||||||
lua.create_function(|_, content: String| {
|
lua.create_function(|_, content: String| {
|
||||||
CTX.with_borrow(|ctx| {
|
CTX.with_borrow(|ctx| {
|
||||||
ctx.as_ref().map(|ctx| {
|
ctx.as_ref().map(|ctx| {
|
||||||
ctx.state.parser.push(
|
ctx.state.push(
|
||||||
ctx.document,
|
ctx.document,
|
||||||
Box::new(Text {
|
Box::new(Text {
|
||||||
location: ctx.location.clone(),
|
location: ctx.location.clone(),
|
||||||
|
|
|
@ -3,7 +3,6 @@ use crate::document::variable::BaseVariable;
|
||||||
use crate::document::variable::PathVariable;
|
use crate::document::variable::PathVariable;
|
||||||
use crate::document::variable::Variable;
|
use crate::document::variable::Variable;
|
||||||
use crate::lua::kernel::CTX;
|
use crate::lua::kernel::CTX;
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
use crate::parser::parser::ParserState;
|
use crate::parser::parser::ParserState;
|
||||||
use crate::parser::parser::ReportColors;
|
use crate::parser::parser::ReportColors;
|
||||||
use crate::parser::rule::RegexRule;
|
use crate::parser::rule::RegexRule;
|
||||||
|
@ -124,7 +123,7 @@ impl RegexRule for VariableRule {
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
_: usize,
|
_: usize,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a dyn Document,
|
document: &'a dyn Document,
|
||||||
token: Token,
|
token: Token,
|
||||||
matches: regex::Captures,
|
matches: regex::Captures,
|
||||||
|
@ -316,7 +315,7 @@ impl RegexRule for VariableSubstitutionRule {
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
_index: usize,
|
_index: usize,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a dyn Document<'a>,
|
document: &'a dyn Document<'a>,
|
||||||
token: Token,
|
token: Token,
|
||||||
matches: regex::Captures,
|
matches: regex::Captures,
|
||||||
|
@ -417,7 +416,7 @@ impl RegexRule for VariableSubstitutionRule {
|
||||||
_ => panic!("Unknown error"),
|
_ => panic!("Unknown error"),
|
||||||
};
|
};
|
||||||
|
|
||||||
variable.parse(token, state, document);
|
variable.parse(state, token, document);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::cell::RefMut;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use mlua::Error;
|
|
||||||
use mlua::FromLuaMulti;
|
|
||||||
use mlua::Function;
|
|
||||||
use mlua::IntoLuaMulti;
|
|
||||||
use mlua::Lua;
|
use mlua::Lua;
|
||||||
|
|
||||||
use crate::document::document::Document;
|
use crate::document::document::Document;
|
||||||
|
@ -17,7 +12,6 @@ pub struct KernelContext<'a, 'b, 'c> {
|
||||||
pub location: Token,
|
pub location: Token,
|
||||||
pub state: &'a ParserState<'a, 'b>,
|
pub state: &'a ParserState<'a, 'b>,
|
||||||
pub document: &'c dyn Document<'c>,
|
pub document: &'c dyn Document<'c>,
|
||||||
//pub parser: &'a dyn Parser,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
|
@ -40,7 +34,7 @@ impl Kernel {
|
||||||
let table = lua.create_table().unwrap();
|
let table = lua.create_table().unwrap();
|
||||||
// TODO: Export this so we can check for duplicate rules based on this name
|
// TODO: Export this so we can check for duplicate rules based on this name
|
||||||
let name = rule.name().to_lowercase().replace(' ', "_");
|
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();
|
table.set(fun_name, fun).unwrap();
|
||||||
}
|
}
|
||||||
nml_table.set(name, table).unwrap();
|
nml_table.set(name, table).unwrap();
|
||||||
|
@ -73,11 +67,9 @@ pub struct KernelHolder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KernelHolder {
|
impl KernelHolder {
|
||||||
pub fn get(&self, kernel_name: &str) -> Option<&Kernel> {
|
pub fn get(&self, kernel_name: &str) -> Option<&Kernel> { self.kernels.get(kernel_name) }
|
||||||
self.kernels.get(kernel_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert(&self, kernel_name: String, kernel: Kernel) {
|
pub fn insert(&mut self, kernel_name: String, kernel: Kernel) {
|
||||||
self.kernels.insert(kernel_name, kernel)
|
self.kernels.insert(kernel_name, kernel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
12
src/main.rs
12
src/main.rs
|
@ -47,13 +47,16 @@ NML version: 0.4\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse(parser: &LangParser, input: &str, debug_opts: &Vec<String>) -> Result<Box<dyn Document<'static>>, String> {
|
fn parse(
|
||||||
|
parser: &LangParser,
|
||||||
|
input: &str,
|
||||||
|
debug_opts: &Vec<String>,
|
||||||
|
) -> Result<Box<dyn Document<'static>>, String> {
|
||||||
println!("Parsing {input}...");
|
println!("Parsing {input}...");
|
||||||
let parser = LangParser::default();
|
|
||||||
|
|
||||||
// Parse
|
// Parse
|
||||||
let source = SourceFile::new(input.to_string(), None).unwrap();
|
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()) {
|
if debug_opts.contains(&"ast".to_string()) {
|
||||||
println!("-- BEGIN AST DEBUGGING --");
|
println!("-- BEGIN AST DEBUGGING --");
|
||||||
|
@ -218,8 +221,7 @@ fn main() -> ExitCode {
|
||||||
}
|
}
|
||||||
match std::fs::metadata(&output) {
|
match std::fs::metadata(&output) {
|
||||||
Ok(output_meta) => {
|
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");
|
eprintln!("Input is a directory, but ouput is not a directory, halting");
|
||||||
return ExitCode::FAILURE;
|
return ExitCode::FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
use ariadne::Report;
|
use ariadne::Report;
|
||||||
|
|
||||||
|
@ -25,13 +26,13 @@ pub trait CustomStyle: core::fmt::Debug {
|
||||||
fn on_start<'a>(
|
fn on_start<'a>(
|
||||||
&self,
|
&self,
|
||||||
location: Token,
|
location: Token,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a (dyn Document<'a> + 'a),
|
document: &'a (dyn Document<'a> + 'a),
|
||||||
) -> Vec<Report<(Rc<dyn Source>, Range<usize>)>>;
|
) -> Vec<Report<(Rc<dyn Source>, Range<usize>)>>;
|
||||||
fn on_end<'a>(
|
fn on_end<'a>(
|
||||||
&self,
|
&self,
|
||||||
location: Token,
|
location: Token,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a (dyn Document<'a> + 'a),
|
document: &'a (dyn Document<'a> + 'a),
|
||||||
) -> Vec<Report<(Rc<dyn Source>, Range<usize>)>>;
|
) -> Vec<Report<(Rc<dyn Source>, Range<usize>)>>;
|
||||||
}
|
}
|
||||||
|
@ -42,13 +43,21 @@ pub struct CustomStyleHolder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CustomStyleHolder {
|
impl CustomStyleHolder {
|
||||||
fn get(&self, style_name: &str) -> Option<Rc<dyn CustomStyle>> {
|
pub fn get(&self, style_name: &str) -> Option<Rc<dyn CustomStyle>> {
|
||||||
self.custom_styles
|
self.custom_styles
|
||||||
.get(style_name)
|
.get(style_name)
|
||||||
.map(|style| style.clone())
|
.map(|style| style.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert(&mut self, style: Rc<dyn CustomStyle>) {
|
pub fn insert(&mut self, style: Rc<dyn CustomStyle>) {
|
||||||
self.custom_styles.insert(style.name().into(), style);
|
self.custom_styles.insert(style.name().into(), style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Deref for CustomStyleHolder {
|
||||||
|
type Target = HashMap<String, Rc<dyn CustomStyle>>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.custom_styles
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,23 +1,11 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::ops::Range;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use ariadne::Label;
|
|
||||||
use ariadne::Report;
|
|
||||||
|
|
||||||
use crate::document::document::Document;
|
use crate::document::document::Document;
|
||||||
use crate::document::document::DocumentAccessors;
|
|
||||||
use crate::document::element::ContainerElement;
|
|
||||||
use crate::document::element::DocumentEnd;
|
use crate::document::element::DocumentEnd;
|
||||||
use crate::document::element::ElemKind;
|
|
||||||
use crate::document::element::Element;
|
|
||||||
use crate::document::langdocument::LangDocument;
|
use crate::document::langdocument::LangDocument;
|
||||||
use crate::elements::paragraph::Paragraph;
|
|
||||||
use crate::elements::registrar::register;
|
use crate::elements::registrar::register;
|
||||||
use crate::elements::text::Text;
|
use crate::elements::text::Text;
|
||||||
use crate::parser::source::SourceFile;
|
|
||||||
use crate::parser::source::VirtualSource;
|
|
||||||
|
|
||||||
use super::parser::Parser;
|
use super::parser::Parser;
|
||||||
use super::parser::ParserState;
|
use super::parser::ParserState;
|
||||||
|
@ -44,17 +32,11 @@ impl LangParser {
|
||||||
rules: vec![],
|
rules: vec![],
|
||||||
colors: ReportColors::with_colors(),
|
colors: ReportColors::with_colors(),
|
||||||
err_flag: RefCell::new(false),
|
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
|
s
|
||||||
}
|
}
|
||||||
|
@ -64,6 +46,7 @@ impl Parser for LangParser {
|
||||||
fn colors(&self) -> &ReportColors { &self.colors }
|
fn colors(&self) -> &ReportColors { &self.colors }
|
||||||
|
|
||||||
fn rules(&self) -> &Vec<Box<dyn Rule>> { &self.rules }
|
fn rules(&self) -> &Vec<Box<dyn Rule>> { &self.rules }
|
||||||
|
fn rules_mut(&mut self) -> &mut Vec<Box<dyn Rule>> { &mut self.rules }
|
||||||
|
|
||||||
fn has_error(&self) -> bool { *self.err_flag.borrow() }
|
fn has_error(&self) -> bool { *self.err_flag.borrow() }
|
||||||
|
|
||||||
|
@ -81,11 +64,11 @@ impl Parser for LangParser {
|
||||||
if let Some(parent) = parent
|
if let Some(parent) = parent
|
||||||
// Terminate parent's paragraph state
|
// Terminate parent's paragraph state
|
||||||
{
|
{
|
||||||
Parser::handle_reports(&self,
|
self.handle_reports(state.shared.rule_state.borrow_mut().on_scope_end(
|
||||||
parent.source(),
|
&state,
|
||||||
state.shared.rule_state
|
parent,
|
||||||
.on_scope_end(self, parent, super::state::Scope::PARAGRAPH),
|
super::state::Scope::PARAGRAPH,
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -95,7 +78,7 @@ impl Parser for LangParser {
|
||||||
let text_content =
|
let text_content =
|
||||||
util::process_text(&doc, &content.as_str()[cursor.pos..rule_pos.pos]);
|
util::process_text(&doc, &content.as_str()[cursor.pos..rule_pos.pos]);
|
||||||
if !text_content.is_empty() {
|
if !text_content.is_empty() {
|
||||||
self.push(
|
state.push(
|
||||||
&doc,
|
&doc,
|
||||||
Box::new(Text::new(
|
Box::new(Text::new(
|
||||||
Token::new(cursor.pos..rule_pos.pos, source.clone()),
|
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() {
|
if let Some((rule_index, match_data)) = result.take() {
|
||||||
// Rule callback
|
// Rule callback
|
||||||
let dd: &'a dyn Document = unsafe { std::mem::transmute(&doc as &dyn Document) };
|
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
|
// Advance
|
||||||
cursor = new_cursor;
|
cursor = new_cursor;
|
||||||
|
@ -120,14 +104,15 @@ impl Parser for LangParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// State
|
// Rule States
|
||||||
self.handle_reports(
|
|
||||||
doc.source(),
|
|
||||||
state.shared.rule_state
|
|
||||||
.on_scope_end(&mut state, &doc, super::state::Scope::DOCUMENT),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.push(
|
self.handle_reports(state.shared.rule_state.borrow_mut().on_scope_end(
|
||||||
|
&state,
|
||||||
|
&doc,
|
||||||
|
super::state::Scope::DOCUMENT,
|
||||||
|
));
|
||||||
|
|
||||||
|
state.push(
|
||||||
&doc,
|
&doc,
|
||||||
Box::new(DocumentEnd(Token::new(
|
Box::new(DocumentEnd(Token::new(
|
||||||
doc.source().content().len()..doc.source().content().len(),
|
doc.source().content().len()..doc.source().content().len(),
|
||||||
|
@ -138,7 +123,12 @@ impl Parser for LangParser {
|
||||||
return Box::new(doc);
|
return Box::new(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_into<'a>(&self, state: mut ParserState, source: Rc<dyn Source>, document: &'a dyn Document<'a>) {
|
fn parse_into<'a>(
|
||||||
|
&self,
|
||||||
|
state: ParserState,
|
||||||
|
source: Rc<dyn Source>,
|
||||||
|
document: &'a dyn Document<'a>,
|
||||||
|
) {
|
||||||
let content = source.content();
|
let content = source.content();
|
||||||
let mut cursor = Cursor::new(0usize, source.clone());
|
let mut cursor = Cursor::new(0usize, source.clone());
|
||||||
|
|
||||||
|
@ -149,7 +139,7 @@ impl Parser for LangParser {
|
||||||
let text_content =
|
let text_content =
|
||||||
util::process_text(document, &content.as_str()[cursor.pos..rule_pos.pos]);
|
util::process_text(document, &content.as_str()[cursor.pos..rule_pos.pos]);
|
||||||
if !text_content.is_empty() {
|
if !text_content.is_empty() {
|
||||||
self.push(
|
state.push(
|
||||||
document,
|
document,
|
||||||
Box::new(Text::new(
|
Box::new(Text::new(
|
||||||
Token::new(cursor.pos..rule_pos.pos, source.clone()),
|
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() {
|
if let Some((rule_index, match_data)) = result.take() {
|
||||||
// Rule callback
|
// 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
|
// Advance
|
||||||
cursor = new_cursor;
|
cursor = new_cursor;
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::cell::Ref;
|
|
||||||
use std::cell::RefMut;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -41,7 +39,7 @@ impl LayoutHolder {
|
||||||
self.layouts.get(layout_name).map(|layout| layout.clone())
|
self.layouts.get(layout_name).map(|layout| layout.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&self, layout: Rc<dyn LayoutType>) {
|
pub fn insert(&mut self, layout: Rc<dyn LayoutType>) {
|
||||||
self.layouts.insert(layout.name().into(), layout);
|
self.layouts.insert(layout.name().into(), layout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::cell::RefCell;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use ariadne::Label;
|
||||||
use ariadne::Report;
|
use ariadne::Report;
|
||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@ use crate::elements::paragraph::Paragraph;
|
||||||
use crate::lua::kernel::Kernel;
|
use crate::lua::kernel::Kernel;
|
||||||
use crate::lua::kernel::KernelHolder;
|
use crate::lua::kernel::KernelHolder;
|
||||||
use crate::parser::source::SourceFile;
|
use crate::parser::source::SourceFile;
|
||||||
|
use crate::parser::source::VirtualSource;
|
||||||
use ariadne::Color;
|
use ariadne::Color;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -55,39 +57,39 @@ impl ReportColors {
|
||||||
|
|
||||||
/// The state that is shared with the state's children
|
/// The state that is shared with the state's children
|
||||||
pub struct SharedState {
|
pub struct SharedState {
|
||||||
pub rule_state: RuleStateHolder,
|
pub rule_state: RefCell<RuleStateHolder>,
|
||||||
|
|
||||||
/// The lua [`Kernel`]s
|
/// The lua [`Kernel`]s
|
||||||
pub kernels: KernelHolder,
|
pub kernels: RefCell<KernelHolder>,
|
||||||
|
|
||||||
/// The styles
|
/// The styles
|
||||||
pub styles: StyleHolder,
|
pub styles: RefCell<StyleHolder>,
|
||||||
|
|
||||||
/// The layouts
|
/// The layouts
|
||||||
pub layouts: LayoutHolder,
|
pub layouts: RefCell<LayoutHolder>,
|
||||||
|
|
||||||
/// The custom styles
|
/// The custom styles
|
||||||
pub custom_styles: CustomStyleHolder,
|
pub custom_styles: RefCell<CustomStyleHolder>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SharedState {
|
impl SharedState {
|
||||||
/// Construct a new empty shared state
|
/// Construct a new empty shared state
|
||||||
pub(self) fn new(parser: &dyn Parser) -> Self {
|
pub(self) fn new(parser: &dyn Parser) -> Self {
|
||||||
let mut s = Self {
|
let s = Self {
|
||||||
rule_state: RuleStateHolder::default(),
|
rule_state: RefCell::new(RuleStateHolder::default()),
|
||||||
kernels: KernelHolder::default(),
|
kernels: RefCell::new(KernelHolder::default()),
|
||||||
styles: StyleHolder::default(),
|
styles: RefCell::new(StyleHolder::default()),
|
||||||
layouts: LayoutHolder::default(),
|
layouts: RefCell::new(LayoutHolder::default()),
|
||||||
custom_styles: CustomStyleHolder::default(),
|
custom_styles: RefCell::new(CustomStyleHolder::default()),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Register default kernel
|
// Register default kernel
|
||||||
s.kernels
|
s.kernels.borrow_mut()
|
||||||
.insert("main".to_string(), Kernel::new(parser));
|
.insert("main".to_string(), Kernel::new(parser));
|
||||||
|
|
||||||
parser.rules().iter().for_each(|rule| {
|
parser.rules().iter().for_each(|rule| {
|
||||||
rule.register_styles(&mut s.styles);
|
rule.register_styles(&mut *s.styles.borrow_mut());
|
||||||
rule.register_layouts(&mut s.layouts);
|
rule.register_layouts(&mut *s.layouts.borrow_mut());
|
||||||
});
|
});
|
||||||
|
|
||||||
s
|
s
|
||||||
|
@ -106,9 +108,13 @@ pub struct ParserState<'a, 'b> {
|
||||||
matches: RefCell<Vec<(usize, Option<Box<dyn Any>>)>>,
|
matches: RefCell<Vec<(usize, Option<Box<dyn Any>>)>>,
|
||||||
|
|
||||||
/// State shared among all states
|
/// State shared among all states
|
||||||
pub shared: Rc<RefCell<SharedState>>,
|
pub shared: Rc<SharedState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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> {
|
impl<'a, 'b> ParserState<'a, 'b> {
|
||||||
/// Constructs a new state for a given parser with an optional parent
|
/// 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 {
|
let shared = if let Some(parent) = &parent {
|
||||||
parent.shared.clone()
|
parent.shared.clone()
|
||||||
} else {
|
} else {
|
||||||
Rc::new(RefCell::new(SharedState::new(parser)))
|
Rc::new(SharedState::new(parser))
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
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
|
/// Note: When parsing a new document, create a new state, then the parsing process
|
||||||
///
|
|
||||||
/// # 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<dyn Rule>,
|
|
||||||
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
|
|
||||||
/// creates states using this method
|
/// creates states using this method
|
||||||
pub fn with_state<F, R>(&self, f: F) -> R
|
pub fn with_state<F, R>(&self, f: F) -> R
|
||||||
where
|
where
|
||||||
|
@ -211,63 +150,6 @@ impl<'a, 'b> ParserState<'a, 'b> {
|
||||||
f(new_state)
|
f(new_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_reports(
|
|
||||||
&self,
|
|
||||||
source: Rc<dyn Source>,
|
|
||||||
reports: Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>,
|
|
||||||
) {
|
|
||||||
for mut report in reports {
|
|
||||||
let mut sources: HashSet<Rc<dyn Source>> = HashSet::new();
|
|
||||||
fn recurse_source(sources: &mut HashSet<Rc<dyn Source>>, source: Rc<dyn Source>) {
|
|
||||||
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::<Vec<(Rc<dyn Source>, String)>>();
|
|
||||||
|
|
||||||
cache.iter().for_each(|(source, _)| {
|
|
||||||
if let Some(location) = source.location() {
|
|
||||||
if let Some(_s) = source.downcast_ref::<SourceFile>() {
|
|
||||||
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::<VirtualSource>() {
|
|
||||||
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`]
|
/// Updates matches from a given start position e.g [`Cursor`]
|
||||||
///
|
///
|
||||||
/// # Return
|
/// # Return
|
||||||
|
@ -341,12 +223,11 @@ impl<'a, 'b> ParserState<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (cursor.at(next_pos),
|
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`]
|
/// Add an [`Element`] to the [`Document`]
|
||||||
fn push(&mut self, doc: &dyn Document, elem: Box<dyn Element>) {
|
pub fn push(&self, doc: &dyn Document, elem: Box<dyn Element>) {
|
||||||
if elem.kind() == ElemKind::Inline || elem.kind() == ElemKind::Invisible {
|
if elem.kind() == ElemKind::Inline || elem.kind() == ElemKind::Invisible {
|
||||||
let mut paragraph = doc
|
let mut paragraph = doc
|
||||||
.last_element_mut::<Paragraph>()
|
.last_element_mut::<Paragraph>()
|
||||||
|
@ -363,10 +244,9 @@ impl<'a, 'b> ParserState<'a, 'b> {
|
||||||
} else {
|
} else {
|
||||||
// Process paragraph events
|
// Process paragraph events
|
||||||
if doc.last_element::<Paragraph>().is_some_and(|_| true) {
|
if doc.last_element::<Paragraph>().is_some_and(|_| true) {
|
||||||
self.handle_reports(
|
self.parser.handle_reports(
|
||||||
doc.source(),
|
self.shared.rule_state.borrow_mut()
|
||||||
self.shared.rule_state
|
.on_scope_end(&self, doc, super::state::Scope::PARAGRAPH),
|
||||||
.on_scope_end(&mut self, doc, super::state::Scope::PARAGRAPH),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,9 +269,6 @@ pub trait Parser {
|
||||||
/// Whether the parser emitted an error during it's parsing process
|
/// Whether the parser emitted an error during it's parsing process
|
||||||
fn has_error(&self) -> bool;
|
fn has_error(&self) -> bool;
|
||||||
|
|
||||||
/// Add an [`Element`] to the [`Document`]
|
|
||||||
fn push<'a>(&self, doc: &dyn Document, elem: Box<dyn Element>);
|
|
||||||
|
|
||||||
/// Parse [`Source`] into a new [`Document`]
|
/// Parse [`Source`] into a new [`Document`]
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
|
@ -453,4 +330,60 @@ pub trait Parser {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_reports(
|
||||||
|
&self,
|
||||||
|
reports: Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>,
|
||||||
|
) {
|
||||||
|
for mut report in reports {
|
||||||
|
let mut sources: HashSet<Rc<dyn Source>> = HashSet::new();
|
||||||
|
fn recurse_source(sources: &mut HashSet<Rc<dyn Source>>, source: Rc<dyn Source>) {
|
||||||
|
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::<Vec<(Rc<dyn Source>, String)>>();
|
||||||
|
|
||||||
|
cache.iter().for_each(|(source, _)| {
|
||||||
|
if let Some(location) = source.location() {
|
||||||
|
if let Some(_s) = source.downcast_ref::<SourceFile>() {
|
||||||
|
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::<VirtualSource>() {
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use super::layout::LayoutHolder;
|
use super::layout::LayoutHolder;
|
||||||
use super::parser::Parser;
|
|
||||||
use super::parser::ParserState;
|
use super::parser::ParserState;
|
||||||
use super::source::Cursor;
|
use super::source::Cursor;
|
||||||
use super::source::Source;
|
use super::source::Source;
|
||||||
|
@ -24,20 +23,20 @@ pub trait Rule: Downcast {
|
||||||
/// Callback when rule matches
|
/// Callback when rule matches
|
||||||
fn on_match<'a>(
|
fn on_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a (dyn Document<'a> + 'a),
|
document: &'a (dyn Document<'a> + 'a),
|
||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
match_data: Box<dyn Any>,
|
match_data: Box<dyn Any>,
|
||||||
) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>);
|
) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>);
|
||||||
|
|
||||||
/// Registers lua bindings
|
/// 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
|
/// Registers default styles
|
||||||
fn register_styles(&self, holder: &mut StyleHolder) {}
|
fn register_styles(&self, _holder: &mut StyleHolder) {}
|
||||||
|
|
||||||
/// Registers default layouts
|
/// Registers default layouts
|
||||||
fn register_layouts(&self, holder: &mut LayoutHolder) {}
|
fn register_layouts(&self, _holder: &mut LayoutHolder) {}
|
||||||
}
|
}
|
||||||
impl_downcast!(Rule);
|
impl_downcast!(Rule);
|
||||||
|
|
||||||
|
@ -57,7 +56,7 @@ pub trait RegexRule {
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
index: usize,
|
index: usize,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a (dyn Document<'a> + 'a),
|
document: &'a (dyn Document<'a> + 'a),
|
||||||
token: Token,
|
token: Token,
|
||||||
matches: regex::Captures,
|
matches: regex::Captures,
|
||||||
|
@ -94,7 +93,7 @@ impl<T: RegexRule + 'static> Rule for T {
|
||||||
|
|
||||||
fn on_match<'a>(
|
fn on_match<'a>(
|
||||||
&self,
|
&self,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &'a (dyn Document<'a> + 'a),
|
document: &'a (dyn Document<'a> + 'a),
|
||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
match_data: Box<dyn Any>,
|
match_data: Box<dyn Any>,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -31,7 +32,7 @@ pub trait RuleState: Downcast {
|
||||||
/// Callback called when state goes out of scope
|
/// Callback called when state goes out of scope
|
||||||
fn on_remove<'a>(
|
fn on_remove<'a>(
|
||||||
&self,
|
&self,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &dyn Document,
|
document: &dyn Document,
|
||||||
) -> Vec<Report<'a, (Rc<dyn Source>, Range<usize>)>>;
|
) -> Vec<Report<'a, (Rc<dyn Source>, Range<usize>)>>;
|
||||||
}
|
}
|
||||||
|
@ -46,35 +47,38 @@ impl core::fmt::Debug for dyn RuleState {
|
||||||
/// Object owning all the states
|
/// Object owning all the states
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct RuleStateHolder {
|
pub struct RuleStateHolder {
|
||||||
states: HashMap<String, Rc<dyn RuleState>>,
|
states: HashMap<String, Rc<RefCell<dyn RuleState>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RuleStateHolder {
|
impl RuleStateHolder {
|
||||||
// Attempts to push [`state`]. On collision, returns an error with the already present state
|
|
||||||
pub fn insert(
|
pub fn insert(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: String,
|
name: String,
|
||||||
state: Rc<dyn RuleState>,
|
state: Rc<RefCell<dyn RuleState>>,
|
||||||
) {
|
) -> Result<Rc<RefCell<dyn RuleState>>, String> {
|
||||||
|
if self.states.contains_key(name.as_str()) {
|
||||||
|
return Err(format!("Attempted to insert duplicate RuleState: {name}"));
|
||||||
|
}
|
||||||
self.states.insert(name, state.clone());
|
self.states.insert(name, state.clone());
|
||||||
|
Ok(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, state_name: &str) -> Option<Rc<dyn RuleState>> {
|
pub fn get(&self, state_name: &str) -> Option<Rc<RefCell<dyn RuleState>>> {
|
||||||
self.states.get(state_name)
|
self.states.get(state_name).map(|state| state.clone())
|
||||||
.map(|state| state.clone())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_scope_end(
|
pub fn on_scope_end(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut ParserState,
|
state: &ParserState,
|
||||||
document: &dyn Document,
|
document: &dyn Document,
|
||||||
scope: Scope,
|
scope: Scope,
|
||||||
) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
||||||
let mut reports = vec![];
|
let mut reports = vec![];
|
||||||
|
|
||||||
self.states.retain(|_name, rule_state| {
|
self.states.retain(|_name, rule_state| {
|
||||||
if rule_state.scope() >= scope {
|
if rule_state.borrow().scope() >= scope {
|
||||||
rule_state
|
rule_state
|
||||||
|
.borrow_mut()
|
||||||
.on_remove(state, document)
|
.on_remove(state, document)
|
||||||
.drain(..)
|
.drain(..)
|
||||||
.for_each(|report| reports.push(report));
|
.for_each(|report| reports.push(report));
|
||||||
|
|
|
@ -32,17 +32,17 @@ pub struct StyleHolder {
|
||||||
|
|
||||||
impl StyleHolder {
|
impl StyleHolder {
|
||||||
/// Checks if a given style key is registered
|
/// 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
|
/// Gets the current active style for an element
|
||||||
/// NOTE: Will panic if a style is not defined for a given element
|
/// NOTE: Will panic if a style is not defined for a given element
|
||||||
/// If you need to process user input, use [`is_registered`]
|
/// If you need to process user input, use [`is_registered`]
|
||||||
fn current(&self, style_key: &str) -> Rc<dyn ElementStyle> {
|
pub fn current(&self, style_key: &str) -> Rc<dyn ElementStyle> {
|
||||||
self.styles.get(style_key).map(|rc| rc.clone()).unwrap()
|
self.styles.get(style_key).map(|rc| rc.clone()).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the [`style`]
|
/// Sets the [`style`]
|
||||||
fn set_current(&mut self, style: Rc<dyn ElementStyle>) {
|
pub fn set_current(&mut self, style: Rc<dyn ElementStyle>) {
|
||||||
self.styles.insert(style.key().to_string(), style);
|
self.styles.insert(style.key().to_string(), style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,7 +141,9 @@ pub fn parse_paragraph<'a>(
|
||||||
document: &'a dyn Document<'a>,
|
document: &'a dyn Document<'a>,
|
||||||
) -> Result<Box<Paragraph>, &'static str> {
|
) -> Result<Box<Paragraph>, &'static str> {
|
||||||
let parsed = state.with_state(|new_state| -> Box<dyn Document> {
|
let parsed = state.with_state(|new_state| -> Box<dyn Document> {
|
||||||
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 {
|
if parsed.content().borrow().len() > 1 {
|
||||||
return Err("Parsed document contains more than a single paragraph");
|
return Err("Parsed document contains more than a single paragraph");
|
||||||
|
|
Loading…
Reference in a new issue