organic/src/parser/new_context.rs
2022-12-04 00:04:37 -05:00

107 lines
3.4 KiB
Rust

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