2022-11-26 22:36:02 -05:00
|
|
|
use nom::bytes::complete::take;
|
2022-10-15 14:04:24 -04:00
|
|
|
use nom::combinator::not;
|
2022-07-15 23:26:49 -04:00
|
|
|
use nom::error::VerboseError;
|
2022-07-16 16:31:00 -04:00
|
|
|
use nom::IResult;
|
2022-11-24 14:59:37 -05:00
|
|
|
|
2022-12-03 22:18:37 -05:00
|
|
|
use super::list::List;
|
2022-12-03 23:53:52 -05:00
|
|
|
use super::token::Token;
|
2022-11-24 15:40:07 -05:00
|
|
|
|
2022-12-03 22:18:37 -05:00
|
|
|
type Matcher = dyn for<'s> Fn(&'s str) -> IResult<&'s str, &'s str, VerboseError<&'s str>>;
|
2022-11-24 16:01:52 -05:00
|
|
|
|
2022-12-03 22:18:37 -05:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct ContextTree<'r> {
|
|
|
|
tree: List<ContextElement<'r>>,
|
2022-11-24 15:40:07 -05:00
|
|
|
}
|
|
|
|
|
2022-12-03 22:18:37 -05:00
|
|
|
impl<'r> ContextTree<'r> {
|
2022-11-26 22:03:15 -05:00
|
|
|
pub fn new() -> Self {
|
2022-12-03 22:18:37 -05:00
|
|
|
ContextTree { tree: List::new() }
|
2022-11-24 15:40:07 -05:00
|
|
|
}
|
2022-11-24 16:01:52 -05:00
|
|
|
|
2022-12-03 22:18:37 -05:00
|
|
|
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!(),
|
|
|
|
};
|
2022-11-26 22:36:02 -05:00
|
|
|
|
2022-12-03 22:18:37 -05:00
|
|
|
current_node = current_node.without_front();
|
2022-11-26 22:03:15 -05:00
|
|
|
}
|
2022-12-03 22:18:37 -05:00
|
|
|
|
|
|
|
// TODO: Make this a custom error
|
|
|
|
not(take(0usize))(i)?;
|
|
|
|
unreachable!()
|
2022-11-26 22:03:15 -05:00
|
|
|
}
|
2022-11-26 22:36:02 -05:00
|
|
|
}
|
|
|
|
|
2022-12-03 22:18:37 -05:00
|
|
|
#[derive(Debug, Clone)]
|
2022-11-26 22:54:54 -05:00
|
|
|
pub enum ContextElement<'r> {
|
|
|
|
FailMatcherNode(FailMatcherNode<'r>),
|
|
|
|
PreviousElementNode(PreviousElementNode<'r>),
|
|
|
|
}
|
|
|
|
|
2022-12-03 22:18:37 -05:00
|
|
|
#[derive(Debug, Clone)]
|
2022-11-26 22:54:54 -05:00
|
|
|
pub struct FailMatcherNode<'r> {
|
2022-11-26 22:36:02 -05:00
|
|
|
pub fail_matcher: ChainBehavior<'r>,
|
|
|
|
}
|
|
|
|
|
2022-12-03 22:18:37 -05:00
|
|
|
#[derive(Debug, Clone)]
|
2022-11-26 22:36:02 -05:00
|
|
|
pub struct PreviousElementNode<'r> {
|
2022-12-03 23:53:52 -05:00
|
|
|
pub element: Token<'r>,
|
2022-11-26 22:36:02 -05:00
|
|
|
}
|
|
|
|
|
2022-11-26 22:54:54 -05:00
|
|
|
#[derive(Clone)]
|
2022-11-26 22:36:02 -05:00
|
|
|
pub enum ChainBehavior<'r> {
|
|
|
|
AndParent(Option<&'r Matcher>),
|
|
|
|
IgnoreParent(Option<&'r Matcher>),
|
|
|
|
}
|
|
|
|
|
2022-12-03 22:18:37 -05:00
|
|
|
impl<'r> std::fmt::Debug for ChainBehavior<'r> {
|
2022-11-25 18:23:51 -05:00
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
2022-12-03 22:18:37 -05:00
|
|
|
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()
|
2022-11-26 22:54:54 -05:00
|
|
|
}
|
|
|
|
}
|