organic/src/parser/nom_context.rs

136 lines
3.6 KiB
Rust
Raw Normal View History

2022-10-15 00:01:37 -04:00
use std::cell::RefCell;
use std::rc::Rc;
2022-07-16 17:27:08 -04:00
use nom::branch::alt;
use nom::combinator::not;
2022-07-15 23:26:49 -04:00
use nom::error::VerboseError;
use nom::IResult;
2022-10-15 00:01:37 -04:00
use nom::Parser;
pub struct TestContext<T> {
head: ContextReference<T>,
}
type ContextReference<T> = Option<Box<ContextLayer<T>>>;
struct ContextLayer<T> {
data: T,
parent: ContextReference<T>,
}
struct ContextData {
fail_matcher: ChainBehavior,
}
impl TestContext<ContextData> {
pub fn new() -> Self {
TestContext { head: None }
}
pub fn with_additional_fail_matcher(
&self,
new_matcher: MatcherRef,
) -> TestContext<ContextData> {
TestContext {
head: Some(Box::new(ContextLayer {
data: ContextData {
fail_matcher: ChainBehavior::AndParent(Some(new_matcher)),
},
parent: self.head, // TODO FIX THIS
})),
}
}
}
/////
///// OLD
/////
type MatcherRef = Rc<RefCell<dyn FnMut(&str) -> IResult<&str, &str, VerboseError<&str>>>>;
2022-10-15 00:01:37 -04:00
2022-10-15 14:16:52 -04:00
struct FailChecker<'r>(&'r NomContext<'r>);
2022-10-15 00:01:37 -04:00
2022-10-15 14:16:52 -04:00
impl<'r> FailChecker<'r> {
fn new(func: &'r NomContext<'r>) -> Self {
2022-10-15 00:01:37 -04:00
Self(func)
}
}
enum ChainBehavior {
AndParent(Option<MatcherRef>),
IgnoreParent(Option<MatcherRef>),
}
2022-10-15 14:16:52 -04:00
pub struct NomContext<'r> {
parent: Option<&'r Self>,
2022-10-15 00:01:37 -04:00
fail_matcher: ChainBehavior,
2022-10-14 20:09:09 -04:00
/// You can't have nested bolds or links in org-mode
match_bold_allowed: bool,
match_link_allowed: bool,
2022-07-15 23:26:49 -04:00
}
2022-10-15 14:16:52 -04:00
impl<'r> NomContext<'r> {
pub fn new(fail_matcher: MatcherRef) -> Self {
2022-07-16 21:32:23 -04:00
NomContext {
2022-10-15 00:01:37 -04:00
parent: None,
fail_matcher: ChainBehavior::IgnoreParent(Some(fail_matcher)),
match_bold_allowed: true,
match_link_allowed: true,
2022-07-16 21:55:33 -04:00
}
}
2022-10-14 20:50:00 -04:00
pub fn with_additional_fail_matcher(&self, other: MatcherRef) -> NomContext {
2022-10-15 00:01:37 -04:00
NomContext {
parent: Some(&self),
fail_matcher: ChainBehavior::AndParent(Some(other)),
match_bold_allowed: self.match_bold_allowed,
match_link_allowed: self.match_link_allowed,
2022-10-15 00:01:37 -04:00
}
}
2022-10-15 14:28:24 -04:00
pub fn without_bold(&self, other: MatcherRef) -> NomContext {
NomContext {
parent: Some(&self),
fail_matcher: ChainBehavior::AndParent(Some(other)),
match_bold_allowed: false,
match_link_allowed: self.match_link_allowed,
}
}
pub fn not_matching_fail<'s>(&self, i: &'s str) -> IResult<&'s str, (), VerboseError<&'s str>> {
not(FailChecker::new(self))(i)
}
pub fn can_match_bold(&self) -> bool {
self.match_bold_allowed
}
pub fn can_match_link(&self) -> bool {
self.match_link_allowed
}
2022-10-15 00:01:37 -04:00
}
2022-10-15 17:48:27 -04:00
impl<'r, 's> Parser<&'s str, &'s str, VerboseError<&'s str>> for FailChecker<'r> {
fn parse(&mut self, i: &'s str) -> IResult<&'s str, &'s str, VerboseError<&'s str>> {
let fail_func = match &self.0.fail_matcher {
ChainBehavior::AndParent(inner) => inner,
ChainBehavior::IgnoreParent(inner) => inner,
};
if let Some(inner) = fail_func {
let parsed = (&mut *inner.borrow_mut())(i);
if parsed.is_ok() {
return parsed;
}
}
match (self.0.parent, &self.0.fail_matcher) {
(None, _) | (_, ChainBehavior::IgnoreParent(_)) => Err(nom::Err::Error(
nom::error::make_error(i, nom::error::ErrorKind::Alt),
)),
(Some(parent), ChainBehavior::AndParent(_)) => {
let mut parent_fail_checker = FailChecker::new(parent);
parent_fail_checker.parse(i)
}
}
2022-10-14 20:50:00 -04:00
}
2022-07-16 21:32:23 -04:00
}