Automatic rules registration
This commit is contained in:
parent
85fe0425b9
commit
4784921bb8
24 changed files with 157 additions and 74 deletions
|
@ -296,6 +296,7 @@ impl Element for Code {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct CodeRule {
|
pub struct CodeRule {
|
||||||
re: [Regex; 2],
|
re: [Regex; 2],
|
||||||
properties: PropertyParser,
|
properties: PropertyParser,
|
||||||
|
@ -330,6 +331,7 @@ impl CodeRule {
|
||||||
|
|
||||||
impl RegexRule for CodeRule {
|
impl RegexRule for CodeRule {
|
||||||
fn name(&self) -> &'static str { "Code" }
|
fn name(&self) -> &'static str { "Code" }
|
||||||
|
fn previous(&self) -> Option<&'static str> { Some("List") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ impl Element for Comment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct CommentRule {
|
pub struct CommentRule {
|
||||||
re: [Regex; 1],
|
re: [Regex; 1],
|
||||||
}
|
}
|
||||||
|
@ -53,6 +54,8 @@ impl CommentRule {
|
||||||
impl RegexRule for CommentRule {
|
impl RegexRule for CommentRule {
|
||||||
fn name(&self) -> &'static str { "Comment" }
|
fn name(&self) -> &'static str { "Comment" }
|
||||||
|
|
||||||
|
fn previous(&self) -> Option<&'static str> { None }
|
||||||
|
|
||||||
fn regexes(&self) -> &[Regex] { &self.re }
|
fn regexes(&self) -> &[Regex] { &self.re }
|
||||||
|
|
||||||
fn on_regex_match<'a>(
|
fn on_regex_match<'a>(
|
||||||
|
|
|
@ -178,10 +178,16 @@ impl RuleState for CustomStyleState {
|
||||||
|
|
||||||
static STATE_NAME: &'static str = "elements.custom_style";
|
static STATE_NAME: &'static str = "elements.custom_style";
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct CustomStyleRule;
|
pub struct CustomStyleRule;
|
||||||
|
|
||||||
|
impl CustomStyleRule {
|
||||||
|
pub fn new() -> Self { Self{} }
|
||||||
|
}
|
||||||
|
|
||||||
impl Rule for CustomStyleRule {
|
impl Rule for CustomStyleRule {
|
||||||
fn name(&self) -> &'static str { "Custom Style" }
|
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, state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
||||||
let content = cursor.source.content();
|
let content = cursor.source.content();
|
||||||
|
|
|
@ -21,6 +21,7 @@ use crate::parser::rule::Rule;
|
||||||
use crate::parser::source::Cursor;
|
use crate::parser::source::Cursor;
|
||||||
use crate::parser::source::Source;
|
use crate::parser::source::Source;
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct ElemStyleRule {
|
pub struct ElemStyleRule {
|
||||||
start_re: Regex,
|
start_re: Regex,
|
||||||
}
|
}
|
||||||
|
@ -58,6 +59,7 @@ impl ElemStyleRule {
|
||||||
|
|
||||||
impl Rule for ElemStyleRule {
|
impl Rule for ElemStyleRule {
|
||||||
fn name(&self) -> &'static str { "Element Style" }
|
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, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
||||||
self.start_re
|
self.start_re
|
||||||
|
|
|
@ -146,6 +146,7 @@ impl Element for Graphviz {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct GraphRule {
|
pub struct GraphRule {
|
||||||
re: [Regex; 1],
|
re: [Regex; 1],
|
||||||
properties: PropertyParser,
|
properties: PropertyParser,
|
||||||
|
@ -178,6 +179,7 @@ impl GraphRule {
|
||||||
|
|
||||||
impl RegexRule for GraphRule {
|
impl RegexRule for GraphRule {
|
||||||
fn name(&self) -> &'static str { "Graph" }
|
fn name(&self) -> &'static str { "Graph" }
|
||||||
|
fn previous(&self) -> Option<&'static str> { Some("Tex") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ use std::rc::Rc;
|
||||||
|
|
||||||
use super::paragraph::Paragraph;
|
use super::paragraph::Paragraph;
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct ImportRule {
|
pub struct ImportRule {
|
||||||
re: [Regex; 1],
|
re: [Regex; 1],
|
||||||
}
|
}
|
||||||
|
@ -40,6 +41,7 @@ impl ImportRule {
|
||||||
|
|
||||||
impl RegexRule for ImportRule {
|
impl RegexRule for ImportRule {
|
||||||
fn name(&self) -> &'static str { "Import" }
|
fn name(&self) -> &'static str { "Import" }
|
||||||
|
fn previous(&self) -> Option<&'static str> { Some("Paragraph") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[Regex] { &self.re }
|
fn regexes(&self) -> &[Regex] { &self.re }
|
||||||
|
|
||||||
|
|
|
@ -284,6 +284,7 @@ impl RuleState for LayoutState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct LayoutRule {
|
pub struct LayoutRule {
|
||||||
re: [Regex; 3],
|
re: [Regex; 3],
|
||||||
}
|
}
|
||||||
|
@ -378,6 +379,7 @@ static STATE_NAME: &'static str = "elements.layout";
|
||||||
|
|
||||||
impl RegexRule for LayoutRule {
|
impl RegexRule for LayoutRule {
|
||||||
fn name(&self) -> &'static str { "Layout" }
|
fn name(&self) -> &'static str { "Layout" }
|
||||||
|
fn previous(&self) -> Option<&'static str> { Some("Media") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,7 @@ impl ContainerElement for Link {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct LinkRule {
|
pub struct LinkRule {
|
||||||
re: [Regex; 1],
|
re: [Regex; 1],
|
||||||
}
|
}
|
||||||
|
@ -85,6 +86,7 @@ impl LinkRule {
|
||||||
|
|
||||||
impl RegexRule for LinkRule {
|
impl RegexRule for LinkRule {
|
||||||
fn name(&self) -> &'static str { "Link" }
|
fn name(&self) -> &'static str { "Link" }
|
||||||
|
fn previous(&self) -> Option<&'static str> { Some("Link") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[Regex] { &self.re }
|
fn regexes(&self) -> &[Regex] { &self.re }
|
||||||
|
|
||||||
|
|
|
@ -106,6 +106,7 @@ impl ContainerElement for ListEntry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct ListRule {
|
pub struct ListRule {
|
||||||
start_re: Regex,
|
start_re: Regex,
|
||||||
continue_re: Regex,
|
continue_re: Regex,
|
||||||
|
@ -249,6 +250,7 @@ impl ListRule {
|
||||||
|
|
||||||
impl Rule for ListRule {
|
impl Rule for ListRule {
|
||||||
fn name(&self) -> &'static str { "List" }
|
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, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
||||||
self.start_re
|
self.start_re
|
||||||
|
|
|
@ -221,6 +221,7 @@ impl ReferenceableElement for Medium {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct MediaRule {
|
pub struct MediaRule {
|
||||||
re: [Regex; 1],
|
re: [Regex; 1],
|
||||||
properties: PropertyParser,
|
properties: PropertyParser,
|
||||||
|
@ -325,6 +326,7 @@ impl MediaRule {
|
||||||
|
|
||||||
impl RegexRule for MediaRule {
|
impl RegexRule for MediaRule {
|
||||||
fn name(&self) -> &'static str { "Media" }
|
fn name(&self) -> &'static str { "Media" }
|
||||||
|
fn previous(&self) -> Option<&'static str> { Some("Graph") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ pub mod media;
|
||||||
pub mod paragraph;
|
pub mod paragraph;
|
||||||
pub mod raw;
|
pub mod raw;
|
||||||
pub mod reference;
|
pub mod reference;
|
||||||
pub mod registrar;
|
|
||||||
pub mod script;
|
pub mod script;
|
||||||
pub mod section;
|
pub mod section;
|
||||||
pub mod style;
|
pub mod style;
|
||||||
|
|
|
@ -91,6 +91,7 @@ impl ContainerElement for Paragraph {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct ParagraphRule {
|
pub struct ParagraphRule {
|
||||||
re: Regex,
|
re: Regex,
|
||||||
}
|
}
|
||||||
|
@ -104,7 +105,8 @@ impl ParagraphRule {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rule for ParagraphRule {
|
impl Rule for ParagraphRule {
|
||||||
fn name(&self) -> &'static str { "Paragraphing" }
|
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, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
||||||
self.re
|
self.re
|
||||||
|
|
|
@ -44,6 +44,7 @@ impl Element for Raw {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct RawRule {
|
pub struct RawRule {
|
||||||
re: [Regex; 1],
|
re: [Regex; 1],
|
||||||
properties: PropertyParser,
|
properties: PropertyParser,
|
||||||
|
@ -72,6 +73,7 @@ impl RawRule {
|
||||||
|
|
||||||
impl RegexRule for RawRule {
|
impl RegexRule for RawRule {
|
||||||
fn name(&self) -> &'static str { "Raw" }
|
fn name(&self) -> &'static str { "Raw" }
|
||||||
|
fn previous(&self) -> Option<&'static str> { Some("Variable Substitution") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,7 @@ impl Element for Reference {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct ReferenceRule {
|
pub struct ReferenceRule {
|
||||||
re: [Regex; 1],
|
re: [Regex; 1],
|
||||||
properties: PropertyParser,
|
properties: PropertyParser,
|
||||||
|
@ -127,6 +128,7 @@ impl ReferenceRule {
|
||||||
|
|
||||||
impl RegexRule for ReferenceRule {
|
impl RegexRule for ReferenceRule {
|
||||||
fn name(&self) -> &'static str { "Reference" }
|
fn name(&self) -> &'static str { "Reference" }
|
||||||
|
fn previous(&self) -> Option<&'static str> { Some("Text") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
use crate::parser::parser::Parser;
|
|
||||||
|
|
||||||
use super::code::CodeRule;
|
|
||||||
use super::comment::CommentRule;
|
|
||||||
use super::elemstyle::ElemStyleRule;
|
|
||||||
use super::graphviz::GraphRule;
|
|
||||||
use super::import::ImportRule;
|
|
||||||
use super::layout::LayoutRule;
|
|
||||||
use super::link::LinkRule;
|
|
||||||
use super::list::ListRule;
|
|
||||||
use super::media::MediaRule;
|
|
||||||
use super::paragraph::ParagraphRule;
|
|
||||||
use super::raw::RawRule;
|
|
||||||
use super::script::ScriptRule;
|
|
||||||
use super::section::SectionRule;
|
|
||||||
use super::style::StyleRule;
|
|
||||||
use super::customstyle::CustomStyleRule;
|
|
||||||
use super::tex::TexRule;
|
|
||||||
use super::text::TextRule;
|
|
||||||
use super::variable::VariableRule;
|
|
||||||
use super::variable::VariableSubstitutionRule;
|
|
||||||
use super::reference::ReferenceRule;
|
|
||||||
|
|
||||||
pub fn register<P: Parser>(parser: &mut P) {
|
|
||||||
parser.add_rule(Box::new(CommentRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(ParagraphRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(ImportRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(ScriptRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(ElemStyleRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(VariableRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(VariableSubstitutionRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(RawRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(ListRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(CodeRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(TexRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(GraphRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(MediaRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(LayoutRule::new()), None).unwrap();
|
|
||||||
|
|
||||||
parser.add_rule(Box::new(StyleRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(CustomStyleRule{}), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(SectionRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(LinkRule::new()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(TextRule::default()), None).unwrap();
|
|
||||||
parser.add_rule(Box::new(ReferenceRule::new()), None).unwrap();
|
|
||||||
}
|
|
|
@ -20,6 +20,7 @@ use std::rc::Rc;
|
||||||
|
|
||||||
use super::text::Text;
|
use super::text::Text;
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct ScriptRule {
|
pub struct ScriptRule {
|
||||||
re: [Regex; 2],
|
re: [Regex; 2],
|
||||||
eval_kinds: [(&'static str, &'static str); 3],
|
eval_kinds: [(&'static str, &'static str); 3],
|
||||||
|
@ -77,6 +78,7 @@ impl ScriptRule {
|
||||||
|
|
||||||
impl RegexRule for ScriptRule {
|
impl RegexRule for ScriptRule {
|
||||||
fn name(&self) -> &'static str { "Script" }
|
fn name(&self) -> &'static str { "Script" }
|
||||||
|
fn previous(&self) -> Option<&'static str> { Some("Import") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
|
|
@ -135,6 +135,7 @@ impl ReferenceableElement for Section {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct SectionRule {
|
pub struct SectionRule {
|
||||||
re: [Regex; 1],
|
re: [Regex; 1],
|
||||||
}
|
}
|
||||||
|
@ -155,6 +156,7 @@ pub mod section_kind {
|
||||||
|
|
||||||
impl RegexRule for SectionRule {
|
impl RegexRule for SectionRule {
|
||||||
fn name(&self) -> &'static str { "Section" }
|
fn name(&self) -> &'static str { "Section" }
|
||||||
|
fn previous(&self) -> Option<&'static str> { Some("Custom Style") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[Regex] { &self.re }
|
fn regexes(&self) -> &[Regex] { &self.re }
|
||||||
|
|
||||||
|
|
|
@ -132,6 +132,7 @@ impl RuleState for StyleState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct StyleRule {
|
pub struct StyleRule {
|
||||||
re: [Regex; 4],
|
re: [Regex; 4],
|
||||||
}
|
}
|
||||||
|
@ -157,6 +158,7 @@ static STATE_NAME: &'static str = "elements.style";
|
||||||
|
|
||||||
impl RegexRule for StyleRule {
|
impl RegexRule for StyleRule {
|
||||||
fn name(&self) -> &'static str { "Style" }
|
fn name(&self) -> &'static str { "Style" }
|
||||||
|
fn previous(&self) -> Option<&'static str> { Some("Layout") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
|
|
@ -219,6 +219,7 @@ impl Element for Tex {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct TexRule {
|
pub struct TexRule {
|
||||||
re: [Regex; 2],
|
re: [Regex; 2],
|
||||||
properties: PropertyParser,
|
properties: PropertyParser,
|
||||||
|
@ -296,6 +297,7 @@ impl TexRule {
|
||||||
|
|
||||||
impl RegexRule for TexRule {
|
impl RegexRule for TexRule {
|
||||||
fn name(&self) -> &'static str { "Tex" }
|
fn name(&self) -> &'static str { "Tex" }
|
||||||
|
fn previous(&self) -> Option<&'static str> { Some("Code") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
|
|
@ -42,13 +42,20 @@ impl Element for Text {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct TextRule;
|
pub struct TextRule;
|
||||||
|
|
||||||
|
impl TextRule {
|
||||||
|
pub fn new() -> Self { Self {} }
|
||||||
|
}
|
||||||
|
|
||||||
impl Rule for TextRule {
|
impl Rule for TextRule {
|
||||||
fn name(&self) -> &'static str { "Text" }
|
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>)> { None }
|
fn next_match(&self, _state: &ParserState, _cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn on_match(
|
fn on_match(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -37,6 +37,7 @@ impl FromStr for VariableKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct VariableRule {
|
pub struct VariableRule {
|
||||||
re: [Regex; 1],
|
re: [Regex; 1],
|
||||||
kinds: Vec<(String, String)>,
|
kinds: Vec<(String, String)>,
|
||||||
|
@ -117,6 +118,7 @@ impl VariableRule {
|
||||||
|
|
||||||
impl RegexRule for VariableRule {
|
impl RegexRule for VariableRule {
|
||||||
fn name(&self) -> &'static str { "Variable" }
|
fn name(&self) -> &'static str { "Variable" }
|
||||||
|
fn previous(&self) -> Option<&'static str> { Some("Element Style") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[Regex] { &self.re }
|
fn regexes(&self) -> &[Regex] { &self.re }
|
||||||
|
|
||||||
|
@ -295,6 +297,7 @@ impl RegexRule for VariableRule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[auto_registry::auto_registry(registry = "rules")]
|
||||||
pub struct VariableSubstitutionRule {
|
pub struct VariableSubstitutionRule {
|
||||||
re: [Regex; 1],
|
re: [Regex; 1],
|
||||||
}
|
}
|
||||||
|
@ -309,6 +312,7 @@ impl VariableSubstitutionRule {
|
||||||
|
|
||||||
impl RegexRule for VariableSubstitutionRule {
|
impl RegexRule for VariableSubstitutionRule {
|
||||||
fn name(&self) -> &'static str { "Variable Substitution" }
|
fn name(&self) -> &'static str { "Variable Substitution" }
|
||||||
|
fn previous(&self) -> Option<&'static str> { Some("Variable") }
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ use std::rc::Rc;
|
||||||
use crate::document::document::Document;
|
use crate::document::document::Document;
|
||||||
use crate::document::element::DocumentEnd;
|
use crate::document::element::DocumentEnd;
|
||||||
use crate::document::langdocument::LangDocument;
|
use crate::document::langdocument::LangDocument;
|
||||||
use crate::elements::registrar::register;
|
|
||||||
use crate::elements::text::Text;
|
use crate::elements::text::Text;
|
||||||
|
|
||||||
use super::parser::Parser;
|
use super::parser::Parser;
|
||||||
|
@ -35,8 +34,10 @@ impl LangParser {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Register rules
|
// Register rules
|
||||||
// TODO: use https://docs.rs/inventory/latest/inventory/
|
for rule in super::rule::get_rule_registry()
|
||||||
register(&mut s);
|
{
|
||||||
|
s.add_rule(rule).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ use crate::document::document::DocumentAccessors;
|
||||||
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::elements::customstyle::CustomStyleRule;
|
|
||||||
use crate::elements::paragraph::Paragraph;
|
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;
|
||||||
|
@ -186,7 +185,6 @@ impl<'a, 'b> ParserState<'a, 'b> {
|
||||||
.for_each(|(rule, (matched_at, match_data))| {
|
.for_each(|(rule, (matched_at, match_data))| {
|
||||||
// Don't upate if not stepped over yet
|
// Don't upate if not stepped over yet
|
||||||
if *matched_at > cursor.pos {
|
if *matched_at > cursor.pos {
|
||||||
// TODO: maybe we should expose matches() so it becomes possible to dynamically register a new rule
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,7 +367,7 @@ pub trait Parser {
|
||||||
/// # Warning
|
/// # Warning
|
||||||
///
|
///
|
||||||
/// This method must not be called if a [`ParserState`] for this parser exists.
|
/// This method must not be called if a [`ParserState`] for this parser exists.
|
||||||
fn add_rule(&mut self, rule: Box<dyn Rule>, after: Option<&'static str>) -> Result<(), String> {
|
fn add_rule(&mut self, rule: Box<dyn Rule>) -> Result<(), String> {
|
||||||
if let Some(_) = self
|
if let Some(_) = self
|
||||||
.rules()
|
.rules()
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -381,23 +379,7 @@ pub trait Parser {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to insert after
|
|
||||||
if let Some(after) = after {
|
|
||||||
let index = self
|
|
||||||
.rules()
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.find(|(_, rule)| rule.name() == after)
|
|
||||||
.map(|(idx, _)| idx);
|
|
||||||
|
|
||||||
if let Some(index) = index {
|
|
||||||
self.rules_mut().insert(index, rule);
|
|
||||||
} else {
|
|
||||||
return Err(format!("Unable to find rule `{after}` to insert after"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.rules_mut().push(rule);
|
self.rules_mut().push(rule);
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,66 @@ use mlua::Function;
|
||||||
use mlua::Lua;
|
use mlua::Lua;
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
macro_rules! create_registry {
|
||||||
|
( $($construct:expr),+ $(,)? ) => {{
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
$(
|
||||||
|
let boxed = Box::new($construct) as Box<dyn Rule>;
|
||||||
|
map.insert(boxed.name(), boxed);
|
||||||
|
)+
|
||||||
|
map
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the list of all rules exported with the [`auto_registry`] proc macro.
|
||||||
|
/// Rules are sorted according to topological order using the [`Rule::previous`] method.
|
||||||
|
#[auto_registry::generate_registry(registry = "rules", target = make_rules, return_type = HashMap<&'static str, Box<dyn Rule>>, maker = create_registry)]
|
||||||
|
pub fn get_rule_registry() -> Vec<Box<dyn Rule>> {
|
||||||
|
fn cmp(
|
||||||
|
map: &HashMap<&'static str, Box<dyn Rule>>,
|
||||||
|
lname: &'static str,
|
||||||
|
rname: &'static str,
|
||||||
|
) -> std::cmp::Ordering {
|
||||||
|
let l = map.get(lname).unwrap();
|
||||||
|
let r = map.get(rname).unwrap();
|
||||||
|
if l.previous() == Some(r.name()) {
|
||||||
|
std::cmp::Ordering::Greater
|
||||||
|
} else if r.previous() == Some(l.name()) {
|
||||||
|
std::cmp::Ordering::Less
|
||||||
|
} else if l.previous().is_some() && r.previous().is_none() {
|
||||||
|
std::cmp::Ordering::Greater
|
||||||
|
} else if r.previous().is_some() && l.previous().is_none() {
|
||||||
|
std::cmp::Ordering::Less
|
||||||
|
} else if let (Some(pl), Some(pr)) = (l.previous(), r.previous()) {
|
||||||
|
cmp(map, pl, pr)
|
||||||
|
} else {
|
||||||
|
std::cmp::Ordering::Equal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut map = make_rules();
|
||||||
|
let mut sorted_keys = map.iter().map(|(key, _)| *key).collect::<Vec<_>>();
|
||||||
|
sorted_keys.sort_by(|l, r| cmp(&map, l, r));
|
||||||
|
|
||||||
|
let mut owned = Vec::with_capacity(sorted_keys.len());
|
||||||
|
for key in sorted_keys {
|
||||||
|
let rule = map.remove(key).unwrap();
|
||||||
|
owned.push(rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
owned
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Rule: Downcast {
|
pub trait Rule: Downcast {
|
||||||
/// Returns rule's name
|
/// The rule name
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
|
|
||||||
|
/// The name of the rule that should come before this one
|
||||||
|
fn previous(&self) -> Option<&'static str>;
|
||||||
|
|
||||||
/// Finds the next match starting from [`cursor`]
|
/// Finds the next match starting from [`cursor`]
|
||||||
fn next_match(&self, state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)>;
|
fn next_match(&self, state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)>;
|
||||||
/// Callback when rule matches
|
/// Callback when rule matches
|
||||||
|
@ -47,8 +101,12 @@ impl core::fmt::Debug for dyn Rule {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RegexRule {
|
pub trait RegexRule {
|
||||||
|
/// The rule name
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
|
|
||||||
|
/// The name of the rule that should come before this one
|
||||||
|
fn previous(&self) -> Option<&'static str>;
|
||||||
|
|
||||||
/// Returns the rule's regexes
|
/// Returns the rule's regexes
|
||||||
fn regexes(&self) -> &[regex::Regex];
|
fn regexes(&self) -> &[regex::Regex];
|
||||||
|
|
||||||
|
@ -69,6 +127,7 @@ pub trait RegexRule {
|
||||||
|
|
||||||
impl<T: RegexRule + 'static> Rule for T {
|
impl<T: RegexRule + 'static> Rule for T {
|
||||||
fn name(&self) -> &'static str { RegexRule::name(self) }
|
fn name(&self) -> &'static str { RegexRule::name(self) }
|
||||||
|
fn previous(&self) -> Option<&'static str> { RegexRule::previous(self) }
|
||||||
|
|
||||||
/// Finds the next match starting from [`cursor`]
|
/// Finds the next match starting from [`cursor`]
|
||||||
fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
fn next_match(&self, _state: &ParserState, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)> {
|
||||||
|
@ -120,3 +179,41 @@ impl<T: RegexRule + 'static> Rule for T {
|
||||||
|
|
||||||
fn register_layouts(&self, holder: &mut LayoutHolder) { self.register_layouts(holder); }
|
fn register_layouts(&self, holder: &mut LayoutHolder) { self.register_layouts(holder); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn registry() {
|
||||||
|
let rules = get_rule_registry();
|
||||||
|
let names: Vec<&'static str> = rules.iter().map(|rule| rule.name()).collect();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
names,
|
||||||
|
vec![
|
||||||
|
"Comment",
|
||||||
|
"Paragraph",
|
||||||
|
"Import",
|
||||||
|
"Script",
|
||||||
|
"Element Style",
|
||||||
|
"Variable",
|
||||||
|
"Variable Substitution",
|
||||||
|
"Raw",
|
||||||
|
"List",
|
||||||
|
"Code",
|
||||||
|
"Tex",
|
||||||
|
"Graph",
|
||||||
|
"Media",
|
||||||
|
"Layout",
|
||||||
|
"Style",
|
||||||
|
"Custom Style",
|
||||||
|
"Section",
|
||||||
|
"Link",
|
||||||
|
"Text",
|
||||||
|
"Reference",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue