use crate::position::Pos;
use crate::state::State;
use crate::{CombineFail, CombineManyFail};
use std::rc::Rc;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ParseResult<T, E, F = ()> {
Ok(T, Pos),
Fail(F, Pos),
Err(E, Pos),
}
pub struct Parser<'a, T, E, F = ()> {
pub(crate) name: Rc<String>,
parse: Rc<dyn Fn(State<'a>) -> ParseResult<T, E, F> + 'a>,
}
impl<T, E, F> std::fmt::Debug for Parser<'_, T, E, F> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let name = self.name.as_ref();
write!(f, "Parser(\"{name}\")")
}
}
impl<'a, T, E, F> Clone for Parser<'a, T, E, F> {
fn clone(&self) -> Self {
Self {
name: self.name.clone(),
parse: self.parse.clone(),
}
}
}
impl<'a, T, E, F> Parser<'a, T, E, F> {
pub fn ret(value: T) -> Self
where
T: Clone + 'a,
{
Parser {
name: Rc::new("ret".to_string()),
parse: Rc::new(move |state| ParseResult::Ok(value.clone(), state.pos)),
}
}
pub fn ret_with(value: impl Fn() -> T + 'a) -> Self {
Parser {
name: Rc::new("ret_with".to_string()),
parse: Rc::new(move |state| ParseResult::Ok(value(), state.pos)),
}
}
pub fn fail(value: F) -> Self
where
F: Clone + 'a,
{
Parser {
name: Rc::new("fail".to_string()),
parse: Rc::new(move |state| ParseResult::Fail(value.clone(), state.pos)),
}
}
pub fn fail_with(value: impl Fn() -> F + 'a) -> Self {
Parser {
name: Rc::new("fail_with".to_string()),
parse: Rc::new(move |state| ParseResult::Fail(value(), state.pos)),
}
}
pub fn err(value: E) -> Self
where
E: Clone + 'a,
{
Parser {
name: Rc::new("err".to_string()),
parse: Rc::new(move |state| ParseResult::Err(value.clone(), state.pos)),
}
}
pub fn err_with(value: impl Fn() -> E + 'a) -> Self {
Parser {
name: Rc::new("err_with".to_string()),
parse: Rc::new(move |state| ParseResult::Err(value(), state.pos)),
}
}
pub fn from_fn<Func>(func: Func) -> Self
where
Func: Fn(State<'a>) -> ParseResult<T, E, F> + 'a,
{
Parser {
name: Rc::new("from_fn".to_string()),
parse: Rc::new(func),
}
}
pub fn parse(&self, state: State<'a>) -> ParseResult<T, E, F> {
(self.parse)(state)
}
pub fn with_name(mut self, name: impl Into<String>) -> Self {
self.name = Rc::new(name.into());
self
}
pub fn map<U>(self, f: impl Fn(T) -> U + 'a) -> Parser<'a, U, E, F>
where
F: 'a,
E: 'a,
T: 'a,
{
let name = format!("map({})", self.name);
Parser::from_fn(move |state| match self.parse(state) {
ParseResult::Ok(value, pos) => ParseResult::Ok(f(value), pos),
ParseResult::Fail(fail_value, pos) => ParseResult::Fail(fail_value, pos),
ParseResult::Err(err_value, pos) => ParseResult::Err(err_value, pos),
})
.with_name(name)
}
pub fn map_fail<G>(self, f: impl Fn(F) -> G + 'a) -> Parser<'a, T, E, G>
where
F: 'a,
E: 'a,
T: 'a,
{
let name = format!("map_fail({})", self.name);
Parser::from_fn(move |state| match self.parse(state) {
ParseResult::Ok(value, pos) => ParseResult::Ok(value, pos),
ParseResult::Fail(fail_value, pos) => ParseResult::Fail(f(fail_value), pos),
ParseResult::Err(err_value, pos) => ParseResult::Err(err_value, pos),
})
.with_name(name)
}
pub fn map_err<E2>(self, f: impl Fn(E) -> E2 + 'a) -> Parser<'a, T, E2, F>
where
F: 'a,
E: 'a,
T: 'a,
{
let name = format!("map_err({})", self.name);
Parser::from_fn(move |state| match self.parse(state) {
ParseResult::Ok(value, pos) => ParseResult::Ok(value, pos),
ParseResult::Fail(fail_value, pos) => ParseResult::Fail(fail_value, pos),
ParseResult::Err(err_value, pos) => ParseResult::Err(f(err_value), pos),
})
.with_name(name)
}
pub fn and_then<U, Func>(self, func: Func) -> Parser<'a, U, E, F>
where
Func: Fn(T) -> Parser<'a, U, E, F> + 'a,
F: 'a,
E: 'a,
T: 'a,
{
let name = format!("and_then({})", self.name);
Parser::from_fn(move |state| match self.parse(state) {
ParseResult::Ok(value, pos) => func(value).parse(state.with_pos(pos)),
ParseResult::Fail(fail_value, pos) => ParseResult::Fail(fail_value, pos),
ParseResult::Err(err_value, pos) => ParseResult::Err(err_value, pos),
})
.with_name(name)
}
pub fn and_then_fail<G, Func>(self, func: Func) -> Parser<'a, T, E, G>
where
Func: Fn(F) -> Parser<'a, T, E, G> + 'a,
F: 'a,
E: 'a,
T: 'a,
{
let name = format!("and_then_fail({})", self.name);
Parser::from_fn(move |state| match self.parse(state) {
ParseResult::Ok(value, pos) => ParseResult::Ok(value, pos),
ParseResult::Fail(fail_value, _) => func(fail_value).parse(state),
ParseResult::Err(err_value, pos) => ParseResult::Err(err_value, pos),
})
.with_name(name)
}
pub fn and_then_err<E2, Func>(self, func: Func) -> Parser<'a, T, E2, F>
where
Func: Fn(E) -> Parser<'a, T, E2, F> + 'a,
F: 'a,
E: 'a,
T: 'a,
{
let name = format!("and_then_err({})", self.name);
Parser::from_fn(move |state| match self.parse(state) {
ParseResult::Ok(value, pos) => ParseResult::Ok(value, pos),
ParseResult::Fail(fail_value, pos) => ParseResult::Fail(fail_value, pos),
ParseResult::Err(err_value, _) => func(err_value).parse(state),
})
.with_name(name)
}
pub fn or<G, H>(self, other: Parser<'a, T, E, G>) -> Parser<'a, T, E, H>
where
T: 'a,
E: 'a,
F: 'a,
G: 'a,
F: CombineFail<'a, G, H>,
{
let name = format!("or({} | {})", self.name, other.name);
Parser::from_fn(move |state| match self.parse(state) {
ParseResult::Ok(value, pos) => ParseResult::Ok(value, pos),
ParseResult::Fail(f1, f1_pos) => {
match other.parse(state) {
ParseResult::Ok(value, pos) => ParseResult::Ok(value, pos),
ParseResult::Fail(f2, f2_pos) => {
let f =
F::combine_fail(f1, state.with_pos(f1_pos), f2, state.with_pos(f2_pos));
ParseResult::Fail(f, state.pos)
}
ParseResult::Err(err_value, pos) => ParseResult::Err(err_value, pos),
}
}
ParseResult::Err(err_value, pos) => ParseResult::Err(err_value, pos),
})
.with_name(name)
}
pub fn or_ret<G>(self, x: T) -> Parser<'a, T, E, G>
where
T: Clone + 'a,
E: 'a,
F: 'a,
G: 'a,
{
self.or(Parser::ret(x)).map_fail(|(_, f)| f)
}
pub fn or_fail<G>(self, f: G) -> Parser<'a, T, E, G>
where
T: 'a,
E: 'a,
F: 'a,
G: Clone + 'a,
{
self.map_fail(move |_| f.clone())
}
pub fn or_err<G>(self, e: E) -> Parser<'a, T, E, G>
where
T: 'a,
E: Clone + 'a,
F: 'a,
G: 'a,
{
self.or(Parser::err(e)).map_fail(|(_f, g)| g)
}
pub fn one_of<G>(
parsers: impl IntoIterator<Item = Parser<'a, T, E, F>> + 'a,
) -> Parser<'a, T, E, G>
where
T: 'a,
E: 'a,
F: 'a + CombineManyFail<'a, G>,
G: 'a,
{
let mut ret = Parser::fail_with(Vec::new);
let mut names = vec![];
for parser in parsers {
names.push(parser.name.clone());
ret = ret.or(parser).map_fail(|(f1, _f1_state, f2, f2_state)| {
let mut f = f1;
f.push((f2, f2_state));
f
});
}
let name = format!(
"one_of({})",
names
.iter()
.map(|s| s.as_str())
.collect::<Vec<_>>()
.join(", ")
);
ret.map_fail(F::combine_many_fail).with_name(name)
}
pub fn filter(self, pred: impl Fn(&T) -> bool + 'a) -> Self
where
T: Clone + 'a,
E: 'a,
F: Clone + Default + 'a,
{
let name = format!("filter({})", self.name);
Parser::and_then(self, move |value| {
if pred(&value) {
Parser::ret(value)
} else {
Parser::fail(F::default())
}
})
.with_name(name)
}
}
impl<'a, E, F> Parser<'a, State<'a>, E, F> {
pub fn state() -> Self {
Parser {
name: Rc::new("state".to_string()),
parse: Rc::new(|state| ParseResult::Ok(state, state.pos)),
}
}
}
#[macro_export]
macro_rules! one_of {
( $($parser:expr),* $(,)? ) => {{
$crate::Parser::one_of(
vec![
$($parser),*
]
)
}};
}