Fix bugs
This commit is contained in:
parent
7f1229b5fe
commit
d4c8e1c897
30 changed files with 552 additions and 177 deletions
|
@ -7,6 +7,7 @@ use rusqlite::Connection;
|
|||
|
||||
use crate::document::document::Document;
|
||||
use crate::parser::langparser::LangParser;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::Parser;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::source::Source;
|
||||
|
@ -25,7 +26,7 @@ fn parse(
|
|||
) -> Result<Box<dyn Document<'static>>, String> {
|
||||
// Parse
|
||||
//let source = SourceFile::new(input.to_string(), None).unwrap();
|
||||
let (doc, _) = parser.parse(ParserState::new(parser, None), source.clone(), None);
|
||||
let (doc, _) = parser.parse(ParserState::new(parser, None), source.clone(), None, ParseMode::default());
|
||||
|
||||
if debug_opts.contains(&"ast".to_string()) {
|
||||
println!("-- BEGIN AST DEBUGGING --");
|
||||
|
|
|
@ -43,9 +43,10 @@ pub mod tests {
|
|||
|
||||
use super::*;
|
||||
use crate::parser::langparser::LangParser;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::Parser;
|
||||
use crate::parser::source::SourceFile;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::source::SourceFile;
|
||||
|
||||
#[test]
|
||||
fn validate_refname_tests() {
|
||||
|
@ -55,7 +56,12 @@ pub mod tests {
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
assert_eq!(validate_refname(&*doc, " abc ", true), Ok("abc"));
|
||||
assert_eq!(
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use super::document::Document;
|
||||
use crate::elements::text::Text;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::source::Source;
|
||||
use crate::parser::source::Token;
|
||||
|
@ -63,7 +64,7 @@ impl Variable for BaseVariable {
|
|||
));
|
||||
|
||||
state.with_state(|new_state| {
|
||||
let _ = new_state.parser.parse_into(new_state, source, document);
|
||||
let _ = new_state.parser.parse_into(new_state, source, document, ParseMode::default());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ use crate::document::element::ElemKind;
|
|||
use crate::document::element::Element;
|
||||
use crate::elements::paragraph::Paragraph;
|
||||
use crate::elements::text::Text;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::rule::Rule;
|
||||
use crate::parser::source::Cursor;
|
||||
|
@ -233,7 +234,15 @@ impl Rule for BlockquoteRule {
|
|||
|
||||
fn previous(&self) -> Option<&'static str> { Some("List") }
|
||||
|
||||
fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
||||
fn next_match(
|
||||
&self,
|
||||
mode: &ParseMode,
|
||||
_state: &ParserState,
|
||||
cursor: &Cursor,
|
||||
) -> Option<(usize, Box<dyn Any>)> {
|
||||
if mode.paragraph_only {
|
||||
return None;
|
||||
}
|
||||
self.start_re
|
||||
.find_at(cursor.source.content(), cursor.pos)
|
||||
.map(|m| (m.start(), Box::new([false; 0]) as Box<dyn Any>))
|
||||
|
@ -310,7 +319,7 @@ impl Rule for BlockquoteRule {
|
|||
let parsed_doc = state.with_state(|new_state| {
|
||||
new_state
|
||||
.parser
|
||||
.parse(new_state, entry_src, Some(document))
|
||||
.parse(new_state, entry_src, Some(document), ParseMode::default())
|
||||
.0
|
||||
});
|
||||
|
||||
|
@ -447,7 +456,12 @@ END
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Paragraph { Text{ content == "BEFORE" }; };
|
||||
|
@ -496,7 +510,12 @@ AFTER
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (_, state) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (_, state) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
let style = state
|
||||
.shared
|
||||
|
|
|
@ -26,6 +26,7 @@ use crate::document::element::ElemKind;
|
|||
use crate::document::element::Element;
|
||||
use crate::lsp::semantic::Semantics;
|
||||
use crate::lua::kernel::CTX;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::rule::RegexRule;
|
||||
use crate::parser::source::Source;
|
||||
|
@ -309,8 +310,7 @@ impl CodeRule {
|
|||
Regex::new(
|
||||
r"``(?:\[((?:\\.|[^\\\\])*?)\])?(?:([^\r\n`]*?)(?:,|\n))?((?:\\(?:.|\n)|[^\\\\])*?)``",
|
||||
)
|
||||
.unwrap()
|
||||
|
||||
.unwrap(),
|
||||
],
|
||||
properties: PropertyParser { properties: props },
|
||||
}
|
||||
|
@ -319,10 +319,15 @@ impl CodeRule {
|
|||
|
||||
impl RegexRule for CodeRule {
|
||||
fn name(&self) -> &'static str { "Code" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Blockquote") }
|
||||
|
||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||
|
||||
fn enabled(&self, mode: &ParseMode, id: usize) -> bool {
|
||||
return !mode.paragraph_only || id != 0;
|
||||
}
|
||||
|
||||
fn on_regex_match(
|
||||
&self,
|
||||
index: usize,
|
||||
|
@ -710,7 +715,12 @@ fn fact(n: usize) -> usize
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
let borrow = doc.content().borrow();
|
||||
let found = borrow
|
||||
|
@ -756,7 +766,12 @@ fn fact(n: usize) -> usize
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
let borrow = doc.content().borrow();
|
||||
let found = borrow
|
||||
|
@ -806,6 +821,7 @@ test code
|
|||
ParserState::new_with_semantics(&parser, None),
|
||||
source.clone(),
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
validate_semantics!(state, source.clone(), 0,
|
||||
code_sep { delta_line == 1, delta_start == 0, length == 3 };
|
||||
|
|
|
@ -3,6 +3,7 @@ use crate::document::document::Document;
|
|||
use crate::document::element::ElemKind;
|
||||
use crate::document::element::Element;
|
||||
use crate::lsp::semantic::Semantics;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::rule::RegexRule;
|
||||
use crate::parser::source::Source;
|
||||
|
@ -56,6 +57,8 @@ impl RegexRule for CommentRule {
|
|||
|
||||
fn regexes(&self) -> &[Regex] { &self.re }
|
||||
|
||||
fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true }
|
||||
|
||||
fn on_regex_match(
|
||||
&self,
|
||||
_: usize,
|
||||
|
@ -132,7 +135,12 @@ COMMENT ::Test
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Paragraph {
|
||||
|
@ -160,6 +168,7 @@ COMMENT ::Test
|
|||
ParserState::new_with_semantics(&parser, None),
|
||||
source.clone(),
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_semantics!(state, source.clone(), 0,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::lua::kernel::Kernel;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use std::any::Any;
|
||||
use std::cell::Ref;
|
||||
use std::cell::RefCell;
|
||||
|
@ -140,10 +141,13 @@ impl RuleState for CustomStyleState {
|
|||
let paragraph = document.last_element::<Paragraph>().unwrap();
|
||||
let paragraph_end = paragraph
|
||||
.content
|
||||
.last().map(|last| (
|
||||
.last()
|
||||
.map(|last| {
|
||||
(
|
||||
last.location().source(),
|
||||
last.location().end() - 1..last.location().end(),
|
||||
))
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
reports.push(
|
||||
|
@ -179,14 +183,20 @@ static STATE_NAME: &str = "elements.custom_style";
|
|||
pub struct CustomStyleRule;
|
||||
|
||||
impl CustomStyleRule {
|
||||
pub fn new() -> Self { Self{} }
|
||||
pub fn new() -> Self { Self {} }
|
||||
}
|
||||
|
||||
impl Rule for CustomStyleRule {
|
||||
fn name(&self) -> &'static str { "Custom Style" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Style") }
|
||||
|
||||
fn next_match(&self, state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
||||
fn next_match(
|
||||
&self,
|
||||
_mode: &ParseMode,
|
||||
state: &ParserState,
|
||||
cursor: &Cursor,
|
||||
) -> Option<(usize, Box<dyn Any>)> {
|
||||
let content = cursor.source.content();
|
||||
|
||||
let mut closest_match = usize::MAX;
|
||||
|
@ -479,6 +489,7 @@ mod tests {
|
|||
use crate::elements::raw::Raw;
|
||||
use crate::elements::text::Text;
|
||||
use crate::parser::langparser::LangParser;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::Parser;
|
||||
use crate::parser::source::SourceFile;
|
||||
use crate::validate_document;
|
||||
|
@ -512,7 +523,12 @@ pre |styled| post °Hello°.
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Paragraph {
|
||||
|
@ -556,7 +572,12 @@ pre [styled] post (Hello).
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Paragraph {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::style::ElementStyle;
|
||||
use std::any::Any;
|
||||
use std::ops::Range;
|
||||
|
@ -59,11 +60,18 @@ impl ElemStyleRule {
|
|||
|
||||
impl Rule for ElemStyleRule {
|
||||
fn name(&self) -> &'static str { "Element Style" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Script") }
|
||||
|
||||
fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
||||
fn next_match(
|
||||
&self,
|
||||
_mode: &ParseMode,
|
||||
_state: &ParserState,
|
||||
cursor: &Cursor,
|
||||
) -> Option<(usize, Box<dyn Any>)> {
|
||||
self.start_re
|
||||
.find_at(cursor.source.content(), cursor.pos).map(|m| (m.start(), Box::new([false; 0]) as Box<dyn Any>))
|
||||
.find_at(cursor.source.content(), cursor.pos)
|
||||
.map(|m| (m.start(), Box::new([false; 0]) as Box<dyn Any>))
|
||||
}
|
||||
|
||||
fn on_match<'a>(
|
||||
|
@ -132,7 +140,9 @@ impl Rule for ElemStyleRule {
|
|||
.with_message("Invalid Style Value")
|
||||
.with_label(
|
||||
Label::new((cursor.source.clone(), matches.get(0).unwrap().range()))
|
||||
.with_message("Unable to parse json string after style key".to_string())
|
||||
.with_message(
|
||||
"Unable to parse json string after style key".to_string(),
|
||||
)
|
||||
.with_color(state.parser.colors().error),
|
||||
)
|
||||
.finish(),
|
||||
|
|
|
@ -5,6 +5,7 @@ use std::sync::Arc;
|
|||
use std::sync::Once;
|
||||
|
||||
use crate::lua::kernel::CTX;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::util::Property;
|
||||
use crate::parser::util::PropertyMapError;
|
||||
|
@ -189,10 +190,13 @@ impl GraphRule {
|
|||
|
||||
impl RegexRule for GraphRule {
|
||||
fn name(&self) -> &'static str { "Graphviz" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Tex") }
|
||||
|
||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||
|
||||
fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only }
|
||||
|
||||
fn on_regex_match(
|
||||
&self,
|
||||
_: usize,
|
||||
|
@ -441,7 +445,12 @@ Another graph
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Graphviz { width == "200px", dot == "Some graph..." };
|
||||
|
@ -461,7 +470,12 @@ Another graph
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Graphviz { width == "200px", dot == "Some graph..." };
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::document::document::Document;
|
||||
use crate::document::document::DocumentAccessors;
|
||||
use crate::lsp::semantic::Semantics;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::parser::ReportColors;
|
||||
use crate::parser::rule::RegexRule;
|
||||
|
@ -43,10 +44,13 @@ impl ImportRule {
|
|||
|
||||
impl RegexRule for ImportRule {
|
||||
fn name(&self) -> &'static str { "Import" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Paragraph") }
|
||||
|
||||
fn regexes(&self) -> &[Regex] { &self.re }
|
||||
|
||||
fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only }
|
||||
|
||||
fn on_regex_match<'a>(
|
||||
&self,
|
||||
_: usize,
|
||||
|
@ -165,7 +169,10 @@ impl RegexRule for ImportRule {
|
|||
};
|
||||
|
||||
state.with_state(|new_state| {
|
||||
let (import_doc, _) = new_state.parser.parse(new_state, import, Some(document));
|
||||
let (import_doc, _) =
|
||||
new_state
|
||||
.parser
|
||||
.parse(new_state, import, Some(document), ParseMode::default());
|
||||
document.merge(import_doc.content(), import_doc.scope(), Some(&import_as));
|
||||
});
|
||||
|
||||
|
@ -181,25 +188,25 @@ impl RegexRule for ImportRule {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
if let Some((sems, tokens)) = Semantics::from_source(token.source(), &state.shared.semantics)
|
||||
if let Some((sems, tokens)) =
|
||||
Semantics::from_source(token.source(), &state.shared.semantics)
|
||||
{
|
||||
// @import
|
||||
let import = if token.source().content().as_bytes()[matches.get(0).unwrap().start()] == b'\n'
|
||||
{
|
||||
matches.get(0).unwrap().start() + 1
|
||||
}
|
||||
else
|
||||
{
|
||||
matches.get(0).unwrap().start()
|
||||
};
|
||||
let import =
|
||||
if token.source().content().as_bytes()[matches.get(0).unwrap().start()] == b'\n' {
|
||||
matches.get(0).unwrap().start() + 1
|
||||
} else {
|
||||
matches.get(0).unwrap().start()
|
||||
};
|
||||
sems.add(import..import + 7, tokens.import_import);
|
||||
|
||||
if let Some(import_as) = matches.get(1)
|
||||
{
|
||||
sems.add(import_as.start()-1..import_as.start(), tokens.import_as_sep);
|
||||
if let Some(import_as) = matches.get(1) {
|
||||
sems.add(
|
||||
import_as.start() - 1..import_as.start(),
|
||||
tokens.import_as_sep,
|
||||
);
|
||||
sems.add(import_as.range(), tokens.import_as);
|
||||
sems.add(import_as.end()..import_as.end()+1, tokens.import_as_sep);
|
||||
sems.add(import_as.end()..import_as.end() + 1, tokens.import_as_sep);
|
||||
}
|
||||
|
||||
let path = matches.get(2).unwrap().range();
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::document::element::Element;
|
|||
use crate::lua::kernel::CTX;
|
||||
use crate::parser::layout::LayoutHolder;
|
||||
use crate::parser::layout::LayoutType;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::parser::ReportColors;
|
||||
use crate::parser::rule::RegexRule;
|
||||
|
@ -232,7 +233,12 @@ impl Element for Layout {
|
|||
fn location(&self) -> &Token { &self.location }
|
||||
fn kind(&self) -> ElemKind { ElemKind::Block }
|
||||
fn element_name(&self) -> &'static str { "Layout" }
|
||||
fn compile(&self, compiler: &Compiler, document: &dyn Document, _cursor: usize) -> Result<String, String> {
|
||||
fn compile(
|
||||
&self,
|
||||
compiler: &Compiler,
|
||||
document: &dyn Document,
|
||||
_cursor: usize,
|
||||
) -> Result<String, String> {
|
||||
self.layout
|
||||
.compile(self.token, self.id, &self.properties, compiler, document)
|
||||
}
|
||||
|
@ -379,10 +385,13 @@ static STATE_NAME: &str = "elements.layout";
|
|||
|
||||
impl RegexRule for LayoutRule {
|
||||
fn name(&self) -> &'static str { "Layout" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Media") }
|
||||
|
||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||
|
||||
fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only }
|
||||
|
||||
fn on_regex_match(
|
||||
&self,
|
||||
index: usize,
|
||||
|
@ -897,7 +906,12 @@ mod tests {
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Layout { token == LayoutToken::Begin, id == 0 };
|
||||
|
@ -949,7 +963,12 @@ mod tests {
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Layout { token == LayoutToken::Begin, id == 0 };
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::document::element::ElemKind;
|
|||
use crate::document::element::Element;
|
||||
use crate::lsp::semantic::Semantics;
|
||||
use crate::lua::kernel::CTX;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::rule::RegexRule;
|
||||
use crate::parser::source::Source;
|
||||
|
@ -94,10 +95,13 @@ impl LinkRule {
|
|||
|
||||
impl RegexRule for LinkRule {
|
||||
fn name(&self) -> &'static str { "Link" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Link") }
|
||||
|
||||
fn regexes(&self) -> &[Regex] { &self.re }
|
||||
|
||||
fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true }
|
||||
|
||||
fn on_regex_match<'a>(
|
||||
&self,
|
||||
_: usize,
|
||||
|
@ -314,7 +318,12 @@ Some [link](url).
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Paragraph {
|
||||
|
@ -344,7 +353,12 @@ nml.link.push("**BOLD link**", "another url")
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Paragraph {
|
||||
|
@ -375,6 +389,7 @@ nml.link.push("**BOLD link**", "another url")
|
|||
ParserState::new_with_semantics(&parser, None),
|
||||
source.clone(),
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_semantics!(state, source.clone(), 0,
|
||||
|
|
|
@ -12,6 +12,7 @@ use crate::document::element::ContainerElement;
|
|||
use crate::document::element::ElemKind;
|
||||
use crate::document::element::Element;
|
||||
use crate::lsp::semantic::Semantics;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::rule::Rule;
|
||||
use crate::parser::source::Cursor;
|
||||
|
@ -269,9 +270,18 @@ impl ListRule {
|
|||
|
||||
impl Rule for ListRule {
|
||||
fn name(&self) -> &'static str { "List" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Raw") }
|
||||
|
||||
fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
||||
fn next_match(
|
||||
&self,
|
||||
mode: &ParseMode,
|
||||
_state: &ParserState,
|
||||
cursor: &Cursor,
|
||||
) -> Option<(usize, Box<dyn Any>)> {
|
||||
if mode.paragraph_only {
|
||||
return None;
|
||||
}
|
||||
self.start_re
|
||||
.find_at(cursor.source.content(), cursor.pos)
|
||||
.map(|m| (m.start(), Box::new([false; 0]) as Box<dyn Any>))
|
||||
|
@ -406,6 +416,7 @@ impl Rule for ListRule {
|
|||
|
||||
// Parse entry content
|
||||
let token = Token::new(entry_start..end_cursor.pos, end_cursor.source.clone());
|
||||
//println!("content={}", entry_content);
|
||||
let entry_src = Rc::new(VirtualSource::new(
|
||||
token.clone(),
|
||||
"List Entry".to_string(),
|
||||
|
@ -475,7 +486,8 @@ mod tests {
|
|||
use crate::parser::langparser::LangParser;
|
||||
use crate::parser::parser::Parser;
|
||||
use crate::parser::source::SourceFile;
|
||||
use crate::{validate_document, validate_semantics};
|
||||
use crate::validate_document;
|
||||
use crate::validate_semantics;
|
||||
|
||||
#[test]
|
||||
fn parser() {
|
||||
|
@ -498,7 +510,7 @@ mod tests {
|
|||
));
|
||||
let parser = LangParser::default();
|
||||
let state = ParserState::new(&parser, None);
|
||||
let (doc, _) = parser.parse(state, source, None);
|
||||
let (doc, _) = parser.parse(state, source, None, ParseMode::default());
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
ListMarker { numbered == false, kind == MarkerKind::Open };
|
||||
|
@ -549,7 +561,8 @@ mod tests {
|
|||
*[offset=5] First **bold**
|
||||
Second line
|
||||
*- Another
|
||||
>@
|
||||
|
||||
|
||||
"#
|
||||
.to_string(),
|
||||
None,
|
||||
|
@ -559,6 +572,7 @@ mod tests {
|
|||
ParserState::new_with_semantics(&parser, None),
|
||||
source.clone(),
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
validate_semantics!(state, source.clone(), 0,
|
||||
list_bullet { delta_line == 1, delta_start == 1, length == 1 };
|
||||
|
|
|
@ -21,6 +21,7 @@ use crate::document::element::ElemKind;
|
|||
use crate::document::element::Element;
|
||||
use crate::document::element::ReferenceableElement;
|
||||
use crate::document::references::validate_refname;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::parser::ReportColors;
|
||||
use crate::parser::rule::RegexRule;
|
||||
|
@ -72,14 +73,21 @@ impl Element for Media {
|
|||
|
||||
fn as_container(&self) -> Option<&dyn ContainerElement> { Some(self) }
|
||||
|
||||
fn compile(&self, compiler: &Compiler, document: &dyn Document, cursor: usize) -> Result<String, String> {
|
||||
fn compile(
|
||||
&self,
|
||||
compiler: &Compiler,
|
||||
document: &dyn Document,
|
||||
cursor: usize,
|
||||
) -> Result<String, String> {
|
||||
match compiler.target() {
|
||||
Target::HTML => {
|
||||
let mut result = String::new();
|
||||
|
||||
result.push_str("<div class=\"media\">");
|
||||
for medium in &self.media {
|
||||
result += medium.compile(compiler, document, cursor+result.len())?.as_str();
|
||||
result += medium
|
||||
.compile(compiler, document, cursor + result.len())?
|
||||
.as_str();
|
||||
}
|
||||
result.push_str("</div>");
|
||||
|
||||
|
@ -132,7 +140,12 @@ impl Element for Medium {
|
|||
|
||||
fn as_referenceable(&self) -> Option<&dyn ReferenceableElement> { Some(self) }
|
||||
|
||||
fn compile(&self, compiler: &Compiler, document: &dyn Document, cursor: usize) -> Result<String, String> {
|
||||
fn compile(
|
||||
&self,
|
||||
compiler: &Compiler,
|
||||
document: &dyn Document,
|
||||
cursor: usize,
|
||||
) -> Result<String, String> {
|
||||
match compiler.target() {
|
||||
Target::HTML => {
|
||||
let mut result = String::new();
|
||||
|
@ -145,10 +158,18 @@ impl Element for Medium {
|
|||
.width
|
||||
.as_ref()
|
||||
.map_or(String::new(), |w| format!(r#" style="width:{w};""#));
|
||||
result.push_str(format!(r#"<div id="{}" class="medium"{width}>"#, self.refid(compiler, refcount)).as_str());
|
||||
result.push_str(
|
||||
format!(
|
||||
r#"<div id="{}" class="medium"{width}>"#,
|
||||
self.refid(compiler, refcount)
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
result += match self.media_type {
|
||||
MediaType::IMAGE => format!(r#"<a href="{0}"><img src="{0}"></a>"#, self.uri),
|
||||
MediaType::VIDEO => format!(r#"<video controls{width}><source src="{0}"></video>"#, self.uri
|
||||
MediaType::VIDEO => format!(
|
||||
r#"<video controls{width}><source src="{0}"></video>"#,
|
||||
self.uri
|
||||
),
|
||||
MediaType::AUDIO => {
|
||||
format!(r#"<audio controls src="{0}"{width}></audio>"#, self.uri)
|
||||
|
@ -158,17 +179,17 @@ impl Element for Medium {
|
|||
|
||||
let caption = self
|
||||
.caption
|
||||
.as_ref().map(|cap| format!(
|
||||
" {}",
|
||||
Compiler::sanitize(compiler.target(), cap.as_str())
|
||||
))
|
||||
.as_ref()
|
||||
.map(|cap| format!(" {}", Compiler::sanitize(compiler.target(), cap.as_str())))
|
||||
.unwrap_or_default();
|
||||
|
||||
result.push_str(
|
||||
format!(r#"<p class="medium-refname">({refcount}){caption}</p>"#).as_str(),
|
||||
);
|
||||
if let Some(paragraph) = self.description.as_ref() {
|
||||
result += paragraph.compile(compiler, document, cursor+result.len())?.as_str();
|
||||
result += paragraph
|
||||
.compile(compiler, document, cursor + result.len())?
|
||||
.as_str();
|
||||
}
|
||||
result.push_str("</div>");
|
||||
|
||||
|
@ -214,9 +235,7 @@ impl ReferenceableElement for Medium {
|
|||
}
|
||||
}
|
||||
|
||||
fn refid(&self, _compiler: &Compiler, refid: usize) -> String {
|
||||
format!("medium-{refid}")
|
||||
}
|
||||
fn refid(&self, _compiler: &Compiler, refid: usize) -> String { format!("medium-{refid}") }
|
||||
}
|
||||
|
||||
#[auto_registry::auto_registry(registry = "rules", path = "crate::elements::media")]
|
||||
|
@ -324,10 +343,13 @@ impl MediaRule {
|
|||
|
||||
impl RegexRule for MediaRule {
|
||||
fn name(&self) -> &'static str { "Media" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Graphviz") }
|
||||
|
||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||
|
||||
fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only }
|
||||
|
||||
fn on_regex_match<'a>(
|
||||
&self,
|
||||
_: usize,
|
||||
|
@ -433,13 +455,15 @@ impl RegexRule for MediaRule {
|
|||
.get("width", |_, value| -> Result<String, ()> {
|
||||
Ok(value.clone())
|
||||
})
|
||||
.ok().map(|(_, s)| s);
|
||||
.ok()
|
||||
.map(|(_, s)| s);
|
||||
|
||||
let caption = properties
|
||||
.get("caption", |_, value| -> Result<String, ()> {
|
||||
Ok(value.clone())
|
||||
})
|
||||
.ok().map(|(_, value)| value);
|
||||
.ok()
|
||||
.map(|(_, value)| value);
|
||||
|
||||
let description = match matches.get(4) {
|
||||
Some(content) => {
|
||||
|
@ -546,7 +570,12 @@ mod tests {
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
let borrow = doc.content().borrow();
|
||||
let group = borrow.first().as_ref().unwrap().as_container().unwrap();
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::document::document::Document;
|
|||
use crate::document::element::ContainerElement;
|
||||
use crate::document::element::ElemKind;
|
||||
use crate::document::element::Element;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::rule::Rule;
|
||||
use crate::parser::source::Cursor;
|
||||
|
@ -48,7 +49,12 @@ impl Element for Paragraph {
|
|||
|
||||
fn element_name(&self) -> &'static str { "Paragraph" }
|
||||
|
||||
fn compile(&self, compiler: &Compiler, document: &dyn Document, cursor: usize) -> Result<String, String> {
|
||||
fn compile(
|
||||
&self,
|
||||
compiler: &Compiler,
|
||||
document: &dyn Document,
|
||||
cursor: usize,
|
||||
) -> Result<String, String> {
|
||||
if self.content.is_empty() {
|
||||
return Ok(String::new());
|
||||
}
|
||||
|
@ -63,7 +69,9 @@ impl Element for Paragraph {
|
|||
result.push_str("<p>");
|
||||
|
||||
for elems in &self.content {
|
||||
result += elems.compile(compiler, document, cursor+result.len())?.as_str();
|
||||
result += elems
|
||||
.compile(compiler, document, cursor + result.len())?
|
||||
.as_str();
|
||||
}
|
||||
|
||||
result.push_str("</p>");
|
||||
|
@ -106,11 +114,18 @@ impl ParagraphRule {
|
|||
|
||||
impl Rule for ParagraphRule {
|
||||
fn name(&self) -> &'static str { "Paragraph" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Comment") }
|
||||
|
||||
fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
||||
fn next_match(
|
||||
&self,
|
||||
_mode: &ParseMode,
|
||||
_state: &ParserState,
|
||||
cursor: &Cursor,
|
||||
) -> Option<(usize, Box<dyn Any>)> {
|
||||
self.re
|
||||
.find_at(cursor.source.content(), cursor.pos).map(|m| (m.start(), Box::new([false; 0]) as Box<dyn Any>))
|
||||
.find_at(cursor.source.content(), cursor.pos)
|
||||
.map(|m| (m.start(), Box::new([false; 0]) as Box<dyn Any>))
|
||||
}
|
||||
|
||||
fn on_match(
|
||||
|
@ -166,7 +181,12 @@ Last paragraph
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Paragraph {
|
||||
|
|
|
@ -3,6 +3,7 @@ use crate::document::document::Document;
|
|||
use crate::document::element::ElemKind;
|
||||
use crate::document::element::Element;
|
||||
use crate::lua::kernel::CTX;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::rule::RegexRule;
|
||||
use crate::parser::source::Source;
|
||||
|
@ -39,7 +40,12 @@ impl Element for Raw {
|
|||
|
||||
fn element_name(&self) -> &'static str { "Raw" }
|
||||
|
||||
fn compile(&self, _compiler: &Compiler, _document: &dyn Document, _cursor: usize) -> Result<String, String> {
|
||||
fn compile(
|
||||
&self,
|
||||
_compiler: &Compiler,
|
||||
_document: &dyn Document,
|
||||
_cursor: usize,
|
||||
) -> Result<String, String> {
|
||||
Ok(self.content.clone())
|
||||
}
|
||||
}
|
||||
|
@ -73,10 +79,13 @@ impl RawRule {
|
|||
|
||||
impl RegexRule for RawRule {
|
||||
fn name(&self) -> &'static str { "Raw" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Variable Substitution") }
|
||||
|
||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||
|
||||
fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true }
|
||||
|
||||
fn on_regex_match(
|
||||
&self,
|
||||
_index: usize,
|
||||
|
@ -271,7 +280,7 @@ mod tests {
|
|||
use crate::elements::text::Text;
|
||||
use crate::parser::langparser::LangParser;
|
||||
use crate::parser::parser::Parser;
|
||||
use crate::parser::source::SourceFile;
|
||||
use crate::parser::source::SourceFile;
|
||||
use crate::validate_document;
|
||||
|
||||
#[test]
|
||||
|
@ -285,7 +294,12 @@ Break{?[kind=block] Raw?}NewParagraph{?<b>?}
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Paragraph;
|
||||
|
@ -308,7 +322,12 @@ Break%<nml.raw.push("block", "Raw")>%NewParagraph%<nml.raw.push("inline", "<b>")
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Paragraph;
|
||||
|
|
|
@ -22,6 +22,7 @@ use crate::document::element::ElemKind;
|
|||
use crate::document::element::Element;
|
||||
use crate::document::references::validate_refname;
|
||||
use crate::lsp::semantic::Semantics;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::parser::ReportColors;
|
||||
use crate::parser::rule::RegexRule;
|
||||
|
@ -227,10 +228,13 @@ impl ReferenceRule {
|
|||
|
||||
impl RegexRule for ReferenceRule {
|
||||
fn name(&self) -> &'static str { "Reference" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Text") }
|
||||
|
||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||
|
||||
fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true }
|
||||
|
||||
fn on_regex_match<'a>(
|
||||
&self,
|
||||
_: usize,
|
||||
|
@ -449,7 +453,12 @@ mod tests {
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Section;
|
||||
|
@ -476,7 +485,12 @@ mod tests {
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Paragraph {
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::document::document::Document;
|
|||
use crate::lsp::semantic::Semantics;
|
||||
use crate::lua::kernel::Kernel;
|
||||
use crate::lua::kernel::KernelContext;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::parser::ReportColors;
|
||||
use crate::parser::rule::RegexRule;
|
||||
|
@ -79,10 +80,13 @@ impl ScriptRule {
|
|||
|
||||
impl RegexRule for ScriptRule {
|
||||
fn name(&self) -> &'static str { "Script" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Import") }
|
||||
|
||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||
|
||||
fn enabled(&self, mode: &ParseMode, id: usize) -> bool { !mode.paragraph_only || id != 0 }
|
||||
|
||||
fn on_regex_match<'a>(
|
||||
&self,
|
||||
index: usize,
|
||||
|
@ -244,9 +248,12 @@ impl RegexRule for ScriptRule {
|
|||
)) as Rc<dyn Source>;
|
||||
|
||||
state.with_state(|new_state| {
|
||||
new_state
|
||||
.parser
|
||||
.parse_into(new_state, parse_source, document);
|
||||
new_state.parser.parse_into(
|
||||
new_state,
|
||||
parse_source,
|
||||
document,
|
||||
ParseMode::default(),
|
||||
);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -350,7 +357,12 @@ Evaluation: %<! make_ref("hello", "id")>%
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Paragraph;
|
||||
|
@ -393,6 +405,7 @@ end
|
|||
ParserState::new_with_semantics(&parser, None),
|
||||
source.clone(),
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
validate_semantics!(state, source.clone(), 0,
|
||||
script_sep { delta_line == 1, delta_start == 0, length == 2 };
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::document::element::Element;
|
|||
use crate::document::element::ReferenceableElement;
|
||||
use crate::lsp::semantic::Semantics;
|
||||
use crate::lua::kernel::CTX;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::rule::RegexRule;
|
||||
use crate::parser::source::Source;
|
||||
|
@ -168,10 +169,13 @@ pub mod section_kind {
|
|||
|
||||
impl RegexRule for SectionRule {
|
||||
fn name(&self) -> &'static str { "Section" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Custom Style") }
|
||||
|
||||
fn regexes(&self) -> &[Regex] { &self.re }
|
||||
|
||||
fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only }
|
||||
|
||||
fn on_regex_match(
|
||||
&self,
|
||||
_: usize,
|
||||
|
@ -327,15 +331,17 @@ impl RegexRule for SectionRule {
|
|||
}),
|
||||
);
|
||||
|
||||
if let Some((sems, tokens)) = Semantics::from_source(token.source(), &state.shared.semantics)
|
||||
if let Some((sems, tokens)) =
|
||||
Semantics::from_source(token.source(), &state.shared.semantics)
|
||||
{
|
||||
sems.add(matches.get(1).unwrap().range(), tokens.section_heading);
|
||||
if let Some(reference) = matches.get(2)
|
||||
{
|
||||
sems.add(reference.start()-1..reference.end()+1, tokens.section_reference);
|
||||
if let Some(reference) = matches.get(2) {
|
||||
sems.add(
|
||||
reference.start() - 1..reference.end() + 1,
|
||||
tokens.section_reference,
|
||||
);
|
||||
}
|
||||
if let Some(kind) = matches.get(3)
|
||||
{
|
||||
if let Some(kind) = matches.get(3) {
|
||||
sems.add(kind.range(), tokens.section_kind);
|
||||
}
|
||||
sems.add(matches.get(5).unwrap().range(), tokens.section_name);
|
||||
|
@ -452,7 +458,8 @@ mod tests {
|
|||
use crate::parser::langparser::LangParser;
|
||||
use crate::parser::parser::Parser;
|
||||
use crate::parser::source::SourceFile;
|
||||
use crate::{validate_document, validate_semantics};
|
||||
use crate::validate_document;
|
||||
use crate::validate_semantics;
|
||||
|
||||
use super::*;
|
||||
|
||||
|
@ -472,7 +479,12 @@ mod tests {
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Section { depth == 1, title == "1" };
|
||||
|
@ -502,7 +514,12 @@ nml.section.push("6", 6, "", "refname")
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Section { depth == 1, title == "1" };
|
||||
|
@ -529,7 +546,7 @@ nml.section.push("6", 6, "", "refname")
|
|||
));
|
||||
let parser = LangParser::default();
|
||||
let state = ParserState::new(&parser, None);
|
||||
let (_, state) = parser.parse(state, source, None);
|
||||
let (_, state) = parser.parse(state, source, None, ParseMode::default());
|
||||
|
||||
let style = state
|
||||
.shared
|
||||
|
@ -547,8 +564,7 @@ nml.section.push("6", 6, "", "refname")
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn semantics()
|
||||
{
|
||||
fn semantics() {
|
||||
let source = Rc::new(SourceFile::with_content(
|
||||
"".to_string(),
|
||||
r#"
|
||||
|
@ -560,21 +576,26 @@ nml.section.push("6", 6, "", "refname")
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (_, state) = parser.parse(ParserState::new_with_semantics(&parser, None), source.clone(), None);
|
||||
let (_, state) = parser.parse(
|
||||
ParserState::new_with_semantics(&parser, None),
|
||||
source.clone(),
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_semantics!(state, source.clone(), 0,
|
||||
section_heading { delta_line == 1, delta_start == 0, length == 1 };
|
||||
section_name { delta_line == 0, delta_start == 1 };
|
||||
section_heading { delta_line == 1, delta_start == 0, length == 1 };
|
||||
section_name { delta_line == 0, delta_start == 1 };
|
||||
|
||||
section_heading { delta_line == 1, delta_start == 0, length == 2 };
|
||||
section_reference { delta_line == 0, delta_start == 2, length == 4 };
|
||||
section_kind { delta_line == 0, delta_start == 4, length == 1 };
|
||||
section_name { delta_line == 0, delta_start == 1 };
|
||||
section_heading { delta_line == 1, delta_start == 0, length == 2 };
|
||||
section_reference { delta_line == 0, delta_start == 2, length == 4 };
|
||||
section_kind { delta_line == 0, delta_start == 4, length == 1 };
|
||||
section_name { delta_line == 0, delta_start == 1 };
|
||||
|
||||
section_heading { delta_line == 1, delta_start == 0, length == 1 };
|
||||
section_reference { delta_line == 0, delta_start == 1, length == 9 };
|
||||
section_kind { delta_line == 0, delta_start == 9, length == 2 };
|
||||
section_name { delta_line == 0, delta_start == 2 };
|
||||
);
|
||||
section_heading { delta_line == 1, delta_start == 0, length == 1 };
|
||||
section_reference { delta_line == 0, delta_start == 1, length == 9 };
|
||||
section_kind { delta_line == 0, delta_start == 9, length == 2 };
|
||||
section_name { delta_line == 0, delta_start == 2 };
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::document::element::ElemKind;
|
|||
use crate::document::element::Element;
|
||||
use crate::lsp::semantic::Semantics;
|
||||
use crate::lua::kernel::CTX;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::rule::RegexRule;
|
||||
use crate::parser::source::Source;
|
||||
|
@ -167,10 +168,13 @@ static STATE_NAME: &str = "elements.style";
|
|||
|
||||
impl RegexRule for StyleRule {
|
||||
fn name(&self) -> &'static str { "Style" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Layout") }
|
||||
|
||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||
|
||||
fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true }
|
||||
|
||||
fn on_regex_match(
|
||||
&self,
|
||||
index: usize,
|
||||
|
@ -316,7 +320,12 @@ __`UNDERLINE+EM`__
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Paragraph {
|
||||
|
@ -357,7 +366,12 @@ terminated here%<nml.style.toggle("Italic")>%
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Paragraph {
|
||||
|
@ -399,6 +413,7 @@ __teかst__ *another*
|
|||
ParserState::new_with_semantics(&parser, None),
|
||||
source.clone(),
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_semantics!(state, source.clone(), 0,
|
||||
|
|
|
@ -29,6 +29,7 @@ use crate::document::document::Document;
|
|||
use crate::document::element::ElemKind;
|
||||
use crate::document::element::Element;
|
||||
use crate::lua::kernel::CTX;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::parser::ReportColors;
|
||||
use crate::parser::rule::RegexRule;
|
||||
|
@ -114,7 +115,9 @@ impl FormattedTex {
|
|||
}
|
||||
|
||||
let mut result = String::new();
|
||||
if let Err(e) = process.stdout.unwrap().read_to_string(&mut result) { panic!("Unable to read `latex2svg` stdout: {}", e) }
|
||||
if let Err(e) = process.stdout.unwrap().read_to_string(&mut result) {
|
||||
panic!("Unable to read `latex2svg` stdout: {}", e)
|
||||
}
|
||||
println!("Done!");
|
||||
|
||||
Ok(result)
|
||||
|
@ -303,10 +306,13 @@ impl TexRule {
|
|||
|
||||
impl RegexRule for TexRule {
|
||||
fn name(&self) -> &'static str { "Tex" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Code") }
|
||||
|
||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||
|
||||
fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true }
|
||||
|
||||
fn on_regex_match(
|
||||
&self,
|
||||
index: usize,
|
||||
|
@ -407,14 +413,16 @@ impl RegexRule for TexRule {
|
|||
.get("caption", |_, value| -> Result<String, ()> {
|
||||
Ok(value.clone())
|
||||
})
|
||||
.ok().map(|(_, value)| value);
|
||||
.ok()
|
||||
.map(|(_, value)| value);
|
||||
|
||||
// Environ
|
||||
let tex_env = properties
|
||||
.get("env", |_, value| -> Result<String, ()> {
|
||||
Ok(value.clone())
|
||||
})
|
||||
.ok().map(|(_, value)| value)
|
||||
.ok()
|
||||
.map(|(_, value)| value)
|
||||
.unwrap();
|
||||
|
||||
state.push(
|
||||
|
@ -548,7 +556,12 @@ $[kind=block,env=another] e^{i\pi}=-1$
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Tex { mathmode == true, tex == "1+1=2", env == "main", caption == Some("Some, text\\".to_string()) };
|
||||
|
@ -576,7 +589,12 @@ $[env=another] e^{i\pi}=-1$
|
|||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
let (doc, _) = parser.parse(
|
||||
ParserState::new(&parser, None),
|
||||
source,
|
||||
None,
|
||||
ParseMode::default(),
|
||||
);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Paragraph {
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::document::document::Document;
|
|||
use crate::document::element::ElemKind;
|
||||
use crate::document::element::Element;
|
||||
use crate::lua::kernel::CTX;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::rule::Rule;
|
||||
use crate::parser::source::Cursor;
|
||||
|
@ -24,12 +25,7 @@ pub struct Text {
|
|||
}
|
||||
|
||||
impl Text {
|
||||
pub fn new(location: Token, content: String) -> Text {
|
||||
Text {
|
||||
location,
|
||||
content,
|
||||
}
|
||||
}
|
||||
pub fn new(location: Token, content: String) -> Text { Text { location, content } }
|
||||
}
|
||||
|
||||
impl Element for Text {
|
||||
|
@ -37,7 +33,12 @@ impl Element for Text {
|
|||
fn kind(&self) -> ElemKind { ElemKind::Inline }
|
||||
fn element_name(&self) -> &'static str { "Text" }
|
||||
|
||||
fn compile(&self, compiler: &Compiler, _document: &dyn Document, _cursor: usize) -> Result<String, String> {
|
||||
fn compile(
|
||||
&self,
|
||||
compiler: &Compiler,
|
||||
_document: &dyn Document,
|
||||
_cursor: usize,
|
||||
) -> Result<String, String> {
|
||||
Ok(Compiler::sanitize(compiler.target(), self.content.as_str()))
|
||||
}
|
||||
}
|
||||
|
@ -51,9 +52,15 @@ impl TextRule {
|
|||
|
||||
impl Rule for TextRule {
|
||||
fn name(&self) -> &'static str { "Text" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Link") }
|
||||
|
||||
fn next_match(&self, _state: &ParserState, _cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
||||
fn next_match(
|
||||
&self,
|
||||
_mode: &ParseMode,
|
||||
_state: &ParserState,
|
||||
_cursor: &Cursor,
|
||||
) -> Option<(usize, Box<dyn Any>)> {
|
||||
None
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::document::variable::PathVariable;
|
|||
use crate::document::variable::Variable;
|
||||
use crate::lsp::semantic::Semantics;
|
||||
use crate::lua::kernel::CTX;
|
||||
use crate::parser::parser::ParseMode;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::parser::ReportColors;
|
||||
use crate::parser::rule::RegexRule;
|
||||
|
@ -119,10 +120,13 @@ impl VariableRule {
|
|||
|
||||
impl RegexRule for VariableRule {
|
||||
fn name(&self) -> &'static str { "Variable" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Element Style") }
|
||||
|
||||
fn regexes(&self) -> &[Regex] { &self.re }
|
||||
|
||||
fn enabled(&self, mode: &ParseMode, _id: usize) -> bool { !mode.paragraph_only }
|
||||
|
||||
fn on_regex_match(
|
||||
&self,
|
||||
_: usize,
|
||||
|
@ -257,17 +261,18 @@ impl RegexRule for VariableRule {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some((sems, tokens)) = Semantics::from_source(token.source(), &state.shared.semantics)
|
||||
if let Some((sems, tokens)) =
|
||||
Semantics::from_source(token.source(), &state.shared.semantics)
|
||||
{
|
||||
let name = matches.get(2).unwrap().range();
|
||||
if let Some(kind) = matches.get(1).map(|m| m.range()) {
|
||||
sems.add(kind.start-1..kind.start, tokens.variable_operator);
|
||||
sems.add(kind.start - 1..kind.start, tokens.variable_operator);
|
||||
sems.add(kind, tokens.variable_kind);
|
||||
} else {
|
||||
sems.add(name.start-1..name.start, tokens.variable_operator);
|
||||
sems.add(name.start - 1..name.start, tokens.variable_operator);
|
||||
}
|
||||
sems.add(name.clone(), tokens.variable_name);
|
||||
sems.add(name.end..name.end+1, tokens.variable_sep);
|
||||
sems.add(name.end..name.end + 1, tokens.variable_sep);
|
||||
let value = matches.get(3).unwrap().range();
|
||||
sems.add(value.clone(), tokens.variable_value);
|
||||
}
|
||||
|
@ -297,8 +302,7 @@ impl RegexRule for VariableRule {
|
|||
let mut value: Option<String> = None;
|
||||
CTX.with_borrow(|ctx| {
|
||||
ctx.as_ref().map(|ctx| {
|
||||
if let Some(var) = ctx.document.get_variable(name.as_str())
|
||||
{
|
||||
if let Some(var) = ctx.document.get_variable(name.as_str()) {
|
||||
value = Some(var.to_string());
|
||||
}
|
||||
})
|
||||
|
@ -328,10 +332,13 @@ impl VariableSubstitutionRule {
|
|||
|
||||
impl RegexRule for VariableSubstitutionRule {
|
||||
fn name(&self) -> &'static str { "Variable Substitution" }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { Some("Variable") }
|
||||
|
||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||
|
||||
fn enabled(&self, _mode: &ParseMode, _id: usize) -> bool { true }
|
||||
|
||||
fn on_regex_match<'a>(
|
||||
&self,
|
||||
_index: usize,
|
||||
|
@ -351,7 +358,9 @@ impl RegexRule for VariableSubstitutionRule {
|
|||
.with_message("Empty variable name")
|
||||
.with_label(
|
||||
Label::new((token.source(), matches.get(0).unwrap().range()))
|
||||
.with_message("Missing variable name for substitution".to_string())
|
||||
.with_message(
|
||||
"Missing variable name for substitution".to_string(),
|
||||
)
|
||||
.with_color(state.parser.colors().error),
|
||||
)
|
||||
.finish(),
|
||||
|
@ -366,7 +375,9 @@ impl RegexRule for VariableSubstitutionRule {
|
|||
.with_message("Invalid variable name")
|
||||
.with_label(
|
||||
Label::new((token.source(), name.range()))
|
||||
.with_message("Variable names contains leading spaces".to_string())
|
||||
.with_message(
|
||||
"Variable names contains leading spaces".to_string(),
|
||||
)
|
||||
.with_color(state.parser.colors().error),
|
||||
)
|
||||
.with_help("Remove leading spaces")
|
||||
|
@ -382,7 +393,9 @@ impl RegexRule for VariableSubstitutionRule {
|
|||
.with_message("Invalid variable name")
|
||||
.with_label(
|
||||
Label::new((token.source(), name.range()))
|
||||
.with_message("Variable names contains trailing spaces".to_string())
|
||||
.with_message(
|
||||
"Variable names contains trailing spaces".to_string(),
|
||||
)
|
||||
.with_color(state.parser.colors().error),
|
||||
)
|
||||
.with_help("Remove trailing spaces")
|
||||
|
@ -392,20 +405,21 @@ impl RegexRule for VariableSubstitutionRule {
|
|||
return result;
|
||||
}
|
||||
// Invalid name
|
||||
if let Err(msg) = VariableRule::validate_name(state.parser.colors(), name.as_str()) {
|
||||
result.push(
|
||||
Report::build(ReportKind::Error, token.source(), name.start())
|
||||
.with_message("Invalid variable name")
|
||||
.with_label(
|
||||
Label::new((token.source(), name.range()))
|
||||
.with_message(msg)
|
||||
.with_color(state.parser.colors().error),
|
||||
)
|
||||
.finish(),
|
||||
);
|
||||
if let Err(msg) = VariableRule::validate_name(state.parser.colors(), name.as_str())
|
||||
{
|
||||
result.push(
|
||||
Report::build(ReportKind::Error, token.source(), name.start())
|
||||
.with_message("Invalid variable name")
|
||||
.with_label(
|
||||
Label::new((token.source(), name.range()))
|
||||
.with_message(msg)
|
||||
.with_color(state.parser.colors().error),
|
||||
)
|
||||
.finish(),
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get variable
|
||||
match document.get_variable(name.as_str()) {
|
||||
|
@ -433,12 +447,13 @@ impl RegexRule for VariableSubstitutionRule {
|
|||
|
||||
variable.parse(state, token.clone(), document);
|
||||
|
||||
if let Some((sems, tokens)) = Semantics::from_source(token.source(), &state.shared.semantics)
|
||||
if let Some((sems, tokens)) =
|
||||
Semantics::from_source(token.source(), &state.shared.semantics)
|
||||
{
|
||||
let name = matches.get(1).unwrap().range();
|
||||
sems.add(name.start-1..name.start, tokens.variable_sub_sep);
|
||||
sems.add(name.start - 1..name.start, tokens.variable_sub_sep);
|
||||
sems.add(name.clone(), tokens.variable_sub_name);
|
||||
sems.add(name.end..name.end+1, tokens.variable_sub_sep);
|
||||
sems.add(name.end..name.end + 1, tokens.variable_sub_sep);
|
||||
}
|
||||
|
||||
result
|
||||
|
|
|
@ -2,9 +2,9 @@ mod cache;
|
|||
mod compiler;
|
||||
mod document;
|
||||
mod elements;
|
||||
mod lsp;
|
||||
mod lua;
|
||||
mod parser;
|
||||
mod lsp;
|
||||
|
||||
use std::env;
|
||||
use std::io::BufWriter;
|
||||
|
|
|
@ -5,9 +5,9 @@ use crate::document::document::Document;
|
|||
use crate::document::element::DocumentEnd;
|
||||
use crate::document::langdocument::LangDocument;
|
||||
use crate::elements::text::Text;
|
||||
use crate::lsp::semantic::Semantics;
|
||||
use crate::lsp::semantic::SemanticsData;
|
||||
|
||||
use super::parser::ParseMode;
|
||||
use super::parser::Parser;
|
||||
use super::parser::ParserState;
|
||||
use super::parser::ReportColors;
|
||||
|
@ -37,8 +37,7 @@ impl LangParser {
|
|||
};
|
||||
|
||||
// Register rules
|
||||
for rule in super::rule::get_rule_registry()
|
||||
{
|
||||
for rule in super::rule::get_rule_registry() {
|
||||
s.add_rule(rule).unwrap();
|
||||
}
|
||||
|
||||
|
@ -59,16 +58,19 @@ impl Parser for LangParser {
|
|||
state: ParserState<'p, 'a>,
|
||||
source: Rc<dyn Source>,
|
||||
parent: Option<&'doc dyn Document<'doc>>,
|
||||
mode: ParseMode,
|
||||
) -> (Box<dyn Document<'doc> + 'doc>, ParserState<'p, 'a>) {
|
||||
let doc = LangDocument::new(source.clone(), parent);
|
||||
|
||||
// Insert semantics into state
|
||||
if let (Some(_), Some(semantics)) = (source.clone().downcast_rc::<SourceFile>().ok(), state.shared.semantics.as_ref())
|
||||
{
|
||||
if let (Some(_), Some(semantics)) = (
|
||||
source.clone().downcast_rc::<SourceFile>().ok(),
|
||||
state.shared.semantics.as_ref(),
|
||||
) {
|
||||
let mut b = semantics.borrow_mut();
|
||||
if !b.sems.contains_key(&source)
|
||||
{
|
||||
b.sems.insert(source.clone(), SemanticsData::new(source.clone()));
|
||||
if !b.sems.contains_key(&source) {
|
||||
b.sems
|
||||
.insert(source.clone(), SemanticsData::new(source.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,7 +88,7 @@ impl Parser for LangParser {
|
|||
}
|
||||
|
||||
loop {
|
||||
let (rule_pos, mut result) = state.update_matches(&cursor);
|
||||
let (rule_pos, mut result) = state.update_matches(&mode, &cursor);
|
||||
|
||||
// Unmatched content
|
||||
let text_content =
|
||||
|
@ -125,13 +127,12 @@ impl Parser for LangParser {
|
|||
super::state::Scope::DOCUMENT,
|
||||
));
|
||||
|
||||
if parent.is_none()
|
||||
{
|
||||
if parent.is_none() {
|
||||
state.push(
|
||||
&doc,
|
||||
Box::new(DocumentEnd(Token::new(
|
||||
doc.source().content().len()..doc.source().content().len(),
|
||||
doc.source(),
|
||||
doc.source().content().len()..doc.source().content().len(),
|
||||
doc.source(),
|
||||
))),
|
||||
);
|
||||
}
|
||||
|
@ -144,12 +145,13 @@ impl Parser for LangParser {
|
|||
state: ParserState<'p, 'a>,
|
||||
source: Rc<dyn Source>,
|
||||
document: &'doc dyn Document<'doc>,
|
||||
mode: ParseMode,
|
||||
) -> ParserState<'p, 'a> {
|
||||
let content = source.content();
|
||||
let mut cursor = Cursor::new(0usize, source.clone());
|
||||
|
||||
loop {
|
||||
let (rule_pos, mut result) = state.update_matches(&cursor);
|
||||
let (rule_pos, mut result) = state.update_matches(&mode, &cursor);
|
||||
|
||||
// Unmatched content
|
||||
let text_content =
|
||||
|
|
|
@ -147,7 +147,10 @@ impl<'a, 'b> ParserState<'a, 'b> {
|
|||
|
||||
/// Constructs a new state with semantics enabled
|
||||
/// See [`ParserState::new`] for mote information
|
||||
pub fn new_with_semantics(parser: &'a dyn Parser, parent: Option<&'a ParserState<'a, 'b>>) -> Self {
|
||||
pub fn new_with_semantics(
|
||||
parser: &'a dyn Parser,
|
||||
parent: Option<&'a ParserState<'a, 'b>>,
|
||||
) -> Self {
|
||||
let matches = parser.rules().iter().map(|_| (0, None)).collect::<Vec<_>>();
|
||||
let shared = if let Some(parent) = &parent {
|
||||
parent.shared.clone()
|
||||
|
@ -199,7 +202,11 @@ impl<'a, 'b> ParserState<'a, 'b> {
|
|||
/// Notes that the result of every call to [`Rule::next_match`] gets stored
|
||||
/// in a table: [`ParserState::matches`]. Until the cursor steps over a
|
||||
/// position in the table, `next_match` won't be called.
|
||||
pub fn update_matches(&self, cursor: &Cursor) -> (Cursor, Option<(usize, Box<dyn Any>)>) {
|
||||
pub fn update_matches(
|
||||
&self,
|
||||
mode: &ParseMode,
|
||||
cursor: &Cursor,
|
||||
) -> (Cursor, Option<(usize, Box<dyn Any>)>) {
|
||||
let mut matches_borrow = self.matches.borrow_mut();
|
||||
|
||||
self.parser
|
||||
|
@ -212,7 +219,7 @@ impl<'a, 'b> ParserState<'a, 'b> {
|
|||
return;
|
||||
}
|
||||
|
||||
(*matched_at, *match_data) = match rule.next_match(self, cursor) {
|
||||
(*matched_at, *match_data) = match rule.next_match(&mode, self, cursor) {
|
||||
None => (usize::MAX, None),
|
||||
Some((mut pos, mut data)) => {
|
||||
// Check if escaped
|
||||
|
@ -233,7 +240,7 @@ impl<'a, 'b> ParserState<'a, 'b> {
|
|||
}
|
||||
|
||||
// Find next potential match
|
||||
(pos, data) = match rule.next_match(self, &cursor.at(pos + 1)) {
|
||||
(pos, data) = match rule.next_match(&mode, self, &cursor.at(pos + 1)) {
|
||||
Some((new_pos, new_data)) => (new_pos, new_data),
|
||||
None => (usize::MAX, data), // Stop iterating
|
||||
}
|
||||
|
@ -308,24 +315,28 @@ impl<'a, 'b> ParserState<'a, 'b> {
|
|||
/// # Error
|
||||
///
|
||||
/// Returns an error if `rule_name` was not found in the parser's ruleset.
|
||||
pub fn reset_match(&self, rule_name: &str) -> Result<(), String>
|
||||
{
|
||||
if self.parser.rules().iter()
|
||||
pub fn reset_match(&self, rule_name: &str) -> Result<(), String> {
|
||||
if self
|
||||
.parser
|
||||
.rules()
|
||||
.iter()
|
||||
.zip(self.matches.borrow_mut().iter_mut())
|
||||
.try_for_each(|(rule, (match_pos, match_data))| {
|
||||
if rule.name() != rule_name { return Ok(()) }
|
||||
if rule.name() != rule_name {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
*match_pos = 0;
|
||||
match_data.take();
|
||||
Err(())
|
||||
}).is_ok()
|
||||
})
|
||||
.is_ok()
|
||||
{
|
||||
return Err(format!("Could not find rule: {rule_name}"));
|
||||
}
|
||||
|
||||
// Resurcively reset
|
||||
if let Some(parent) = self.parent
|
||||
{
|
||||
if let Some(parent) = self.parent {
|
||||
return parent.reset_match(rule_name);
|
||||
}
|
||||
|
||||
|
@ -333,6 +344,18 @@ impl<'a, 'b> ParserState<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct ParseMode {
|
||||
pub paragraph_only: bool,
|
||||
}
|
||||
|
||||
impl Default for ParseMode {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
paragraph_only: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Parser {
|
||||
/// Gets the colors for formatting errors
|
||||
///
|
||||
|
@ -365,6 +388,7 @@ pub trait Parser {
|
|||
state: ParserState<'p, 'a>,
|
||||
source: Rc<dyn Source>,
|
||||
parent: Option<&'doc dyn Document<'doc>>,
|
||||
mode: ParseMode,
|
||||
) -> (Box<dyn Document<'doc> + 'doc>, ParserState<'p, 'a>);
|
||||
|
||||
/// Parse [`Source`] into an already existing [`Document`]
|
||||
|
@ -384,6 +408,7 @@ pub trait Parser {
|
|||
state: ParserState<'p, 'a>,
|
||||
source: Rc<dyn Source>,
|
||||
document: &'doc dyn Document<'doc>,
|
||||
mode: ParseMode,
|
||||
) -> ParserState<'p, 'a>;
|
||||
|
||||
/// Adds a rule to the parser.
|
||||
|
@ -444,8 +469,11 @@ pub trait Parser {
|
|||
|
||||
if let Some(_s) = source.downcast_ref::<VirtualSource>() {
|
||||
let start = location.start()
|
||||
+ if location.source().content().as_bytes()[location.start()]
|
||||
== b'\n' { 1 } else { 0 };
|
||||
+ if location.source().content().as_bytes()[location.start()] == b'\n' {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
report.labels.push(
|
||||
Label::new((location.source(), start..location.end()))
|
||||
.with_message("In evaluation of")
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use super::layout::LayoutHolder;
|
||||
use super::parser::ParseMode;
|
||||
use super::parser::ParserState;
|
||||
use super::source::Cursor;
|
||||
use super::source::Source;
|
||||
|
@ -73,7 +74,13 @@ pub trait Rule: Downcast {
|
|||
fn previous(&self) -> Option<&'static str>;
|
||||
|
||||
/// Finds the next match starting from [`cursor`]
|
||||
fn next_match(&self, state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)>;
|
||||
fn next_match(
|
||||
&self,
|
||||
mode: &ParseMode,
|
||||
state: &ParserState,
|
||||
cursor: &Cursor,
|
||||
) -> Option<(usize, Box<dyn Any>)>;
|
||||
|
||||
/// Callback when rule matches
|
||||
fn on_match<'a>(
|
||||
&self,
|
||||
|
@ -110,6 +117,9 @@ pub trait RegexRule {
|
|||
/// Returns the rule's regexes
|
||||
fn regexes(&self) -> &[regex::Regex];
|
||||
|
||||
/// Wheter parsing for the rule is enabled
|
||||
fn enabled(&self, mode: &ParseMode, index: usize) -> bool;
|
||||
|
||||
/// Callback on regex rule match
|
||||
fn on_regex_match<'a>(
|
||||
&self,
|
||||
|
@ -127,13 +137,22 @@ pub trait RegexRule {
|
|||
|
||||
impl<T: RegexRule + 'static> Rule for T {
|
||||
fn name(&self) -> &'static str { RegexRule::name(self) }
|
||||
|
||||
fn previous(&self) -> Option<&'static str> { RegexRule::previous(self) }
|
||||
|
||||
/// Finds the next match starting from [`cursor`]
|
||||
fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
||||
fn next_match(
|
||||
&self,
|
||||
mode: &ParseMode,
|
||||
_state: &ParserState,
|
||||
cursor: &Cursor,
|
||||
) -> Option<(usize, Box<dyn Any>)> {
|
||||
let content = cursor.source.content();
|
||||
let mut found: Option<(usize, usize)> = None;
|
||||
self.regexes().iter().enumerate().for_each(|(id, re)| {
|
||||
if !RegexRule::enabled(self, mode, id) {
|
||||
return;
|
||||
}
|
||||
if let Some(m) = re.find_at(content.as_str(), cursor.pos) {
|
||||
found = found
|
||||
.map(|(f_pos, f_id)| {
|
||||
|
|
|
@ -60,7 +60,8 @@ macro_rules! impl_elementstyle {
|
|||
serde_json::from_str::<$t>(json)
|
||||
.map_err(|e| e.to_string())
|
||||
.map(|obj| {
|
||||
std::rc::Rc::new(obj) as std::rc::Rc<dyn $crate::parser::style::ElementStyle>
|
||||
std::rc::Rc::new(obj)
|
||||
as std::rc::Rc<dyn $crate::parser::style::ElementStyle>
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ use crate::document::document::DocumentAccessors;
|
|||
use crate::document::element::ElemKind;
|
||||
use crate::elements::paragraph::Paragraph;
|
||||
|
||||
use super::parser::ParseMode;
|
||||
use super::parser::ParserState;
|
||||
use super::source::Source;
|
||||
|
||||
|
@ -143,7 +144,7 @@ pub fn parse_paragraph<'a>(
|
|||
let parsed = state.with_state(|new_state| -> Box<dyn Document> {
|
||||
new_state
|
||||
.parser
|
||||
.parse(new_state, source.clone(), Some(document))
|
||||
.parse(new_state, source.clone(), Some(document), ParseMode { paragraph_only: true })
|
||||
.0
|
||||
});
|
||||
if parsed.content().borrow().len() > 1 {
|
||||
|
|
|
@ -10,6 +10,7 @@ use std::rc::Rc;
|
|||
|
||||
use dashmap::DashMap;
|
||||
use parser::langparser::LangParser;
|
||||
use parser::parser::ParseMode;
|
||||
use parser::parser::Parser;
|
||||
use parser::parser::ParserState;
|
||||
use parser::source::SourceFile;
|
||||
|
@ -42,7 +43,7 @@ impl Backend {
|
|||
// Which will require a dyn Document to work
|
||||
let source = Rc::new(SourceFile::with_content(params.uri.to_string(), params.text.clone(), None));
|
||||
let parser = LangParser::default();
|
||||
let (_doc, state) = parser.parse(ParserState::new_with_semantics(&parser, None), source.clone(), None);
|
||||
let (_doc, state) = parser.parse(ParserState::new_with_semantics(&parser, None), source.clone(), None, ParseMode::default());
|
||||
|
||||
if let Some(sems) = state.shared.semantics.as_ref()
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue