organic/src/parser/nom_context.rs

138 lines
4.1 KiB
Rust
Raw Normal View History

use std::cell::RefCell;
use std::rc::Rc;
use nom::branch::alt;
use nom::bytes::complete::take;
use nom::combinator::not;
use nom::error::ContextError;
2022-11-24 16:24:49 -05:00
use nom::error::ErrorKind;
use nom::error::ParseError;
2022-07-15 23:26:49 -04:00
use nom::error::VerboseError;
use nom::IResult;
use nom::Parser;
use tracing::trace;
2022-11-24 14:59:37 -05:00
2022-11-26 22:03:15 -05:00
type Link<'r, T> = Option<&'r Node<'r, T>>;
type Matcher = dyn for<'s> Fn(&'s str) -> IResult<&'s str, &'s str, VerboseError<&'s str>>;
pub type OrgModeContextNode<'r> = ContextTree<'r, ContextElement<'r>>;
2022-11-24 15:40:07 -05:00
struct Node<'r, T> {
elem: T,
next: Link<'r, T>,
2022-11-26 22:03:15 -05:00
}
pub struct ContextTree<'r, T> {
2022-11-26 22:03:15 -05:00
head: Option<Node<'r, T>>,
2022-11-24 15:40:07 -05:00
}
impl<'r, T> ContextTree<'r, T> {
2022-11-26 22:03:15 -05:00
pub fn new() -> Self {
ContextTree { head: None }
2022-11-24 15:40:07 -05:00
}
pub fn with_additional_node(&'r self, element: T) -> ContextTree<'r, T> {
2022-11-26 22:03:15 -05:00
let new_node = Node {
elem: element,
next: self.head.as_ref(),
2022-11-26 22:03:15 -05:00
};
2022-11-26 22:03:15 -05:00
ContextTree {
head: Some(new_node),
}
}
}
2022-11-26 22:54:54 -05:00
pub enum ContextElement<'r> {
FailMatcherNode(FailMatcherNode<'r>),
PreviousElementNode(PreviousElementNode<'r>),
}
pub struct FailMatcherNode<'r> {
pub fail_matcher: ChainBehavior<'r>,
}
pub struct PreviousElementNode<'r> {
pub dummy: &'r str,
}
2022-11-26 22:54:54 -05:00
#[derive(Clone)]
pub enum ChainBehavior<'r> {
AndParent(Option<&'r Matcher>),
IgnoreParent(Option<&'r Matcher>),
}
pub trait OrgModeContextTree<'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(
2022-11-26 22:03:15 -05:00
&'r self,
fail_matcher: &'r Matcher,
) -> ContextTree<'r, ContextElement<'r>> {
2022-11-26 22:54:54 -05:00
self.with_additional_node(ContextElement::FailMatcherNode(FailMatcherNode {
fail_matcher: ChainBehavior::AndParent(Some(fail_matcher)),
2022-11-26 22:54:54 -05:00
}))
}
// 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() {
2022-11-26 22:54:54 -05:00
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;
}
2022-11-24 16:24:49 -05:00
}
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)?;
2022-11-24 16:24:49 -05:00
}
ChainBehavior::IgnoreParent(None) => {
// TODO: Make this a custom error
not(take(0usize))(i)?;
2022-11-24 16:24:49 -05:00
}
};
current_node = current_node.map(|current_head| current_head.next).flatten();
}
2022-11-24 16:24:49 -05:00
// TODO: Make this a custom error
not(take(0usize))(i)?;
unreachable!()
}
2022-11-24 15:40:07 -05:00
}
2022-11-25 18:23:51 -05:00
impl<'r, T> std::fmt::Debug for ContextTree<'r, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "ContextTree")
}
}
2022-11-26 22:54:54 -05:00
impl<'r> ContextElement<'r> {
pub fn get_fail_matcher(&self) -> ChainBehavior<'r> {
match self {
ContextElement::FailMatcherNode(fail_matcher_node) => {
fail_matcher_node.fail_matcher.clone()
}
ContextElement::PreviousElementNode(previous_element_node) => {
ChainBehavior::AndParent(None)
}
}
}
}