Replace the old nom_context with the contents of new_context.
This commit is contained in:
parent
84fa1c3aae
commit
6cfc39ca45
@ -1,8 +1,7 @@
|
|||||||
mod list;
|
mod list;
|
||||||
mod new_context;
|
|
||||||
mod nom_context;
|
mod nom_context;
|
||||||
mod parser_with_context;
|
mod parser_with_context;
|
||||||
mod text;
|
mod text;
|
||||||
mod text_element_parser;
|
mod text_element_parser;
|
||||||
pub use text_element_parser::document;
|
pub use text_element_parser::document;
|
||||||
type Context<'r> = &'r new_context::ContextTree<'r>;
|
type Context<'r> = &'r nom_context::ContextTree<'r>;
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
use nom::bytes::complete::take;
|
|
||||||
use nom::combinator::not;
|
|
||||||
use nom::error::VerboseError;
|
|
||||||
use nom::IResult;
|
|
||||||
|
|
||||||
use super::list::List;
|
|
||||||
|
|
||||||
type Matcher = dyn for<'s> Fn(&'s str) -> IResult<&'s str, &'s str, VerboseError<&'s str>>;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct ContextTree<'r> {
|
|
||||||
tree: List<ContextElement<'r>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'r> ContextTree<'r> {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
ContextTree { tree: List::new() }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_additional_node(&self, data: ContextElement<'r>) -> ContextTree<'r> {
|
|
||||||
let new_list = self.tree.push_front(data);
|
|
||||||
ContextTree { tree: new_list }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn check_fail_matcher<'s>(
|
|
||||||
&'r self,
|
|
||||||
i: &'s str,
|
|
||||||
) -> IResult<&'s str, &'s str, VerboseError<&'s str>> {
|
|
||||||
// TODO: Can I do this without incrementing reference counters? Perhaps via implementing an iterator over the list?
|
|
||||||
let mut current_node = self.tree.clone();
|
|
||||||
while !current_node.is_empty() {
|
|
||||||
let context_element = current_node
|
|
||||||
.get_data()
|
|
||||||
.expect("While looop proves its Some()");
|
|
||||||
match context_element {
|
|
||||||
ContextElement::FailMatcherNode(fail_matcher) => {
|
|
||||||
match fail_matcher.fail_matcher {
|
|
||||||
ChainBehavior::AndParent(Some(matcher)) => {
|
|
||||||
let local_result = matcher(i);
|
|
||||||
if local_result.is_ok() {
|
|
||||||
return local_result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ChainBehavior::AndParent(None) => {}
|
|
||||||
ChainBehavior::IgnoreParent(Some(matcher)) => {
|
|
||||||
let local_result = matcher(i);
|
|
||||||
if local_result.is_ok() {
|
|
||||||
return local_result;
|
|
||||||
}
|
|
||||||
// TODO: Make this a custom error
|
|
||||||
not(take(0usize))(i)?;
|
|
||||||
}
|
|
||||||
ChainBehavior::IgnoreParent(None) => {
|
|
||||||
// TODO: Make this a custom error
|
|
||||||
not(take(0usize))(i)?;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
ContextElement::PreviousElementNode(_) => todo!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
current_node = current_node.without_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Make this a custom error
|
|
||||||
not(take(0usize))(i)?;
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum ContextElement<'r> {
|
|
||||||
FailMatcherNode(FailMatcherNode<'r>),
|
|
||||||
PreviousElementNode(PreviousElementNode<'r>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct FailMatcherNode<'r> {
|
|
||||||
pub fail_matcher: ChainBehavior<'r>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct PreviousElementNode<'r> {
|
|
||||||
pub dummy: &'r str,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum ChainBehavior<'r> {
|
|
||||||
AndParent(Option<&'r Matcher>),
|
|
||||||
IgnoreParent(Option<&'r Matcher>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'r> std::fmt::Debug for ChainBehavior<'r> {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
let mut formatter = f.debug_struct("ChainBehavior");
|
|
||||||
// match self {
|
|
||||||
// ChainBehavior::AndParent(_) => {
|
|
||||||
// formatter = formatter.field("type", &"AndParent");
|
|
||||||
// }
|
|
||||||
// ChainBehavior::IgnoreParent(_) => {
|
|
||||||
// formatter = formatter.field("type", &"IgnoreParent");
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
formatter.finish()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +1,85 @@
|
|||||||
use std::cell::RefCell;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use nom::branch::alt;
|
|
||||||
use nom::bytes::complete::take;
|
use nom::bytes::complete::take;
|
||||||
use nom::combinator::not;
|
use nom::combinator::not;
|
||||||
use nom::error::ContextError;
|
|
||||||
use nom::error::ErrorKind;
|
|
||||||
use nom::error::ParseError;
|
|
||||||
use nom::error::VerboseError;
|
use nom::error::VerboseError;
|
||||||
use nom::IResult;
|
use nom::IResult;
|
||||||
use nom::Parser;
|
|
||||||
use tracing::trace;
|
|
||||||
|
|
||||||
type Link<'r, T> = Option<&'r Node<'r, T>>;
|
use super::list::List;
|
||||||
|
|
||||||
type Matcher = dyn for<'s> Fn(&'s str) -> IResult<&'s str, &'s str, VerboseError<&'s str>>;
|
type Matcher = dyn for<'s> Fn(&'s str) -> IResult<&'s str, &'s str, VerboseError<&'s str>>;
|
||||||
pub type OrgModeContextNode<'r> = ContextTree<'r, ContextElement<'r>>;
|
|
||||||
|
|
||||||
struct Node<'r, T> {
|
#[derive(Debug, Clone)]
|
||||||
elem: T,
|
pub struct ContextTree<'r> {
|
||||||
next: Link<'r, T>,
|
tree: List<ContextElement<'r>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ContextTree<'r, T> {
|
impl<'r> ContextTree<'r> {
|
||||||
head: Option<Node<'r, T>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'r, T> ContextTree<'r, T> {
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
ContextTree { head: None }
|
ContextTree { tree: List::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_additional_node(&'r self, element: T) -> ContextTree<'r, T> {
|
pub fn with_additional_node(&self, data: ContextElement<'r>) -> ContextTree<'r> {
|
||||||
let new_node = Node {
|
let new_list = self.tree.push_front(data);
|
||||||
elem: element,
|
ContextTree { tree: new_list }
|
||||||
next: self.head.as_ref(),
|
}
|
||||||
};
|
|
||||||
|
|
||||||
ContextTree {
|
pub fn check_fail_matcher<'s>(
|
||||||
head: Some(new_node),
|
&'r self,
|
||||||
|
i: &'s str,
|
||||||
|
) -> IResult<&'s str, &'s str, VerboseError<&'s str>> {
|
||||||
|
// TODO: Can I do this without incrementing reference counters? Perhaps via implementing an iterator over the list?
|
||||||
|
let mut current_node = self.tree.clone();
|
||||||
|
while !current_node.is_empty() {
|
||||||
|
let context_element = current_node
|
||||||
|
.get_data()
|
||||||
|
.expect("While looop proves its Some()");
|
||||||
|
match context_element {
|
||||||
|
ContextElement::FailMatcherNode(fail_matcher) => {
|
||||||
|
match fail_matcher.fail_matcher {
|
||||||
|
ChainBehavior::AndParent(Some(matcher)) => {
|
||||||
|
let local_result = matcher(i);
|
||||||
|
if local_result.is_ok() {
|
||||||
|
return local_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ChainBehavior::AndParent(None) => {}
|
||||||
|
ChainBehavior::IgnoreParent(Some(matcher)) => {
|
||||||
|
let local_result = matcher(i);
|
||||||
|
if local_result.is_ok() {
|
||||||
|
return local_result;
|
||||||
|
}
|
||||||
|
// TODO: Make this a custom error
|
||||||
|
not(take(0usize))(i)?;
|
||||||
|
}
|
||||||
|
ChainBehavior::IgnoreParent(None) => {
|
||||||
|
// TODO: Make this a custom error
|
||||||
|
not(take(0usize))(i)?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
ContextElement::PreviousElementNode(_) => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
current_node = current_node.without_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Make this a custom error
|
||||||
|
not(take(0usize))(i)?;
|
||||||
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub enum ContextElement<'r> {
|
pub enum ContextElement<'r> {
|
||||||
FailMatcherNode(FailMatcherNode<'r>),
|
FailMatcherNode(FailMatcherNode<'r>),
|
||||||
PreviousElementNode(PreviousElementNode<'r>),
|
PreviousElementNode(PreviousElementNode<'r>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct FailMatcherNode<'r> {
|
pub struct FailMatcherNode<'r> {
|
||||||
pub fail_matcher: ChainBehavior<'r>,
|
pub fail_matcher: ChainBehavior<'r>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct PreviousElementNode<'r> {
|
pub struct PreviousElementNode<'r> {
|
||||||
pub dummy: &'r str,
|
pub dummy: &'r str,
|
||||||
}
|
}
|
||||||
@ -61,77 +90,17 @@ pub enum ChainBehavior<'r> {
|
|||||||
IgnoreParent(Option<&'r Matcher>),
|
IgnoreParent(Option<&'r Matcher>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait OrgModeContextTree<'r> {
|
impl<'r> std::fmt::Debug for ChainBehavior<'r> {
|
||||||
fn with_additional_fail_matcher(&'r self, fail_matcher: &'r Matcher) -> OrgModeContextNode<'r>;
|
|
||||||
|
|
||||||
fn match_fail<'s>(&'r self, i: &'s str) -> IResult<&'s str, &'s str, VerboseError<&'s str>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'r> OrgModeContextTree<'r> for OrgModeContextNode<'r> {
|
|
||||||
fn with_additional_fail_matcher(
|
|
||||||
&'r self,
|
|
||||||
fail_matcher: &'r Matcher,
|
|
||||||
) -> ContextTree<'r, ContextElement<'r>> {
|
|
||||||
self.with_additional_node(ContextElement::FailMatcherNode(FailMatcherNode {
|
|
||||||
fail_matcher: ChainBehavior::AndParent(Some(fail_matcher)),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
// fn with_previous_element(&'r self, dummy: &'r str) -> ContextTree<'r, PreviousElementNode<'r>> {
|
|
||||||
// self.with_additional_node(PreviousElementNode {
|
|
||||||
// dummy
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn match_fail<'s>(&'r self, i: &'s str) -> IResult<&'s str, &'s str, VerboseError<&'s str>> {
|
|
||||||
let mut current_node = self.head.as_ref();
|
|
||||||
while current_node.is_some() {
|
|
||||||
let current_node_unwrapped =
|
|
||||||
current_node.expect("while loop asserts current_node is some.");
|
|
||||||
match current_node_unwrapped.elem.get_fail_matcher() {
|
|
||||||
ChainBehavior::AndParent(Some(matcher)) => {
|
|
||||||
let local_result = matcher(i);
|
|
||||||
if local_result.is_ok() {
|
|
||||||
return local_result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ChainBehavior::AndParent(None) => {}
|
|
||||||
ChainBehavior::IgnoreParent(Some(matcher)) => {
|
|
||||||
let local_result = matcher(i);
|
|
||||||
if local_result.is_ok() {
|
|
||||||
return local_result;
|
|
||||||
}
|
|
||||||
// TODO: Make this a custom error
|
|
||||||
not(take(0usize))(i)?;
|
|
||||||
}
|
|
||||||
ChainBehavior::IgnoreParent(None) => {
|
|
||||||
// TODO: Make this a custom error
|
|
||||||
not(take(0usize))(i)?;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
current_node = current_node.map(|current_head| current_head.next).flatten();
|
|
||||||
}
|
|
||||||
// TODO: Make this a custom error
|
|
||||||
not(take(0usize))(i)?;
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'r, T> std::fmt::Debug for ContextTree<'r, T> {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "ContextTree")
|
let mut formatter = f.debug_struct("ChainBehavior");
|
||||||
}
|
// match self {
|
||||||
}
|
// ChainBehavior::AndParent(_) => {
|
||||||
|
// formatter = formatter.field("type", &"AndParent");
|
||||||
impl<'r> ContextElement<'r> {
|
// }
|
||||||
pub fn get_fail_matcher(&self) -> ChainBehavior<'r> {
|
// ChainBehavior::IgnoreParent(_) => {
|
||||||
match self {
|
// formatter = formatter.field("type", &"IgnoreParent");
|
||||||
ContextElement::FailMatcherNode(fail_matcher_node) => {
|
// }
|
||||||
fail_matcher_node.fail_matcher.clone()
|
// };
|
||||||
}
|
formatter.finish()
|
||||||
ContextElement::PreviousElementNode(previous_element_node) => {
|
|
||||||
ChainBehavior::AndParent(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,10 @@ use std::rc::Rc;
|
|||||||
use crate::parser::parser_with_context::parser_with_context;
|
use crate::parser::parser_with_context::parser_with_context;
|
||||||
use crate::parser::text::paragraph_end;
|
use crate::parser::text::paragraph_end;
|
||||||
|
|
||||||
use super::new_context::ChainBehavior;
|
use super::nom_context::ChainBehavior;
|
||||||
use super::new_context::ContextElement;
|
use super::nom_context::ContextElement;
|
||||||
use super::new_context::ContextTree;
|
use super::nom_context::ContextTree;
|
||||||
use super::new_context::FailMatcherNode;
|
use super::nom_context::FailMatcherNode;
|
||||||
use super::text::bold_end;
|
use super::text::bold_end;
|
||||||
use super::text::bold_start;
|
use super::text::bold_start;
|
||||||
use super::text::line_break;
|
use super::text::line_break;
|
||||||
@ -133,12 +133,12 @@ fn recognize_bold_end(input: &str) -> Res<&str, &str> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn flat_bold<'s, 'r>(context: Context<'r>, i: &'s str) -> Res<&'s str, Bold<'s>> {
|
fn flat_bold<'s, 'r>(context: Context<'r>, i: &'s str) -> Res<&'s str, Bold<'s>> {
|
||||||
let new_context =
|
let nom_context =
|
||||||
context.with_additional_node(ContextElement::FailMatcherNode(FailMatcherNode {
|
context.with_additional_node(ContextElement::FailMatcherNode(FailMatcherNode {
|
||||||
fail_matcher: ChainBehavior::AndParent(Some(&recognize_bold_end)),
|
fail_matcher: ChainBehavior::AndParent(Some(&recognize_bold_end)),
|
||||||
}));
|
}));
|
||||||
// let new_context = context.with_additional_fail_matcher(&recognize_bold_end);
|
// let nom_context = context.with_additional_fail_matcher(&recognize_bold_end);
|
||||||
let text_element_parser = parser_with_context!(flat_text_element)(new_context);
|
let text_element_parser = parser_with_context!(flat_text_element)(nom_context);
|
||||||
let (remaining, captured) = recognize(tuple((
|
let (remaining, captured) = recognize(tuple((
|
||||||
bold_start,
|
bold_start,
|
||||||
many_till(text_element_parser, bold_end),
|
many_till(text_element_parser, bold_end),
|
||||||
@ -152,12 +152,12 @@ fn recognize_link_end(input: &str) -> Res<&str, &str> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn flat_link<'s, 'r>(context: Context<'r>, i: &'s str) -> Res<&'s str, Link<'s>> {
|
fn flat_link<'s, 'r>(context: Context<'r>, i: &'s str) -> Res<&'s str, Link<'s>> {
|
||||||
let new_context =
|
let nom_context =
|
||||||
context.with_additional_node(ContextElement::FailMatcherNode(FailMatcherNode {
|
context.with_additional_node(ContextElement::FailMatcherNode(FailMatcherNode {
|
||||||
fail_matcher: ChainBehavior::AndParent(Some(&recognize_link_end)),
|
fail_matcher: ChainBehavior::AndParent(Some(&recognize_link_end)),
|
||||||
}));
|
}));
|
||||||
// let new_context = context.with_additional_fail_matcher(&recognize_link_end);
|
// let nom_context = context.with_additional_fail_matcher(&recognize_link_end);
|
||||||
let text_element_parser = parser_with_context!(flat_text_element)(new_context);
|
let text_element_parser = parser_with_context!(flat_text_element)(nom_context);
|
||||||
let (remaining, captured) = recognize(tuple((
|
let (remaining, captured) = recognize(tuple((
|
||||||
link_start,
|
link_start,
|
||||||
many_till(text_element_parser, link_end),
|
many_till(text_element_parser, link_end),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user