Replace the old nom_context with the contents of new_context.

This commit is contained in:
Tom Alexander 2022-12-03 22:18:37 -05:00
parent 84fa1c3aae
commit 6cfc39ca45
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
4 changed files with 78 additions and 216 deletions

View File

@ -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>;

View File

@ -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()
}
}

View File

@ -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)
}
}
} }
} }

View File

@ -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),