Refactor
This commit is contained in:
parent
461738dab9
commit
2617cbe507
28 changed files with 319 additions and 265 deletions
|
@ -3,7 +3,7 @@
|
||||||
@'html.css = style.css
|
@'html.css = style.css
|
||||||
|
|
||||||
@tex.main.fontsize = 9
|
@tex.main.fontsize = 9
|
||||||
@tex.main.preamble = \usepackage{xcolor} \\
|
@tex.main.preamble = \usepackage{xcolor, amsmath} \\
|
||||||
\definecolor{__color1}{HTML}{d5d5d5} \\
|
\definecolor{__color1}{HTML}{d5d5d5} \\
|
||||||
\everymath{\color{__color1}\displaystyle}
|
\everymath{\color{__color1}\displaystyle}
|
||||||
@tex.main.block_prepend = \color{__color1}
|
@tex.main.block_prepend = \color{__color1}
|
||||||
|
@ -77,7 +77,7 @@ end
|
||||||
|
|
||||||
Evaluating `!` from a kernel: `\%<![kernel] eval>\%`
|
Evaluating `!` from a kernel: `\%<![kernel] eval>\%`
|
||||||
|
|
||||||
* `\%<![example] make_bold("Hello, World!")>\%` → %<![example] make_bold("Hello, World!")>%
|
* `\%<[example]! make_bold("Hello, World!")>\%` → %<[example]! make_bold("Hello, World!")>%
|
||||||
|
|
||||||
# Latex
|
# Latex
|
||||||
|
|
||||||
|
|
|
@ -62,12 +62,12 @@ impl Compiler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn header(&self, document: &Document) -> String
|
pub fn header(&self, document: &dyn Document) -> String
|
||||||
{
|
{
|
||||||
pub fn get_variable_or_error(document: &Document, var_name: &'static str) -> Option<Rc<dyn Variable>>
|
pub fn get_variable_or_error(document: &dyn Document, var_name: &'static str) -> Option<Rc<dyn Variable>>
|
||||||
{
|
{
|
||||||
document.get_variable(var_name)
|
document.get_variable(var_name)
|
||||||
.and_then(|(_, var)| Some(var))
|
.and_then(|var| Some(var))
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
println!("Missing variable `{var_name}` in {}", document.source().name());
|
println!("Missing variable `{var_name}` in {}", document.source().name());
|
||||||
None
|
None
|
||||||
|
@ -85,7 +85,7 @@ impl Compiler
|
||||||
result += format!("<title>{}</title>", self.sanitize(page_title.to_string())).as_str();
|
result += format!("<title>{}</title>", self.sanitize(page_title.to_string())).as_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((_, css)) = document.get_variable("html.css")
|
if let Some(css) = document.get_variable("html.css")
|
||||||
{
|
{
|
||||||
result += format!("<link rel=\"stylesheet\" href=\"{}\">", self.sanitize(css.to_string())).as_str();
|
result += format!("<link rel=\"stylesheet\" href=\"{}\">", self.sanitize(css.to_string())).as_str();
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ impl Compiler
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn footer(&self, _document: &Document) -> String
|
pub fn footer(&self, _document: &dyn Document) -> String
|
||||||
{
|
{
|
||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
match self.target()
|
match self.target()
|
||||||
|
@ -116,10 +116,10 @@ impl Compiler
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile(&self, document: &Document) -> String
|
pub fn compile(&self, document: &dyn Document) -> String
|
||||||
{
|
{
|
||||||
let mut out = String::new();
|
let mut out = String::new();
|
||||||
let borrow = document.content.borrow();
|
let borrow = document.content().borrow();
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
out += self.header(document).as_str();
|
out += self.header(document).as_str();
|
||||||
|
|
|
@ -8,6 +8,9 @@ use super::element::Element;
|
||||||
use super::variable::Variable;
|
use super::variable::Variable;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Referenceable rework
|
||||||
|
// Usize based referencing is not an acceptable method
|
||||||
|
// if we want to support deltas for the lsp
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Scope {
|
pub struct Scope {
|
||||||
/// List of all referenceable elements in current scope.
|
/// List of all referenceable elements in current scope.
|
||||||
|
@ -17,7 +20,7 @@ pub struct Scope {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scope {
|
impl Scope {
|
||||||
fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
referenceable: HashMap::new(),
|
referenceable: HashMap::new(),
|
||||||
variables: HashMap::new(),
|
variables: HashMap::new(),
|
||||||
|
@ -54,113 +57,82 @@ impl Scope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
pub trait Document<'a>: core::fmt::Debug
|
||||||
pub struct Document<'a> {
|
|
||||||
source: Rc<dyn Source>,
|
|
||||||
parent: Option<&'a Document<'a>>, /// Document's parent
|
|
||||||
|
|
||||||
// FIXME: Render these fields private
|
|
||||||
pub content: RefCell<Vec<Box<dyn Element>>>,
|
|
||||||
pub scope: RefCell<Scope>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Document<'a> {
|
|
||||||
pub fn new(source: Rc<dyn Source>, parent: Option<&'a Document<'a>>) -> Self
|
|
||||||
{
|
{
|
||||||
Self {
|
/// Gets the document [`Source`]
|
||||||
source: source,
|
fn source(&self) -> Rc<dyn Source>;
|
||||||
parent: parent,
|
|
||||||
content: RefCell::new(Vec::new()),
|
|
||||||
scope: RefCell::new(Scope::new()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn source(&self) -> Rc<dyn Source> { self.source.clone() }
|
/// Gets the document parent (if it exists)
|
||||||
|
fn parent(&self) -> Option<&'a dyn Document<'a>>;
|
||||||
|
|
||||||
pub fn parent(&self) -> Option<&Document> { self.parent }
|
/// Gets the document content
|
||||||
|
/// The content is essentially the AST for the document
|
||||||
|
fn content(&self) -> &RefCell<Vec<Box<dyn Element>>>;
|
||||||
|
|
||||||
/// Push an element [`elem`] to content. [`in_paragraph`] is true if a paragraph is active
|
/// Gets the document [`Scope`]
|
||||||
pub fn push(&self, elem: Box<dyn Element>)
|
fn scope(&self) -> &RefCell<Scope>;
|
||||||
|
|
||||||
|
/// Pushes a new element into the document's content
|
||||||
|
fn push(&self, elem: Box<dyn Element>)
|
||||||
{
|
{
|
||||||
// Add index of current element to scope's reference table
|
// TODO: RefTable
|
||||||
if let Some(referenceable) = elem.as_referenceable()
|
|
||||||
{
|
self.content()
|
||||||
// Only add if referenceable holds a reference
|
.borrow_mut()
|
||||||
if let Some(ref_name) = referenceable.reference_name()
|
.push(elem);
|
||||||
{
|
|
||||||
self.scope.borrow_mut().referenceable.insert(ref_name.clone(), self.content.borrow().len());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.content.borrow_mut().push(elem);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn last_element<T: Element>(&self, recurse: bool) -> Option<Ref<'_, T>>
|
/*
|
||||||
|
fn last_element(&'a self, recurse: bool) -> Option<Ref<'_, dyn Element>>
|
||||||
{
|
{
|
||||||
let elem = Ref::filter_map(self.content.borrow(),
|
let elem = Ref::filter_map(self.content().borrow(),
|
||||||
|content| content.last()
|
|content| content.last()
|
||||||
.and_then(|last| last.downcast_ref::<T>())).ok();
|
.and_then(|last| last.downcast_ref::<Element>())
|
||||||
|
).ok();
|
||||||
|
|
||||||
|
|
||||||
if elem.is_some() || !recurse { return elem }
|
if elem.is_some() || !recurse { return elem }
|
||||||
|
|
||||||
match self.parent
|
match self.parent()
|
||||||
{
|
{
|
||||||
None => None,
|
None => None,
|
||||||
Some(parent) => parent.last_element(true),
|
Some(parent) => parent.last_element(true),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn last_element_mut<T: Element>(&self, recurse: bool) -> Option<RefMut<'_, T>>
|
fn last_element_mut(&'a self, recurse: bool) -> Option<RefMut<'_, dyn Element>>
|
||||||
{
|
{
|
||||||
let elem = RefMut::filter_map(self.content.borrow_mut(),
|
let elem = RefMut::filter_map(self.content().borrow_mut(),
|
||||||
|content| content.last_mut()
|
|content| content.last_mut()).ok();
|
||||||
.and_then(|last| last.downcast_mut::<T>())).ok();
|
|
||||||
|
|
||||||
if elem.is_some() || !recurse { return elem }
|
if elem.is_some() || !recurse { return elem }
|
||||||
|
|
||||||
match self.parent
|
match self.parent()
|
||||||
{
|
{
|
||||||
None => None,
|
None => None,
|
||||||
Some(parent) => parent.last_element_mut(true),
|
Some(parent) => parent.last_element_mut(true),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
pub fn get_reference(&self, ref_name: &str) -> Option<(&Document<'a>, std::cell::Ref<'_, Box<dyn Element>>)> {
|
fn add_variable(&self, variable: Rc<dyn Variable>)
|
||||||
match self.scope.borrow().referenceable.get(ref_name) {
|
|
||||||
// Return if found
|
|
||||||
Some(elem) => {
|
|
||||||
return Some((&self,
|
|
||||||
std::cell::Ref::map(self.content.borrow(),
|
|
||||||
|m| &m[*elem])))
|
|
||||||
},
|
|
||||||
|
|
||||||
// Continue search recursively
|
|
||||||
None => match self.parent {
|
|
||||||
Some(parent) => return parent.get_reference(ref_name),
|
|
||||||
|
|
||||||
// Not found
|
|
||||||
None => return None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_variable(&self, variable: Rc<dyn Variable>)
|
|
||||||
{
|
{
|
||||||
self.scope.borrow_mut().variables.insert(
|
self.scope().borrow_mut().variables.insert(
|
||||||
variable.name().to_string(),
|
variable.name().to_string(),
|
||||||
variable);
|
variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_variable<S: AsRef<str>>(&self, name: S) -> Option<(&Document<'a>, Rc<dyn Variable>)>
|
fn get_variable(&self, name: &str) -> Option<Rc<dyn Variable>>
|
||||||
{
|
{
|
||||||
match self.scope.borrow().variables.get(name.as_ref())
|
match self.scope().borrow().variables.get(name)
|
||||||
{
|
{
|
||||||
Some(variable) => {
|
Some(variable) => {
|
||||||
return Some((&self, variable.clone()));
|
return Some(variable.clone());
|
||||||
},
|
},
|
||||||
|
|
||||||
// Continue search recursively
|
// Continue search recursively
|
||||||
None => match self.parent {
|
None => match self.parent() {
|
||||||
Some(parent) => return parent.get_variable(name),
|
Some(parent) => return parent.get_variable(name),
|
||||||
|
|
||||||
// Not found
|
// Not found
|
||||||
|
@ -169,16 +141,16 @@ impl<'a> Document<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_variable<S: AsRef<str>>(&self, name: S) -> Option<(&Document<'a>, Rc<dyn Variable>)>
|
fn remove_variable(&self, name: &str) -> Option<Rc<dyn Variable>>
|
||||||
{
|
{
|
||||||
match self.scope.borrow_mut().variables.remove(name.as_ref())
|
match self.scope().borrow_mut().variables.remove(name)
|
||||||
{
|
{
|
||||||
Some(variable) => {
|
Some(variable) => {
|
||||||
return Some((&self, variable.clone()));
|
return Some(variable.clone());
|
||||||
},
|
},
|
||||||
|
|
||||||
// Continue search recursively
|
// Continue search recursively
|
||||||
None => match self.parent {
|
None => match self.parent() {
|
||||||
Some(parent) => return parent.remove_variable(name),
|
Some(parent) => return parent.remove_variable(name),
|
||||||
|
|
||||||
// Not found
|
// Not found
|
||||||
|
@ -188,23 +160,44 @@ impl<'a> Document<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Merges [`other`] into [`self`]
|
/// Merges [`other`] into [`self`]
|
||||||
pub fn merge(&self, other: Document, merge_as: Option<&String>)
|
fn merge(&self, content: &RefCell<Vec<Box<dyn Element>>>, scope: &RefCell<Scope>, merge_as: Option<&String>)
|
||||||
{
|
{
|
||||||
match merge_as
|
match merge_as
|
||||||
{
|
{
|
||||||
Some(merge_as) => self.scope.borrow_mut()
|
Some(merge_as) => self.scope().borrow_mut()
|
||||||
.merge(
|
.merge(
|
||||||
&mut *other.scope.borrow_mut(),
|
&mut *scope.borrow_mut(),
|
||||||
merge_as,
|
merge_as,
|
||||||
self.content.borrow().len()+1),
|
self.content().borrow().len()+1),
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Content
|
// Content
|
||||||
self.content.borrow_mut().extend((other.content.borrow_mut())
|
self.content().borrow_mut().extend((content.borrow_mut())
|
||||||
.drain(..)
|
.drain(..)
|
||||||
.map(|value| value));
|
.map(|value| value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait DocumentAccessors<'a>
|
||||||
|
{
|
||||||
|
fn last_element<T: Element>(&self) -> Option<Ref<'_, T>>;
|
||||||
|
fn last_element_mut<T: Element>(&self) -> Option<RefMut<'_, T>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> DocumentAccessors<'a> for dyn Document<'a> + '_
|
||||||
|
{
|
||||||
|
fn last_element<T: Element>(&self) -> Option<Ref<'_, T>>
|
||||||
|
{
|
||||||
|
Ref::filter_map(self.content().borrow(),
|
||||||
|
|content| content.last()
|
||||||
|
.and_then(|last| last.downcast_ref::<T>())).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn last_element_mut<T: Element>(&self) -> Option<RefMut<'_, T>>
|
||||||
|
{
|
||||||
|
RefMut::filter_map(self.content().borrow_mut(),
|
||||||
|
|content| content.last_mut()
|
||||||
|
.and_then(|last| last.downcast_mut::<T>())).ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ pub trait Element: Downcast
|
||||||
fn as_referenceable(&self) -> Option<&dyn ReferenceableElement> { None }
|
fn as_referenceable(&self) -> Option<&dyn ReferenceableElement> { None }
|
||||||
|
|
||||||
/// Compiles element
|
/// Compiles element
|
||||||
fn compile(&self, compiler: &Compiler, document: &Document) -> Result<String, String>;
|
fn compile(&self, compiler: &Compiler, document: &dyn Document) -> Result<String, String>;
|
||||||
}
|
}
|
||||||
impl_downcast!(Element);
|
impl_downcast!(Element);
|
||||||
|
|
||||||
|
|
38
src/document/langdocument.rs
Normal file
38
src/document/langdocument.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
|
use crate::parser::source::Source;
|
||||||
|
|
||||||
|
use super::{document::{Document, Scope}, element::Element};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct LangDocument<'a> {
|
||||||
|
source: Rc<dyn Source>,
|
||||||
|
parent: Option<&'a dyn Document<'a>>, /// Document's parent
|
||||||
|
|
||||||
|
// FIXME: Render these fields private
|
||||||
|
pub content: RefCell<Vec<Box<dyn Element>>>,
|
||||||
|
pub scope: RefCell<Scope>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> LangDocument<'a>
|
||||||
|
{
|
||||||
|
pub fn new(source: Rc<dyn Source>, parent: Option<&'a dyn Document<'a>>) -> Self
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
source: source,
|
||||||
|
parent: parent,
|
||||||
|
content: RefCell::new(Vec::new()),
|
||||||
|
scope: RefCell::new(Scope::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Document<'a> for LangDocument<'a> {
|
||||||
|
fn source(&self) -> Rc<dyn Source> { self.source.clone() }
|
||||||
|
|
||||||
|
fn parent(&self) -> Option<&'a dyn Document<'a>> { self.parent.and_then(|p| Some(p as &dyn Document<'a>)) }
|
||||||
|
|
||||||
|
fn content(&self) -> &RefCell<Vec<Box<dyn Element>>> { &self.content }
|
||||||
|
|
||||||
|
fn scope(&self) -> &RefCell<Scope> { &self.scope }
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
pub mod document;
|
pub mod document;
|
||||||
|
pub mod langdocument;
|
||||||
pub mod element;
|
pub mod element;
|
||||||
pub mod variable;
|
pub mod variable;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{path::PathBuf, rc::Rc};
|
use std::{path::PathBuf, rc::Rc};
|
||||||
use crate::{elements::text::Text, parser::{parser::Parser, source::{Source, Token, VirtualSource}}};
|
use crate::{elements::text::Text, parser::{parser::Parser, source::{Source, Token, VirtualSource}}};
|
||||||
use super::{document::Document};
|
use super::document::Document;
|
||||||
|
|
||||||
|
|
||||||
// TODO enforce to_string(from_string(to_string())) == to_string()
|
// TODO enforce to_string(from_string(to_string())) == to_string()
|
||||||
|
@ -15,7 +15,7 @@ pub trait Variable
|
||||||
/// Converts variable to a string
|
/// Converts variable to a string
|
||||||
fn to_string(&self) -> String;
|
fn to_string(&self) -> String;
|
||||||
|
|
||||||
fn parse<'a>(&self, location: Token, parser: &dyn Parser, document: &'a Document);
|
fn parse<'a>(&self, location: Token, parser: &dyn Parser, document: &'a dyn Document<'a>);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::fmt::Debug for dyn Variable
|
impl core::fmt::Debug for dyn Variable
|
||||||
|
@ -52,7 +52,7 @@ impl Variable for BaseVariable
|
||||||
|
|
||||||
fn to_string(&self) -> String { self.value.clone() }
|
fn to_string(&self) -> String { self.value.clone() }
|
||||||
|
|
||||||
fn parse<'a>(&self, _location: Token, parser: &dyn Parser, document: &'a Document) {
|
fn parse<'a>(&self, _location: Token, parser: &dyn Parser, document: &'a dyn Document<'a>) {
|
||||||
let source = Rc::new(VirtualSource::new(
|
let source = Rc::new(VirtualSource::new(
|
||||||
self.location().clone(),
|
self.location().clone(),
|
||||||
self.name().to_string(),
|
self.name().to_string(),
|
||||||
|
@ -90,12 +90,12 @@ impl Variable for PathVariable
|
||||||
|
|
||||||
fn to_string(&self) -> String { self.path.to_str().unwrap().to_string() }
|
fn to_string(&self) -> String { self.path.to_str().unwrap().to_string() }
|
||||||
|
|
||||||
fn parse<'a>(&self, location: Token, parser: &dyn Parser, document: &'a Document){
|
fn parse<'a>(&self, location: Token, parser: &dyn Parser, document: &'a dyn Document) {
|
||||||
// TODO: Avoid copying the location twice...
|
// TODO: Avoid copying the content...
|
||||||
// Maybe create a special VirtualSource where the `content()` method
|
// Maybe create a special VirtualSource where the `content()` method
|
||||||
// calls `Variable::to_string()`
|
// calls `Variable::to_string()`
|
||||||
let source = Rc::new(VirtualSource::new(
|
let source = Rc::new(VirtualSource::new(
|
||||||
location.clone(),
|
location,
|
||||||
self.name().to_string(),
|
self.name().to_string(),
|
||||||
self.to_string()));
|
self.to_string()));
|
||||||
|
|
||||||
|
|
|
@ -174,7 +174,7 @@ impl Element for Code {
|
||||||
|
|
||||||
fn to_string(&self) -> String { format!("{self:#?}") }
|
fn to_string(&self) -> String { format!("{self:#?}") }
|
||||||
|
|
||||||
fn compile(&self, compiler: &Compiler, _document: &Document)
|
fn compile(&self, compiler: &Compiler, _document: &dyn Document)
|
||||||
-> Result<String, String> {
|
-> Result<String, String> {
|
||||||
|
|
||||||
match compiler.target()
|
match compiler.target()
|
||||||
|
@ -226,7 +226,7 @@ impl CodeRule {
|
||||||
Self {
|
Self {
|
||||||
re: [
|
re: [
|
||||||
Regex::new(r"(?:^|\n)```(?:\[((?:\\.|[^\\\\])*?)\])?(.*?)(?:,(.*))?\n((?:\\(?:.|\n)|[^\\\\])*?)```").unwrap(),
|
Regex::new(r"(?:^|\n)```(?:\[((?:\\.|[^\\\\])*?)\])?(.*?)(?:,(.*))?\n((?:\\(?:.|\n)|[^\\\\])*?)```").unwrap(),
|
||||||
Regex::new(r"``(?:\[((?:\\.|[^\[\]\\])*?)\])?(?:(.*)(?:\n|,))?((?:\\(?:.|\n)|[^\\\\])*?)``").unwrap(),
|
Regex::new(r"``(?:\[((?:\\.|[^\[\]\\])*?)\])?(?:(.*?)(?:\n|,))?((?:\\(?:.|\n)|[^\\\\])*?)``").unwrap(),
|
||||||
],
|
],
|
||||||
properties: PropertyParser::new(props)
|
properties: PropertyParser::new(props)
|
||||||
}
|
}
|
||||||
|
@ -239,7 +239,7 @@ impl RegexRule for CodeRule
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
fn on_regex_match(&self, index: usize, parser: &dyn Parser, document: &Document, token: Token, matches: Captures)
|
fn on_regex_match<'a>(&self, index: usize, parser: &dyn Parser, document: &'a dyn Document, token: Token, matches: Captures)
|
||||||
-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
||||||
let mut reports = vec![];
|
let mut reports = vec![];
|
||||||
|
|
||||||
|
@ -328,7 +328,7 @@ impl RegexRule for CodeRule
|
||||||
}
|
}
|
||||||
|
|
||||||
let theme = document.get_variable("code.theme")
|
let theme = document.get_variable("code.theme")
|
||||||
.and_then(|(_doc, var)| Some(var.to_string()));
|
.and_then(|var| Some(var.to_string()));
|
||||||
|
|
||||||
if index == 0 // Block
|
if index == 0 // Block
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use mlua::{Function, Lua};
|
use mlua::{Function, Lua};
|
||||||
use regex::{Captures, Regex};
|
use regex::{Captures, Regex};
|
||||||
use crate::parser::{parser::Parser, rule::RegexRule, source::{Source, Token}};
|
use crate::{document::document::Document, parser::{parser::Parser, rule::RegexRule, source::{Source, Token}}};
|
||||||
use ariadne::{Report, Label, ReportKind};
|
use ariadne::{Report, Label, ReportKind};
|
||||||
use crate::{compiler::compiler::Compiler, document::{document::Document, element::{ElemKind, Element}}};
|
use crate::{compiler::compiler::Compiler, document::element::{ElemKind, Element}};
|
||||||
use std::{ops::Range, rc::Rc};
|
use std::{ops::Range, rc::Rc};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -24,7 +24,7 @@ impl Element for Comment
|
||||||
fn kind(&self) -> ElemKind { ElemKind::Invisible }
|
fn kind(&self) -> ElemKind { ElemKind::Invisible }
|
||||||
fn element_name(&self) -> &'static str { "Comment" }
|
fn element_name(&self) -> &'static str { "Comment" }
|
||||||
fn to_string(&self) -> String { format!("{self:#?}") }
|
fn to_string(&self) -> String { format!("{self:#?}") }
|
||||||
fn compile(&self, _compiler: &Compiler, _document: &Document)
|
fn compile(&self, _compiler: &Compiler, _document: &dyn Document)
|
||||||
-> Result<String, String> {
|
-> Result<String, String> {
|
||||||
Ok("".to_string())
|
Ok("".to_string())
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ impl RegexRule for CommentRule {
|
||||||
|
|
||||||
fn regexes(&self) -> &[Regex] { &self.re }
|
fn regexes(&self) -> &[Regex] { &self.re }
|
||||||
|
|
||||||
fn on_regex_match(&self, _: usize, parser: &dyn Parser, document: &Document, token: Token, matches: Captures)
|
fn on_regex_match<'a>(&self, _: usize, parser: &dyn Parser, document: &'a dyn Document, token: Token, matches: Captures)
|
||||||
-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
||||||
let mut reports = vec![];
|
let mut reports = vec![];
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use mlua::{Function, Lua};
|
use mlua::{Function, Lua};
|
||||||
use regex::Regex;
|
use regex::{Captures, Regex};
|
||||||
use crate::parser::{parser::{Parser, ReportColors}, rule::RegexRule, source::{Source, SourceFile, Token}};
|
use crate::{document::document::{DocumentAccessors, Document}, parser::{parser::{Parser, ReportColors}, rule::RegexRule, source::{Source, SourceFile, Token}}};
|
||||||
use ariadne::{Report, Fmt, Label, ReportKind};
|
use ariadne::{Report, Fmt, Label, ReportKind};
|
||||||
use crate::document::document::Document;
|
|
||||||
use std::{ops::Range, rc::Rc};
|
use std::{ops::Range, rc::Rc};
|
||||||
|
|
||||||
use super::paragraph::Paragraph;
|
use super::paragraph::Paragraph;
|
||||||
|
@ -35,8 +34,8 @@ impl RegexRule for ImportRule {
|
||||||
|
|
||||||
fn regexes(&self) -> &[Regex] { &self.re }
|
fn regexes(&self) -> &[Regex] { &self.re }
|
||||||
|
|
||||||
fn on_regex_match(&self, _: usize, parser: &dyn Parser, document: &Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
|
fn on_regex_match<'a>(&self, _: usize, parser: &dyn Parser, document: &'a dyn Document<'a>, token: Token, matches: Captures)
|
||||||
{
|
-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
|
|
||||||
// Path
|
// Path
|
||||||
|
@ -138,13 +137,11 @@ impl RegexRule for ImportRule {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO
|
let import_doc = parser.parse(import, Some(document));
|
||||||
let import_doc = parser.parse(import, Some(&document));
|
document.merge(import_doc.content(), import_doc.scope(), Some(&import_as));
|
||||||
|
|
||||||
document.merge(import_doc, Some(&import_as));
|
|
||||||
|
|
||||||
// Close paragraph
|
// Close paragraph
|
||||||
if document.last_element::<Paragraph>(false).is_some()
|
if document.last_element::<Paragraph>().is_some()
|
||||||
{
|
{
|
||||||
parser.push(document, Box::new(Paragraph::new(
|
parser.push(document, Box::new(Paragraph::new(
|
||||||
Token::new(token.end()..token.end(), token.source())
|
Token::new(token.end()..token.end(), token.source())
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use mlua::{Function, Lua};
|
use mlua::{Function, Lua};
|
||||||
use regex::Regex;
|
use regex::{Captures, Regex};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use crate::parser::{parser::Parser, rule::RegexRule, source::{Source, Token}, util};
|
use crate::parser::{parser::Parser, rule::RegexRule, source::{Source, Token}, util};
|
||||||
use ariadne::{Report, Fmt, Label, ReportKind};
|
use ariadne::{Report, Fmt, Label, ReportKind};
|
||||||
|
@ -26,7 +26,7 @@ impl Element for Link
|
||||||
fn kind(&self) -> ElemKind { ElemKind::Inline }
|
fn kind(&self) -> ElemKind { ElemKind::Inline }
|
||||||
fn element_name(&self) -> &'static str { "Link" }
|
fn element_name(&self) -> &'static str { "Link" }
|
||||||
fn to_string(&self) -> String { format!("{self:#?}") }
|
fn to_string(&self) -> String { format!("{self:#?}") }
|
||||||
fn compile(&self, compiler: &Compiler, _document: &Document) -> Result<String, String> {
|
fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result<String, String> {
|
||||||
match compiler.target()
|
match compiler.target()
|
||||||
{
|
{
|
||||||
Target::HTML => {
|
Target::HTML => {
|
||||||
|
@ -51,7 +51,7 @@ pub struct LinkRule {
|
||||||
|
|
||||||
impl LinkRule {
|
impl LinkRule {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self { re: [Regex::new(r"(?:^|\n)```(.*?)(?:,(.*))?\n((?:\\.|[^\[\]\\])*?)```").unwrap()] }
|
Self { re: [Regex::new(r"\[((?:\\.|[^\\\\])*?)\]\(((?:\\.|[^\\\\])*?)\)").unwrap()] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,8 +60,8 @@ impl RegexRule for LinkRule {
|
||||||
|
|
||||||
fn regexes(&self) -> &[Regex] { &self.re }
|
fn regexes(&self) -> &[Regex] { &self.re }
|
||||||
|
|
||||||
fn on_regex_match(&self, _: usize, parser: &dyn Parser, document: &Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
|
fn on_regex_match<'a>(&self, _: usize, parser: &dyn Parser, document: &'a dyn Document, token: Token, matches: Captures)
|
||||||
{
|
-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
let link_name = match matches.get(1)
|
let link_name = match matches.get(1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{any::Any, cell::Ref, ops::Range, rc::Rc};
|
use std::{any::Any, cell::Ref, ops::Range, rc::Rc};
|
||||||
|
|
||||||
use crate::{compiler::compiler::{Compiler, Target}, document::{document::Document, element::{ElemKind, Element}}, parser::{parser::Parser, rule::Rule, source::{Cursor, Source, Token, VirtualSource}}};
|
use crate::{compiler::compiler::{Compiler, Target}, document::{document::{Document, DocumentAccessors}, element::{ElemKind, Element}}, parser::{parser::Parser, rule::Rule, source::{Cursor, Source, Token, VirtualSource}}};
|
||||||
use ariadne::{Label, Report, ReportKind};
|
use ariadne::{Label, Report, ReportKind};
|
||||||
use mlua::{Function, Lua};
|
use mlua::{Function, Lua};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
@ -57,7 +57,7 @@ impl Element for List
|
||||||
|
|
||||||
fn to_string(&self) -> String { format!("{self:#?}") }
|
fn to_string(&self) -> String { format!("{self:#?}") }
|
||||||
|
|
||||||
fn compile(&self, compiler: &Compiler, document: &Document) -> Result<String, String> {
|
fn compile(&self, compiler: &Compiler, document: &dyn Document) -> Result<String, String> {
|
||||||
match compiler.target()
|
match compiler.target()
|
||||||
{
|
{
|
||||||
Target::HTML => {
|
Target::HTML => {
|
||||||
|
@ -196,10 +196,11 @@ impl ListRule {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_depth(depth: &str, document: &Document) -> Vec<(bool, usize)>
|
fn parse_depth(depth: &str, document: &dyn Document) -> Vec<(bool, usize)>
|
||||||
{
|
{
|
||||||
let mut parsed = vec![];
|
let mut parsed = vec![];
|
||||||
let prev_entry = document.last_element::<List>(true)
|
// FIXME: Previous iteration used to recursively retrieve the list indent
|
||||||
|
let prev_entry = document.last_element::<List>()
|
||||||
.and_then(|list| Ref::filter_map(list, |m| m.entries.last() ).ok() )
|
.and_then(|list| Ref::filter_map(list, |m| m.entries.last() ).ok() )
|
||||||
.and_then(|entry| Ref::filter_map(entry, |e| Some(&e.numbering)).ok() );
|
.and_then(|entry| Ref::filter_map(entry, |e| Some(&e.numbering)).ok() );
|
||||||
|
|
||||||
|
@ -246,7 +247,8 @@ impl Rule for ListRule
|
||||||
|m| Some((m.start(), Box::new([false;0]) as Box<dyn Any>)) )
|
|m| Some((m.start(), Box::new([false;0]) as Box<dyn Any>)) )
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_match<'a>(&self, parser: &dyn Parser, document: &'a Document<'a>, cursor: Cursor, _match_data: Option<Box<dyn Any>>) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
|
fn on_match<'a>(&self, parser: &dyn Parser, document: &'a dyn Document<'a>, cursor: Cursor, _match_data: Option<Box<dyn Any>>)
|
||||||
|
-> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
|
||||||
let mut reports = vec![];
|
let mut reports = vec![];
|
||||||
let content = cursor.source.content();
|
let content = cursor.source.content();
|
||||||
let (end_cursor, numbering, source) = match self.start_re.captures_at(content, cursor.pos) {
|
let (end_cursor, numbering, source) = match self.start_re.captures_at(content, cursor.pos) {
|
||||||
|
@ -310,8 +312,8 @@ impl Rule for ListRule
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let parsed_entry = parser.parse(Rc::new(source), Some(&document));
|
let parsed_entry = parser.parse(Rc::new(source), Some(document));
|
||||||
let mut parsed_paragraph = parsed_entry.last_element_mut::<Paragraph>(false).unwrap(); // Extract content from paragraph
|
let mut parsed_paragraph = parsed_entry.last_element_mut::<Paragraph>().unwrap(); // Extract content from paragraph
|
||||||
let entry = ListEntry::new(
|
let entry = ListEntry::new(
|
||||||
Token::new(cursor.pos..end_cursor.pos, cursor.source.clone()),
|
Token::new(cursor.pos..end_cursor.pos, cursor.source.clone()),
|
||||||
numbering,
|
numbering,
|
||||||
|
@ -319,14 +321,14 @@ impl Rule for ListRule
|
||||||
);
|
);
|
||||||
|
|
||||||
// Ger previous list, if none insert a new list
|
// Ger previous list, if none insert a new list
|
||||||
let mut list = match document.last_element_mut::<List>(false)
|
let mut list = match document.last_element_mut::<List>()
|
||||||
{
|
{
|
||||||
Some(last) => last,
|
Some(last) => last,
|
||||||
None => {
|
None => {
|
||||||
parser.push(document,
|
parser.push(document,
|
||||||
Box::new(List::new(
|
Box::new(List::new(
|
||||||
Token::new(cursor.pos..end_cursor.pos, cursor.source.clone()))));
|
Token::new(cursor.pos..end_cursor.pos, cursor.source.clone()))));
|
||||||
document.last_element_mut::<List>(false).unwrap()
|
document.last_element_mut::<List>().unwrap()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
list.push(entry);
|
list.push(entry);
|
||||||
|
|
|
@ -54,7 +54,7 @@ impl Element for Paragraph
|
||||||
|
|
||||||
fn to_string(&self) -> String { format!("{:#?}", self) }
|
fn to_string(&self) -> String { format!("{:#?}", self) }
|
||||||
|
|
||||||
fn compile(&self, compiler: &Compiler, document: &Document) -> Result<String, String> {
|
fn compile(&self, compiler: &Compiler, document: &dyn Document) -> Result<String, String> {
|
||||||
if self.content.is_empty() { return Ok(String::new()) }
|
if self.content.is_empty() { return Ok(String::new()) }
|
||||||
|
|
||||||
match compiler.target()
|
match compiler.target()
|
||||||
|
@ -109,7 +109,7 @@ impl Rule for ParagraphRule
|
||||||
.and_then(|m| Some((m.start(), Box::new([false;0]) as Box<dyn Any>)) )
|
.and_then(|m| Some((m.start(), Box::new([false;0]) as Box<dyn Any>)) )
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_match(&self, parser: &dyn Parser, document: &Document, cursor: Cursor, _match_data: Option<Box<dyn Any>>)
|
fn on_match(&self, parser: &dyn Parser, document: &dyn Document, cursor: Cursor, _match_data: Option<Box<dyn Any>>)
|
||||||
-> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
|
-> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
|
||||||
|
|
||||||
let end_cursor = match self.re.captures_at(cursor.source.content(), cursor.pos)
|
let end_cursor = match self.re.captures_at(cursor.source.content(), cursor.pos)
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
use mlua::{Function, Lua};
|
use mlua::{Error::BadArgument, Function, Lua};
|
||||||
use regex::{Captures, Regex};
|
use regex::{Captures, Regex};
|
||||||
use crate::{compiler::compiler::Compiler, document::element::{ElemKind, Element}, parser::{parser::Parser, rule::RegexRule, source::{Source, Token}, util::{self, Property, PropertyParser}}};
|
use crate::{compiler::compiler::Compiler, document::{document::Document, element::{ElemKind, Element}}, lua::kernel::CTX, parser::{parser::Parser, rule::RegexRule, source::{Source, Token}, util::{self, Property, PropertyParser}}};
|
||||||
use ariadne::{Fmt, Label, Report, ReportKind};
|
use ariadne::{Fmt, Label, Report, ReportKind};
|
||||||
use crate::document::document::Document;
|
use std::{collections::HashMap, ops::Range, rc::Rc, str::FromStr, sync::Arc};
|
||||||
use std::{collections::HashMap, ops::Range, rc::Rc, str::FromStr};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Raw {
|
struct Raw {
|
||||||
location: Token,
|
pub(self) location: Token,
|
||||||
kind: ElemKind,
|
pub(self) kind: ElemKind,
|
||||||
content: String,
|
pub(self) content: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Raw {
|
impl Raw {
|
||||||
|
@ -26,7 +25,7 @@ impl Element for Raw {
|
||||||
|
|
||||||
fn to_string(&self) -> String { format!("{self:#?}") }
|
fn to_string(&self) -> String { format!("{self:#?}") }
|
||||||
|
|
||||||
fn compile(&self, compiler: &Compiler, _document: &Document) -> Result<String, String> {
|
fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result<String, String> {
|
||||||
Ok(self.content.clone())
|
Ok(self.content.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +58,7 @@ impl RegexRule for RawRule
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
fn on_regex_match(&self, _index: usize, parser: &dyn Parser, document: &Document, token: Token, matches: Captures)
|
fn on_regex_match(&self, _index: usize, parser: &dyn Parser, document: &dyn Document, token: Token, matches: Captures)
|
||||||
-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
||||||
let mut reports = vec![];
|
let mut reports = vec![];
|
||||||
|
|
||||||
|
@ -154,15 +153,43 @@ impl RegexRule for RawRule
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
parser.push(document, Box::new(Raw::new(
|
parser.push(document, Box::new(Raw {
|
||||||
token.clone(),
|
location: token.clone(),
|
||||||
raw_kind,
|
kind: raw_kind,
|
||||||
raw_content
|
content: raw_content
|
||||||
)));
|
}));
|
||||||
|
|
||||||
reports
|
reports
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> {
|
||||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] }
|
let mut bindings = vec![];
|
||||||
|
|
||||||
|
bindings.push(("push".to_string(), lua.create_function(
|
||||||
|
|_, (kind, content): (String, String)| {
|
||||||
|
// Validate kind
|
||||||
|
let kind = match ElemKind::from_str(kind.as_str())
|
||||||
|
{
|
||||||
|
Ok(kind) => kind,
|
||||||
|
Err(e) => return Err(BadArgument {
|
||||||
|
to: Some("push".to_string()),
|
||||||
|
pos: 1,
|
||||||
|
name: Some("kind".to_string()),
|
||||||
|
cause: Arc::new(mlua::Error::external(
|
||||||
|
format!("Wrong section kind specified: {e}")))})
|
||||||
|
};
|
||||||
|
|
||||||
|
CTX.with_borrow(|ctx| ctx.as_ref().map(|ctx| {
|
||||||
|
ctx.parser.push(ctx.document, Box::new(Raw {
|
||||||
|
location: ctx.location.clone(),
|
||||||
|
kind,
|
||||||
|
content,
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}).unwrap()));
|
||||||
|
|
||||||
|
bindings
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use mlua::{Function, Lua};
|
use mlua::{Function, Lua};
|
||||||
use regex::{Captures, Regex};
|
use regex::{Captures, Regex};
|
||||||
use crate::{lua::kernel::{Kernel, KernelContext, KernelHolder}, parser::{parser::{Parser, ReportColors}, rule::RegexRule, source::{Source, Token, VirtualSource}, util}};
|
use crate::{document::document::Document, lua::kernel::{Kernel, KernelContext, KernelHolder}, parser::{parser::{Parser, ReportColors}, rule::RegexRule, source::{Source, Token, VirtualSource}, util}};
|
||||||
use ariadne::{Fmt, Label, Report, ReportKind};
|
use ariadne::{Fmt, Label, Report, ReportKind};
|
||||||
use crate::document::document::Document;
|
|
||||||
use std::{ops::Range, rc::Rc};
|
use std::{ops::Range, rc::Rc};
|
||||||
|
|
||||||
use super::text::Text;
|
use super::text::Text;
|
||||||
|
@ -18,7 +17,7 @@ impl ScriptRule {
|
||||||
Self {
|
Self {
|
||||||
re: [
|
re: [
|
||||||
Regex::new(r"(?:^|\n)@<(?:(.*)\n?)((?:\\.|[^\\\\])*?)(?:\n?)>@").unwrap(),
|
Regex::new(r"(?:^|\n)@<(?:(.*)\n?)((?:\\.|[^\\\\])*?)(?:\n?)>@").unwrap(),
|
||||||
Regex::new(r"%<([^\s[:alpha:]])?(?:\[(.*?)\])?((?:\\.|[^\\\\])*?)(?:\n?)>%").unwrap()
|
Regex::new(r"%<(?:\[(.*?)\])?([^\s[:alpha:]])?((?:\\.|[^\\\\])*?)(?:\n?)>%").unwrap()
|
||||||
],
|
],
|
||||||
eval_kinds: [
|
eval_kinds: [
|
||||||
("", "Eval"),
|
("", "Eval"),
|
||||||
|
@ -60,11 +59,11 @@ impl RegexRule for ScriptRule
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
fn on_regex_match(&self, index: usize, parser: &dyn Parser, document: &Document, token: Token, matches: Captures)
|
fn on_regex_match<'a>(&self, index: usize, parser: &dyn Parser, document: &'a dyn Document<'a>, token: Token, matches: Captures)
|
||||||
-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
||||||
let mut reports = vec![];
|
let mut reports = vec![];
|
||||||
|
|
||||||
let kernel_name = match matches.get(if index == 0 {1} else {2}) {
|
let kernel_name = match matches.get(1) {
|
||||||
None => "main".to_string(),
|
None => "main".to_string(),
|
||||||
Some(name) => {
|
Some(name) => {
|
||||||
match ScriptRule::validate_kernel_name(parser.colors(), name.as_str())
|
match ScriptRule::validate_kernel_name(parser.colors(), name.as_str())
|
||||||
|
@ -84,13 +83,7 @@ impl RegexRule for ScriptRule
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let kernel_name = matches.get(if index == 0 {1} else {2})
|
let kernel = parser.get_kernel(kernel_name.as_str()).unwrap_or_else(|| {
|
||||||
.and_then(|name| {
|
|
||||||
let trimmed = name.as_str().trim_start().trim_end();
|
|
||||||
(!trimmed.is_empty()).then_some(trimmed)
|
|
||||||
})
|
|
||||||
.unwrap_or("main");
|
|
||||||
let kernel = parser.get_kernel(kernel_name).unwrap_or_else(|| {
|
|
||||||
parser.insert_kernel(kernel_name.to_string(), Kernel::new(parser))
|
parser.insert_kernel(kernel_name.to_string(), Kernel::new(parser))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -143,7 +136,7 @@ impl RegexRule for ScriptRule
|
||||||
else // Eval
|
else // Eval
|
||||||
{
|
{
|
||||||
// Validate kind
|
// Validate kind
|
||||||
let kind = match matches.get(1) {
|
let kind = match matches.get(2) {
|
||||||
None => 0,
|
None => 0,
|
||||||
Some(kind) => {
|
Some(kind) => {
|
||||||
match self.validate_kind(parser.colors(), kind.as_str())
|
match self.validate_kind(parser.colors(), kind.as_str())
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use mlua::{Error::BadArgument, Function, Lua};
|
use mlua::{Error::BadArgument, Function, Lua};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use crate::{compiler::compiler::Target, lua::kernel::CTX, parser::{parser::Parser, rule::RegexRule, source::{Source, Token}}};
|
use crate::{compiler::compiler::Target, document::document::Document, lua::kernel::CTX, parser::{parser::Parser, rule::RegexRule, source::{Source, Token}}};
|
||||||
use ariadne::{Report, Fmt, Label, ReportKind};
|
use ariadne::{Report, Fmt, Label, ReportKind};
|
||||||
use crate::{compiler::compiler::Compiler, document::{document::Document, element::{ElemKind, Element, ReferenceableElement}}};
|
use crate::{compiler::compiler::Compiler, document::element::{ElemKind, Element, ReferenceableElement}};
|
||||||
use std::{ops::Range, rc::Rc, sync::Arc};
|
use std::{ops::Range, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -21,7 +21,7 @@ impl Element for Section
|
||||||
fn element_name(&self) -> &'static str { "Section" }
|
fn element_name(&self) -> &'static str { "Section" }
|
||||||
fn to_string(&self) -> String { format!("{self:#?}") }
|
fn to_string(&self) -> String { format!("{self:#?}") }
|
||||||
fn as_referenceable(&self) -> Option<&dyn ReferenceableElement> { Some(self) }
|
fn as_referenceable(&self) -> Option<&dyn ReferenceableElement> { Some(self) }
|
||||||
fn compile(&self, compiler: &Compiler, _document: &Document) -> Result<String, String> {
|
fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result<String, String> {
|
||||||
match compiler.target()
|
match compiler.target()
|
||||||
{
|
{
|
||||||
Target::HTML => {
|
Target::HTML => {
|
||||||
|
@ -61,7 +61,7 @@ impl RegexRule for SectionRule {
|
||||||
|
|
||||||
fn regexes(&self) -> &[Regex] { &self.re }
|
fn regexes(&self) -> &[Regex] { &self.re }
|
||||||
|
|
||||||
fn on_regex_match(&self, _: usize, parser: &dyn Parser, document: &Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
|
fn on_regex_match(&self, _: usize, parser: &dyn Parser, document: &dyn Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
|
||||||
{
|
{
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
let section_depth = match matches.get(1)
|
let section_depth = match matches.get(1)
|
||||||
|
@ -89,6 +89,7 @@ impl RegexRule for SectionRule {
|
||||||
// [Optional] Reference name
|
// [Optional] Reference name
|
||||||
let section_refname = matches.get(2).map_or_else(|| None,
|
let section_refname = matches.get(2).map_or_else(|| None,
|
||||||
|refname| {
|
|refname| {
|
||||||
|
/* TODO: Wait for reference rework
|
||||||
// Check for duplicate reference
|
// Check for duplicate reference
|
||||||
if let Some((ref_doc, reference)) = document.get_reference(refname.as_str())
|
if let Some((ref_doc, reference)) = document.get_reference(refname.as_str())
|
||||||
{
|
{
|
||||||
|
@ -112,6 +113,7 @@ impl RegexRule for SectionRule {
|
||||||
.with_note(format!("Previous reference was overwritten"))
|
.with_note(format!("Previous reference was overwritten"))
|
||||||
.finish());
|
.finish());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
Some(refname.as_str().to_string())
|
Some(refname.as_str().to_string())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use mlua::{Function, Lua};
|
use mlua::{Function, Lua};
|
||||||
use regex::{Captures, Regex};
|
use regex::{Captures, Regex};
|
||||||
use crate::{compiler::compiler::{Compiler, Target}, document::element::{ElemKind, Element}, parser::{parser::Parser, rule::RegexRule, source::{Source, Token}, state::State}};
|
use crate::{compiler::compiler::{Compiler, Target}, document::{document::{DocumentAccessors, Document}, element::{ElemKind, Element}}, parser::{parser::Parser, rule::RegexRule, source::{Source, Token}, state::State}};
|
||||||
use ariadne::{Fmt, Label, Report, ReportKind};
|
use ariadne::{Fmt, Label, Report, ReportKind};
|
||||||
use crate::document::document::Document;
|
|
||||||
use crate::parser::state::Scope;
|
use crate::parser::state::Scope;
|
||||||
use std::{cell::RefCell, ops::Range, rc::Rc};
|
use std::{cell::RefCell, ops::Range, rc::Rc};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
@ -29,7 +28,7 @@ impl Element for Style
|
||||||
fn kind(&self) -> ElemKind { ElemKind::Inline }
|
fn kind(&self) -> ElemKind { ElemKind::Inline }
|
||||||
fn element_name(&self) -> &'static str { "Section" }
|
fn element_name(&self) -> &'static str { "Section" }
|
||||||
fn to_string(&self) -> String { format!("{self:#?}") }
|
fn to_string(&self) -> String { format!("{self:#?}") }
|
||||||
fn compile(&self, compiler: &Compiler, _document: &Document) -> Result<String, String> {
|
fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result<String, String> {
|
||||||
match compiler.target()
|
match compiler.target()
|
||||||
{
|
{
|
||||||
Target::HTML => {
|
Target::HTML => {
|
||||||
|
@ -66,7 +65,7 @@ impl State for StyleState
|
||||||
{
|
{
|
||||||
fn scope(&self) -> Scope { Scope::PARAGRAPH }
|
fn scope(&self) -> Scope { Scope::PARAGRAPH }
|
||||||
|
|
||||||
fn on_remove<'a>(&self, parser: &dyn Parser, document: &Document) -> Vec<Report<'a, (Rc<dyn Source>, Range<usize>)>> {
|
fn on_remove<'a>(&self, parser: &dyn Parser, document: &dyn Document) -> Vec<Report<'a, (Rc<dyn Source>, Range<usize>)>> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
self.toggled
|
self.toggled
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -80,7 +79,7 @@ impl State for StyleState
|
||||||
|
|
||||||
//let active_range = range.start .. paragraph.location().end()-1;
|
//let active_range = range.start .. paragraph.location().end()-1;
|
||||||
|
|
||||||
let paragraph = document.last_element::<Paragraph>(false).unwrap();
|
let paragraph = document.last_element::<Paragraph>().unwrap();
|
||||||
let paragraph_end = paragraph.content.last()
|
let paragraph_end = paragraph.content.last()
|
||||||
.and_then(|last| Some((last.location().source(), last.location().end()-1 .. last.location().end())))
|
.and_then(|last| Some((last.location().source(), last.location().end()-1 .. last.location().end())))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -145,7 +144,7 @@ impl RegexRule for StyleRule
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
fn on_regex_match(&self, index: usize, parser: &dyn Parser, document: &Document, token: Token, _matches: Captures) -> Vec<Report<(Rc<dyn Source>, Range<usize>)>> {
|
fn on_regex_match(&self, index: usize, parser: &dyn Parser, document: &dyn Document, token: Token, _matches: Captures) -> Vec<Report<(Rc<dyn Source>, Range<usize>)>> {
|
||||||
let result = vec![];
|
let result = vec![];
|
||||||
|
|
||||||
let query = parser.state().query(&STATE_NAME);
|
let query = parser.state().query(&STATE_NAME);
|
||||||
|
|
|
@ -123,7 +123,7 @@ impl Element for Tex {
|
||||||
|
|
||||||
fn to_string(&self) -> String { format!("{self:#?}") }
|
fn to_string(&self) -> String { format!("{self:#?}") }
|
||||||
|
|
||||||
fn compile(&self, compiler: &Compiler, document: &Document)
|
fn compile(&self, compiler: &Compiler, document: &dyn Document)
|
||||||
-> Result<String, String> {
|
-> Result<String, String> {
|
||||||
|
|
||||||
match compiler.target() {
|
match compiler.target() {
|
||||||
|
@ -136,18 +136,18 @@ impl Element for Tex {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let exec = document.get_variable(format!("tex.{}.exec", self.env))
|
let exec = document.get_variable(format!("tex.{}.exec", self.env).as_str())
|
||||||
.map_or("latex2svg".to_string(), |(_, var)| var.to_string());
|
.map_or("latex2svg".to_string(), |var| var.to_string());
|
||||||
// FIXME: Because fontsize is passed as an arg, verify that it cannot be used to execute python/shell code
|
// FIXME: Because fontsize is passed as an arg, verify that it cannot be used to execute python/shell code
|
||||||
let fontsize = document.get_variable(format!("tex.{}.fontsize", self.env))
|
let fontsize = document.get_variable(format!("tex.{}.fontsize", self.env).as_str())
|
||||||
.map_or("12".to_string(), |(_, var)| var.to_string());
|
.map_or("12".to_string(), |var| var.to_string());
|
||||||
let preamble = document.get_variable(format!("tex.{}.preamble", self.env))
|
let preamble = document.get_variable(format!("tex.{}.preamble", self.env).as_str())
|
||||||
.map_or("".to_string(), |(_, var)| var.to_string());
|
.map_or("".to_string(), |var| var.to_string());
|
||||||
let prepend = if self.block == TexKind::Inline { "".to_string() }
|
let prepend = if self.block == TexKind::Inline { "".to_string() }
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
document.get_variable(format!("tex.{}.block_prepend", self.env))
|
document.get_variable(format!("tex.{}.block_prepend", self.env).as_str())
|
||||||
.map_or("".to_string(), |(_, var)| var.to_string()+"\n")
|
.map_or("".to_string(), |var| var.to_string()+"\n")
|
||||||
};
|
};
|
||||||
|
|
||||||
let latex = match self.block
|
let latex = match self.block
|
||||||
|
@ -205,7 +205,7 @@ impl RegexRule for TexRule
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
fn on_regex_match(&self, index: usize, parser: &dyn Parser, document: &Document, token: Token, matches: Captures)
|
fn on_regex_match(&self, index: usize, parser: &dyn Parser, document: &dyn Document, token: Token, matches: Captures)
|
||||||
-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
-> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
||||||
let mut reports = vec![];
|
let mut reports = vec![];
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use mlua::{Function, Lua};
|
use mlua::{Function, Lua};
|
||||||
|
|
||||||
use crate::{compiler::compiler::Compiler, document::{document::Document, element::{ElemKind, Element}}, lua::kernel::CTX, parser::{rule::Rule, source::Token}};
|
use crate::{compiler::compiler::Compiler, document::{document::Document, element::{ElemKind, Element}}, lua::kernel::CTX, parser::{parser::Parser, rule::Rule, source::Token}};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Text
|
pub struct Text
|
||||||
|
@ -27,7 +27,7 @@ impl Element for Text
|
||||||
fn element_name(&self) -> &'static str { "Text" }
|
fn element_name(&self) -> &'static str { "Text" }
|
||||||
fn to_string(&self) -> String { format!("{self:#?}") }
|
fn to_string(&self) -> String { format!("{self:#?}") }
|
||||||
|
|
||||||
fn compile(&self, compiler: &Compiler, _document: &Document) -> Result<String, String> {
|
fn compile(&self, compiler: &Compiler, _document: &dyn Document) -> Result<String, String> {
|
||||||
Ok(compiler.sanitize(self.content.as_str()))
|
Ok(compiler.sanitize(self.content.as_str()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,11 +41,10 @@ impl Rule for TextRule
|
||||||
|
|
||||||
fn next_match(&self, cursor: &crate::parser::source::Cursor) -> Option<(usize, Box<dyn std::any::Any>)> { None }
|
fn next_match(&self, cursor: &crate::parser::source::Cursor) -> Option<(usize, Box<dyn std::any::Any>)> { None }
|
||||||
|
|
||||||
fn on_match(&self, parser: &dyn crate::parser::parser::Parser, document: &crate::document::document::Document, cursor: crate::parser::source::Cursor, match_data: Option<Box<dyn std::any::Any>>) -> (crate::parser::source::Cursor, Vec<ariadne::Report<'_, (std::rc::Rc<dyn crate::parser::source::Source>, std::ops::Range<usize>)>>) { panic!("Text canno match"); }
|
fn on_match(&self, parser: &dyn Parser, document: &dyn Document, cursor: crate::parser::source::Cursor, match_data: Option<Box<dyn std::any::Any>>) -> (crate::parser::source::Cursor, Vec<ariadne::Report<'_, (std::rc::Rc<dyn crate::parser::source::Source>, std::ops::Range<usize>)>>) { panic!("Text canno match"); }
|
||||||
|
|
||||||
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> {
|
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> {
|
||||||
let mut bindings = vec![];
|
let mut bindings = vec![];
|
||||||
|
|
||||||
bindings.push(("push".to_string(), lua.create_function(
|
bindings.push(("push".to_string(), lua.create_function(
|
||||||
|_, content: String| {
|
|_, content: String| {
|
||||||
CTX.with_borrow(|ctx| ctx.as_ref().map(|ctx| {
|
CTX.with_borrow(|ctx| ctx.as_ref().map(|ctx| {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use mlua::{Function, Lua};
|
use mlua::{Function, Lua};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use crate::parser::{parser::{Parser, ReportColors}, rule::RegexRule, source::{Source, Token}};
|
use crate::{document::document::Document, parser::{parser::{Parser, ReportColors}, rule::RegexRule, source::{Source, Token}}};
|
||||||
use ariadne::{Report, Fmt, Label, ReportKind};
|
use ariadne::{Report, Fmt, Label, ReportKind};
|
||||||
use crate::document::{document::Document, variable::{BaseVariable, PathVariable, Variable}};
|
use crate::document::variable::{BaseVariable, PathVariable, Variable};
|
||||||
use std::{ops::Range, rc::Rc};
|
use std::{ops::Range, rc::Rc};
|
||||||
|
|
||||||
pub struct VariableRule {
|
pub struct VariableRule {
|
||||||
|
@ -91,7 +91,7 @@ impl RegexRule for VariableRule {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn on_regex_match(&self, _: usize, parser: &dyn Parser, document: &Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
|
fn on_regex_match<'a>(&self, _: usize, parser: &dyn Parser, document: &'a dyn Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
|
||||||
{
|
{
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
// [Optional] variable kind
|
// [Optional] variable kind
|
||||||
|
@ -223,7 +223,7 @@ impl RegexRule for VariableSubstitutionRule
|
||||||
|
|
||||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||||
|
|
||||||
fn on_regex_match(&self, _index: usize, parser: &dyn Parser, document: &Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
fn on_regex_match<'a>(&self, _index: usize, parser: &dyn Parser, document: &'a dyn Document<'a>, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
|
|
||||||
let variable = match matches.get(1)
|
let variable = match matches.get(1)
|
||||||
|
@ -307,27 +307,13 @@ impl RegexRule for VariableSubstitutionRule
|
||||||
.finish());
|
.finish());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
Some((_, var)) => var,
|
Some(var) => var,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => panic!("Unknown error")
|
_ => panic!("Unknown error")
|
||||||
};
|
};
|
||||||
|
|
||||||
variable.parse(token, parser, document);
|
variable.parse(token, parser, document);
|
||||||
//let parsed = variable.parse(
|
|
||||||
// token,
|
|
||||||
// parser,
|
|
||||||
// document
|
|
||||||
//);
|
|
||||||
////document.merge(parsed, None);
|
|
||||||
//parsed.content.borrow_mut()
|
|
||||||
// .drain(..)
|
|
||||||
// .for_each(|elem| parser.push(document, elem));
|
|
||||||
//parser.push(document, )
|
|
||||||
|
|
||||||
// TODO: Full rework of document
|
|
||||||
// parser shound parse into previous document, and not into a new document
|
|
||||||
// This should prevent having to sue `recurse: bool` in the last_element getters
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,20 +71,36 @@ pub fn semantic_token_from_document(document: &Document) -> Vec<SemanticToken>
|
||||||
source: source.clone()
|
source: source.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
document.content.borrow()
|
semantic_tokens.push(SemanticToken {
|
||||||
.iter()
|
delta_line: 1,
|
||||||
.for_each(|elem| {
|
delta_start: 1,
|
||||||
if let Some(paragraph) = elem.downcast_ref::<Paragraph>()
|
length: 5,
|
||||||
{
|
token_type: 0,
|
||||||
paragraph.content
|
token_modifiers_bitset: 0,
|
||||||
.iter()
|
|
||||||
.for_each(|elem| provide(&mut semantic_tokens, &mut cursor, elem));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
provide(&mut semantic_tokens, &mut cursor, elem);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
semantic_tokens.push(SemanticToken {
|
||||||
|
delta_line: 1,
|
||||||
|
delta_start: 1,
|
||||||
|
length: 5,
|
||||||
|
token_type: 1,
|
||||||
|
token_modifiers_bitset: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
//document.content.borrow()
|
||||||
|
// .iter()
|
||||||
|
// .for_each(|elem| {
|
||||||
|
// if let Some(paragraph) = elem.downcast_ref::<Paragraph>()
|
||||||
|
// {
|
||||||
|
// paragraph.content
|
||||||
|
// .iter()
|
||||||
|
// .for_each(|elem| provide(&mut semantic_tokens, &mut cursor, elem));
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// provide(&mut semantic_tokens, &mut cursor, elem);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
semantic_tokens
|
semantic_tokens
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
use std::{cell::{RefCell, RefMut}, rc::Rc};
|
use std::cell::{RefCell, RefMut};
|
||||||
|
|
||||||
use mlua::{Error, FromLua, Lua, UserData, UserDataMethods};
|
use mlua::Lua;
|
||||||
|
|
||||||
use crate::{document::document::Document, parser::{parser::Parser, source::Token}};
|
use crate::{document::document::Document, parser::{parser::Parser, source::Token}};
|
||||||
|
|
||||||
pub struct KernelContext<'a>
|
pub struct KernelContext<'a, 'b>
|
||||||
{
|
{
|
||||||
pub location: Token,
|
pub location: Token,
|
||||||
pub parser: &'a dyn Parser,
|
pub parser: &'a dyn Parser,
|
||||||
pub document: &'a Document<'a>,
|
pub document: &'b dyn Document<'b>,
|
||||||
//pub parser: &'a dyn Parser,
|
//pub parser: &'a dyn Parser,
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
pub static CTX: RefCell<Option<KernelContext<'static>>> = RefCell::new(None);
|
pub static CTX: RefCell<Option<KernelContext<'static, 'static>>> = RefCell::new(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -23,7 +23,6 @@ pub struct Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Kernel {
|
impl Kernel {
|
||||||
|
|
||||||
// TODO: Take parser as arg and
|
// TODO: Take parser as arg and
|
||||||
// iterate over the rules
|
// iterate over the rules
|
||||||
// to find export the bindings (if some)
|
// to find export the bindings (if some)
|
||||||
|
|
25
src/main.rs
25
src/main.rs
|
@ -75,26 +75,27 @@ fn main() {
|
||||||
if debug_opts.contains(&"ast".to_string())
|
if debug_opts.contains(&"ast".to_string())
|
||||||
{
|
{
|
||||||
println!("-- BEGIN AST DEBUGGING --");
|
println!("-- BEGIN AST DEBUGGING --");
|
||||||
doc.content.borrow().iter().for_each(|elem| {
|
doc.content().borrow().iter().for_each(|elem| {
|
||||||
println!("{}", (elem).to_string())
|
println!("{}", (elem).to_string())
|
||||||
});
|
});
|
||||||
println!("-- END AST DEBUGGING --");
|
println!("-- END AST DEBUGGING --");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if debug_opts.contains(&"ref".to_string())
|
// TODO
|
||||||
{
|
//if debug_opts.contains(&"ref".to_string())
|
||||||
println!("-- BEGIN REFERENCES DEBUGGING --");
|
//{
|
||||||
let sc = doc.scope.borrow();
|
// println!("-- BEGIN REFERENCES DEBUGGING --");
|
||||||
sc.referenceable.iter().for_each(|(name, pos)| {
|
// let sc = doc.scope.borrow();
|
||||||
println!(" - {name}: `{:#?}`", doc.content.borrow()[*pos]);
|
// sc.referenceable.iter().for_each(|(name, pos)| {
|
||||||
});
|
// println!(" - {name}: `{:#?}`", doc.content.borrow()[*pos]);
|
||||||
println!("-- END REFERENCES DEBUGGING --");
|
// });
|
||||||
}
|
// println!("-- END REFERENCES DEBUGGING --");
|
||||||
|
//}
|
||||||
if debug_opts.contains(&"var".to_string())
|
if debug_opts.contains(&"var".to_string())
|
||||||
{
|
{
|
||||||
println!("-- BEGIN VARIABLES DEBUGGING --");
|
println!("-- BEGIN VARIABLES DEBUGGING --");
|
||||||
let sc = doc.scope.borrow();
|
let sc = doc.scope().borrow();
|
||||||
sc.variables.iter().for_each(|(_name, var)| {
|
sc.variables.iter().for_each(|(_name, var)| {
|
||||||
println!(" - `{:#?}`", var);
|
println!(" - `{:#?}`", var);
|
||||||
});
|
});
|
||||||
|
@ -103,7 +104,7 @@ fn main() {
|
||||||
|
|
||||||
|
|
||||||
let compiler = Compiler::new(compiler::compiler::Target::HTML, db_path);
|
let compiler = Compiler::new(compiler::compiler::Target::HTML, db_path);
|
||||||
let out = compiler.compile(&doc);
|
let out = compiler.compile(doc.as_ref());
|
||||||
|
|
||||||
std::fs::write("a.html", out).unwrap();
|
std::fs::write("a.html", out).unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use std::{cell::{RefCell, RefMut}, collections::{HashMap, HashSet}, ops::Range, rc::Rc};
|
use std::{cell::{Ref, RefCell, RefMut}, collections::{HashMap, HashSet}, ops::Range, rc::Rc};
|
||||||
|
|
||||||
use ariadne::{Label, Report};
|
use ariadne::{Label, Report};
|
||||||
|
|
||||||
use crate::{document::{document::Document, element::{ElemKind, Element}}, elements::{paragraph::Paragraph, registrar::register, text::Text}, lua::kernel::{Kernel, KernelHolder}, parser::source::{SourceFile, VirtualSource}};
|
use crate::{document::{document::{DocumentAccessors, Document}, element::{ElemKind, Element}, langdocument::LangDocument}, elements::{paragraph::Paragraph, registrar::register, text::Text}, lua::kernel::{Kernel, KernelHolder}, parser::source::{SourceFile, VirtualSource}};
|
||||||
|
|
||||||
use super::{parser::{Parser, ReportColors}, rule::Rule, source::{Cursor, Source, Token}, state::StateHolder, util};
|
use super::{parser::{Parser, ReportColors}, rule::Rule, source::{Cursor, Source, Token}, state::StateHolder, util};
|
||||||
|
|
||||||
|
@ -132,14 +132,14 @@ impl Parser for LangParser
|
||||||
fn state_mut(&self) -> std::cell::RefMut<'_, StateHolder> { self.state.borrow_mut() }
|
fn state_mut(&self) -> std::cell::RefMut<'_, StateHolder> { self.state.borrow_mut() }
|
||||||
|
|
||||||
/// Add an [`Element`] to the [`Document`]
|
/// Add an [`Element`] to the [`Document`]
|
||||||
fn push<'a>(&self, doc: &'a Document<'a>, elem: Box<dyn Element>)
|
fn push<'a>(&self, doc: &dyn Document, elem: Box<dyn Element>)
|
||||||
{
|
{
|
||||||
if elem.kind() == ElemKind::Inline || elem.kind() == ElemKind::Invisible
|
if elem.kind() == ElemKind::Inline || elem.kind() == ElemKind::Invisible
|
||||||
{
|
{
|
||||||
let mut paragraph = doc.last_element_mut::<Paragraph>(false)
|
let mut paragraph = doc.last_element_mut::<Paragraph>()
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
doc.push(Box::new(Paragraph::new(elem.location().clone())));
|
doc.push(Box::new(Paragraph::new(elem.location().clone())));
|
||||||
doc.last_element_mut::<Paragraph>(false)
|
doc.last_element_mut::<Paragraph>()
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
|
|
||||||
paragraph.push(elem);
|
paragraph.push(elem);
|
||||||
|
@ -147,20 +147,20 @@ impl Parser for LangParser
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Process paragraph events
|
// Process paragraph events
|
||||||
if doc.last_element_mut::<Paragraph>(false)
|
if doc.last_element::<Paragraph>()
|
||||||
.is_some_and(|_| true)
|
.is_some_and(|_| true)
|
||||||
{
|
{
|
||||||
self.handle_reports(doc.source(),
|
self.handle_reports(doc.source(),
|
||||||
self.state_mut().on_scope_end(self, &doc, super::state::Scope::PARAGRAPH));
|
self.state_mut().on_scope_end(self, doc, super::state::Scope::PARAGRAPH));
|
||||||
}
|
}
|
||||||
|
|
||||||
doc.push(elem);
|
doc.push(elem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse<'a>(&self, source: Rc<dyn Source>, parent: Option<&'a Document<'a>>) -> Document<'a>
|
fn parse<'a>(&self, source: Rc<dyn Source>, parent: Option<&'a dyn Document<'a>>) -> Box<dyn Document<'a>+'a>
|
||||||
{
|
{
|
||||||
let doc = Document::new(source.clone(), parent);
|
let doc = LangDocument::new(source.clone(), parent);
|
||||||
let mut matches = Vec::new();
|
let mut matches = Vec::new();
|
||||||
for _ in 0..self.rules.len() {
|
for _ in 0..self.rules.len() {
|
||||||
matches.push((0usize, None));
|
matches.push((0usize, None));
|
||||||
|
@ -169,10 +169,10 @@ impl Parser for LangParser
|
||||||
let content = source.content();
|
let content = source.content();
|
||||||
let mut cursor = Cursor::new(0usize, doc.source()); // Cursor in file
|
let mut cursor = Cursor::new(0usize, doc.source()); // Cursor in file
|
||||||
|
|
||||||
if parent.is_some() // Terminate parent's paragraph state
|
if let Some(parent) = parent // Terminate parent's paragraph state
|
||||||
{
|
{
|
||||||
self.handle_reports(parent.as_ref().unwrap().source(),
|
self.handle_reports(parent.source(),
|
||||||
self.state_mut().on_scope_end(self, parent.as_ref().unwrap(), super::state::Scope::PARAGRAPH));
|
self.state_mut().on_scope_end(self, parent, super::state::Scope::PARAGRAPH));
|
||||||
}
|
}
|
||||||
|
|
||||||
loop
|
loop
|
||||||
|
@ -193,7 +193,8 @@ impl Parser for LangParser
|
||||||
{
|
{
|
||||||
|
|
||||||
// Rule callback
|
// Rule callback
|
||||||
let (new_cursor, reports) = (*rule).on_match(self, &doc, rule_pos, match_data);
|
let dd: &'a dyn Document = unsafe {std::mem::transmute(&doc as &dyn Document)};
|
||||||
|
let (new_cursor, reports) = rule.on_match(self, dd, rule_pos, match_data);
|
||||||
|
|
||||||
self.handle_reports(doc.source(), reports);
|
self.handle_reports(doc.source(), reports);
|
||||||
|
|
||||||
|
@ -210,10 +211,10 @@ impl Parser for LangParser
|
||||||
self.handle_reports(doc.source(),
|
self.handle_reports(doc.source(),
|
||||||
self.state_mut().on_scope_end(self, &doc, super::state::Scope::DOCUMENT));
|
self.state_mut().on_scope_end(self, &doc, super::state::Scope::DOCUMENT));
|
||||||
|
|
||||||
return doc;
|
return Box::new(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_into<'a>(&self, source: Rc<dyn Source>, document: &'a Document<'a>)
|
fn parse_into<'a>(&self, source: Rc<dyn Source>, document: &'a dyn Document<'a>)
|
||||||
{
|
{
|
||||||
let mut matches = Vec::new();
|
let mut matches = Vec::new();
|
||||||
for _ in 0..self.rules.len() {
|
for _ in 0..self.rules.len() {
|
||||||
|
@ -228,10 +229,10 @@ impl Parser for LangParser
|
||||||
let (rule_pos, rule, match_data) = self.update_matches(&cursor, &mut matches);
|
let (rule_pos, rule, match_data) = self.update_matches(&cursor, &mut matches);
|
||||||
|
|
||||||
// Unmatched content
|
// Unmatched content
|
||||||
let text_content = util::process_text(&document, &content.as_str()[cursor.pos..rule_pos.pos]);
|
let text_content = util::process_text(document, &content.as_str()[cursor.pos..rule_pos.pos]);
|
||||||
if !text_content.is_empty()
|
if !text_content.is_empty()
|
||||||
{
|
{
|
||||||
self.push(&document, Box::new(Text::new(
|
self.push(document, Box::new(Text::new(
|
||||||
Token::new(cursor.pos..rule_pos.pos, source.clone()),
|
Token::new(cursor.pos..rule_pos.pos, source.clone()),
|
||||||
text_content
|
text_content
|
||||||
)));
|
)));
|
||||||
|
@ -240,7 +241,7 @@ impl Parser for LangParser
|
||||||
if let Some(rule) = rule
|
if let Some(rule) = rule
|
||||||
{
|
{
|
||||||
// Rule callback
|
// Rule callback
|
||||||
let (new_cursor, reports) = (*rule).on_match(self, &document, rule_pos, match_data);
|
let (new_cursor, reports) = (*rule).on_match(self, document, rule_pos, match_data);
|
||||||
|
|
||||||
self.handle_reports(document.source(), reports);
|
self.handle_reports(document.source(), reports);
|
||||||
|
|
||||||
|
|
|
@ -115,11 +115,11 @@ pub trait Parser: KernelHolder
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add an [`Element`] to the [`Document`]
|
/// Add an [`Element`] to the [`Document`]
|
||||||
fn push<'a>(&self, doc: &'a Document<'a>, elem: Box<dyn Element>);
|
fn push<'a>(&self, doc: &dyn Document, elem: Box<dyn Element>);
|
||||||
|
|
||||||
/// Parse [`Source`] into a new [`Document`]
|
/// Parse [`Source`] into a new [`Document`]
|
||||||
fn parse<'a>(&self, source: Rc<dyn Source>, parent: Option<&'a Document<'a>>) -> Document<'a>;
|
fn parse<'a>(&self, source: Rc<dyn Source>, parent: Option<&'a dyn Document<'a>>) -> Box<dyn Document<'a>+'a>;
|
||||||
|
|
||||||
/// Parse [`Source`] into an already existing [`Document`]
|
/// Parse [`Source`] into an already existing [`Document`]
|
||||||
fn parse_into<'a>(&self, source: Rc<dyn Source>, document: &'a Document<'a>);
|
fn parse_into<'a>(&self, source: Rc<dyn Source>, document: &'a dyn Document<'a>);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub trait Rule {
|
||||||
/// Finds the next match starting from [`cursor`]
|
/// Finds the next match starting from [`cursor`]
|
||||||
fn next_match(&self, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)>;
|
fn next_match(&self, cursor: &Cursor) -> Option<(usize, Box<dyn Any>)>;
|
||||||
/// Callback when rule matches
|
/// Callback when rule matches
|
||||||
fn on_match(&self, parser: &dyn Parser, document: &Document, cursor: Cursor, match_data: Option<Box<dyn Any>>) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>);
|
fn on_match<'a>(&self, parser: &dyn Parser, document: &'a (dyn Document<'a>+'a), cursor: Cursor, match_data: Option<Box<dyn Any>>) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>);
|
||||||
/// Export bindings to lua
|
/// Export bindings to lua
|
||||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)>;
|
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)>;
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ pub trait RegexRule
|
||||||
fn regexes(&self) -> &[regex::Regex];
|
fn regexes(&self) -> &[regex::Regex];
|
||||||
|
|
||||||
/// Callback on regex rule match
|
/// Callback on regex rule match
|
||||||
fn on_regex_match(&self, index: usize, parser: &dyn Parser, document: &Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>;
|
fn on_regex_match<'a>(&self, index: usize, parser: &dyn Parser, document: &'a (dyn Document<'a>+'a), token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>;
|
||||||
|
|
||||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)>;
|
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)>;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ impl<T: RegexRule> Rule for T {
|
||||||
(pos, Box::new(id) as Box<dyn Any>));
|
(pos, Box::new(id) as Box<dyn Any>));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_match(&self, parser: &dyn Parser, document: &Document, cursor: Cursor, match_data: Option<Box<dyn Any>>)
|
fn on_match<'a>(&self, parser: &dyn Parser, document: &'a (dyn Document<'a>+'a), cursor: Cursor, match_data: Option<Box<dyn Any>>)
|
||||||
-> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
|
-> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>) {
|
||||||
let content = cursor.source.content();
|
let content = cursor.source.content();
|
||||||
let index = unsafe { match_data.unwrap_unchecked().downcast::<usize>().unwrap_unchecked() };
|
let index = unsafe { match_data.unwrap_unchecked().downcast::<usize>().unwrap_unchecked() };
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub trait State: Downcast
|
||||||
fn scope(&self) -> Scope;
|
fn scope(&self) -> Scope;
|
||||||
|
|
||||||
/// Callback called when state goes out of scope
|
/// Callback called when state goes out of scope
|
||||||
fn on_remove<'a>(&self, parser: &dyn Parser, document: &Document) -> Vec<Report<'a, (Rc<dyn Source>, Range<usize>)>>;
|
fn on_remove<'a>(&self, parser: &dyn Parser, document: &dyn Document) -> Vec<Report<'a, (Rc<dyn Source>, Range<usize>)>>;
|
||||||
}
|
}
|
||||||
impl_downcast!(State);
|
impl_downcast!(State);
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ impl StateHolder
|
||||||
.map_or(None, |st| Some(st.clone()))
|
.map_or(None, |st| Some(st.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_scope_end(&mut self, parser: &dyn Parser, document: &Document, scope: Scope) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
|
pub fn on_scope_end(&mut self, parser: &dyn Parser, document: &dyn Document, scope: Scope) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
|
||||||
{
|
{
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
use crate::{document::{document::Document, element::ElemKind}, elements::paragraph::Paragraph};
|
use crate::{document::{document::{Document, DocumentAccessors}, element::ElemKind}, elements::paragraph::Paragraph};
|
||||||
|
|
||||||
/// Processes text for escape characters and paragraphing
|
/// Processes text for escape characters and paragraphing
|
||||||
pub fn process_text(document: &Document, content: &str) -> String
|
pub fn process_text(document: &dyn Document, content: &str) -> String
|
||||||
{
|
{
|
||||||
let mut escaped = false;
|
let mut escaped = false;
|
||||||
let mut newlines = 0usize; // Consecutive newlines
|
let mut newlines = 0usize; // Consecutive newlines
|
||||||
|
@ -30,7 +30,7 @@ pub fn process_text(document: &Document, content: &str) -> String
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if document.last_element::<Paragraph>(false)
|
if document.last_element::<Paragraph>()
|
||||||
.and_then(|par| par.find_back(|e| e.kind() != ElemKind::Invisible)
|
.and_then(|par| par.find_back(|e| e.kind() != ElemKind::Invisible)
|
||||||
.and_then(|e| Some(e.kind() == ElemKind::Inline)))
|
.and_then(|e| Some(e.kind() == ElemKind::Inline)))
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
|
@ -65,7 +65,7 @@ pub fn process_text(document: &Document, content: &str) -> String
|
||||||
// Content begins with whitespace
|
// Content begins with whitespace
|
||||||
if prev.is_none()
|
if prev.is_none()
|
||||||
{
|
{
|
||||||
if document.last_element::<Paragraph>(false).is_some()
|
if document.last_element::<Paragraph>().is_some()
|
||||||
{
|
{
|
||||||
return (out+g, Some(g));
|
return (out+g, Some(g));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue