#[cfg(not(feature = "std"))]
pub extern crate alloc;
use crate::impls::{SimpleError, SimplePosition};
use crate::traits::{Error, Input, Position, ResultOf};
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use core::marker::PhantomData;
#[cfg_attr(feature = "std", derive(Debug, PartialEq, Eq))]
#[derive(Clone)]
pub struct ParserOptions {
pub max_nest_level: Option<u32>,
}
impl Default for ParserOptions {
fn default() -> Self {
ParserOptions {
max_nest_level: Some(100),
}
}
}
#[cfg_attr(feature = "std", derive(Debug, PartialEq, Eq))]
#[derive(Clone)]
pub struct ParserContext {
nest_level: u32,
options: ParserOptions,
}
impl ParserContext {
pub fn new(options: ParserOptions) -> Self {
Self {
nest_level: 0,
options,
}
}
pub fn options(&self) -> &ParserOptions {
&self.options
}
pub fn nest<I: Input>(&self, input: &I, pos: I::Position) -> Result<Self, I::Error> {
if Some(self.nest_level) == self.options.max_nest_level {
Err(input.error_at(pos, "Exceeded nest level"))
} else {
Ok(Self {
nest_level: self.nest_level + 1,
options: self.options.clone(),
})
}
}
}
pub trait Parser<I: Input> {
type Output;
fn parse(input: &I, current: I::Position, context: &ParserContext)
-> ResultOf<I, Self::Output>;
}
pub trait Predicate<T> {
fn eval(t: &T) -> bool;
}
pub struct ExpectChar<P>(PhantomData<P>);
impl<P: Predicate<char>, I: Input> Parser<I> for ExpectChar<P> {
type Output = char;
fn parse(
input: &I,
current: I::Position,
_context: &ParserContext,
) -> ResultOf<I, Self::Output> {
let (c, next) = input
.next(current)
.map_err(|e| e.add_reason(current, "ExpectChar"))?;
if P::eval(&c) {
Ok((c, next))
} else {
Err(input.error_at(current, "ExpectChar"))
}
}
}
pub struct Null;
impl<I: Input> Parser<I> for Null {
type Output = ();
fn parse(
_input: &I,
current: I::Position,
_context: &ParserContext,
) -> ResultOf<I, Self::Output> {
Ok(((), current))
}
}
pub struct Concat<P, P2>(PhantomData<(P, P2)>);
impl<I: Input, P: Parser<I>, P2: Parser<I>> Parser<I> for Concat<P, P2> {
type Output = (P::Output, P2::Output);
fn parse(
input: &I,
current: I::Position,
context: &ParserContext,
) -> ResultOf<I, Self::Output> {
let (output1, pos) =
P::parse(input, current, context).map_err(|e| e.add_reason(current, "Concat1"))?;
let (output2, pos) =
P2::parse(input, pos, context).map_err(|e| e.add_reason(current, "Concat2"))?;
Ok(((output1, output2), pos))
}
}
pub type Concat3<P, P2, P3> = Concat<P, Concat<P2, P3>>;
pub type Concat4<P, P2, P3, P4> = Concat<P, Concat<P2, Concat<P3, P4>>>;
pub type Concat5<P, P2, P3, P4, P5> = Concat<P, Concat<P2, Concat<P3, Concat<P4, P5>>>>;
#[cfg_attr(feature = "std", derive(Debug))]
pub enum Either<A, B> {
A(A),
B(B),
}
pub struct OneOf<P, P2>(PhantomData<(P, P2)>);
impl<I: Input, P: Parser<I>, P2: Parser<I>> Parser<I> for OneOf<P, P2> {
type Output = Either<P::Output, P2::Output>;
fn parse(
input: &I,
current: I::Position,
context: &ParserContext,
) -> ResultOf<I, Self::Output> {
P::parse(input, current, context)
.map(|(output, pos)| (Either::A(output), pos))
.or_else(|_| {
P2::parse(input, current, context).map(|(output, pos)| (Either::B(output), pos))
})
.map_err(|e| e.add_reason(current, "OneOf"))
}
}
pub type OneOf3<P, P2, P3> = OneOf<P, OneOf<P2, P3>>;
pub type OneOf4<P, P2, P3, P4> = OneOf<P, OneOf3<P2, P3, P4>>;
pub type OneOf5<P, P2, P3, P4, P5> = OneOf<P, OneOf4<P2, P3, P4, P5>>;
pub type OneOf6<P, P2, P3, P4, P5, P6> = OneOf<P, OneOf5<P2, P3, P4, P5, P6>>;
pub type OneOf7<P, P2, P3, P4, P5, P6, P7> = OneOf<P, OneOf6<P2, P3, P4, P5, P6, P7>>;
pub type OneOf8<P, P2, P3, P4, P5, P6, P7, P8> = OneOf<P, OneOf7<P2, P3, P4, P5, P6, P7, P8>>;
pub type OneOf9<P, P2, P3, P4, P5, P6, P7, P8, P9> =
OneOf<P, OneOf8<P2, P3, P4, P5, P6, P7, P8, P9>>;
pub type ZeroOrOne<P> = OneOf<P, Null>;
pub type ZeroOrMore<P> = OneOf<OneOrMore<P>, Null>;
pub struct OneOrMore<P>(PhantomData<P>);
impl<I: Input, P: Parser<I>> Parser<I> for OneOrMore<P> {
type Output = Vec<P::Output>;
fn parse(
input: &I,
current: I::Position,
context: &ParserContext,
) -> ResultOf<I, Self::Output> {
let mut output_list = Vec::new();
let (output, mut pos) =
P::parse(input, current, context).map_err(|e| e.add_reason(current, "OneOrMore"))?;
output_list.push(output);
loop {
if let Ok((output, next_pos)) = P::parse(input, pos, context) {
pos = next_pos;
output_list.push(output);
} else {
return Ok((output_list, pos));
}
}
}
}
impl Input for &str {
type Position = SimplePosition;
type Error = SimpleError;
fn next(&self, pos: Self::Position) -> Result<(char, Self::Position), Self::Error> {
self.chars()
.nth(pos.index() as usize)
.ok_or_else(|| self.error_at(pos, "Out of bounds"))
.map(|c| (c, pos.next(c)))
}
fn next_range(
&self,
start: Self::Position,
counts: u32,
) -> Result<(&str, Self::Position), Self::Error> {
let start_index = start.index() as usize;
let range = start_index..start_index + counts as usize;
self.get(range)
.map(|s| {
let mut pos = start;
for c in s.chars() {
pos = pos.next(c);
}
(s, pos)
})
.ok_or_else(|| self.error_at(start, "Out of bounds"))
}
fn error_at(&self, pos: Self::Position, reason: &'static str) -> Self::Error {
let mut reasons = Vec::new();
reasons.push((pos, reason));
SimpleError { reasons }
}
fn is_end(&self, pos: Self::Position) -> bool {
pos.index() as usize >= self.len()
}
}
#[macro_export]
macro_rules! literals {
(
$(
$( #[ $attr:meta ] )*
$vis:vis $name:ident => $($($value:literal)..=+)|+;
)*
) => {
$(
$crate::literals!{
IMPL
$( #[ $attr ] )*
$vis $name => $($($value)..=+)|+
}
)*
};
(
IMPL
$( #[ $attr:meta ] )*
$vis:vis $name:ident => $($($value:literal)..=+)|+
) => (
$crate::paste::item! {
$vis struct [< $name Predicate >];
impl $crate::parser::Predicate<char> for [< $name Predicate >] {
fn eval(c: &char) -> bool {
match *c {
$($($value)..=+)|+ => true,
_ => false
}
}
}
$( #[ $attr ] )*
$vis type $name = $crate::parser::ExpectChar<[< $name Predicate >]>;
}
);
}
#[macro_export]
macro_rules! parsers {
(
$(
$( #[ $attr:meta ] )*
$vis:vis $name:ident = $type:ty, $output_type:ty, ($output:ident) => $body:block;
)*
) => {
$(
$vis struct $name;
impl<I: $crate::traits::Input> $crate::parser::Parser<I> for $name {
type Output = $output_type;
fn parse(input: &I, current: I::Position, context: &ParserContext) -> $crate::traits::ResultOf<I, Self::Output> {
let ($output, pos) = <$type as $crate::parser::Parser<I>>::parse(input, current, context)
.map_err(|e| <I::Error as $crate::traits::Error>::add_reason(e, current, stringify!($name)))?;
let res = $body;
Ok((res, pos))
}
}
)*
};
}