use core::{
fmt::Debug,
ops::BitOr,
};
use crate::{
Parsed,
Streaming,
Success,
};
pub trait Parse<Stream, Context> {
type Token;
fn parse(&mut self, stream: Stream) -> Parsed<Self::Token, Stream, Context>;
}
impl<Token, Stream, Context, F> Parse<Stream, Context> for F
where
F: FnMut(Stream) -> Parsed<Token, Stream, Context>,
{
type Token = Token;
fn parse(&mut self, stream: Stream) -> Parsed<Token, Stream, Context> {
self(stream)
}
}
impl<Stream, Context, Parser, const N: usize> Parse<Stream, Context> for [Parser; N]
where
Stream: Streaming,
Parser: Parse<Stream, Context>,
Context: BitOr<Output = Context>,
{
type Token = Parser::Token;
fn parse(&mut self, stream: Stream) -> Parsed<Self::Token, Stream, Context> {
let mut iter = self.iter_mut();
if let Some(first) = iter.next() {
match first.parse(stream.clone()) {
success @ Parsed::Success { .. } => success,
Parsed::Failure(context) => {
let mut acc = context;
for parser in iter {
match parser.parse(stream.clone()) {
success @ Parsed::Success { .. } => {
return success;
}
Parsed::Failure(context) => {
acc = acc.bitor(context);
}
Parsed::Error(context) => {
return Parsed::Error(acc.bitor(context));
}
}
}
Parsed::Failure(acc)
}
Parsed::Error(context) => Parsed::Error(context),
}
} else {
panic!("Parse empty array don't make sense")
}
}
}
include!(concat!(env!("OUT_DIR"), "/parse_tuple.rs"));
impl<Stream, Context> Parse<Stream, Context> for () {
type Token = ();
fn parse(&mut self, stream: Stream) -> Parsed<(), Stream, Context> {
Parsed::new_success((), stream)
}
}
#[cfg(test)]
mod tests {
use core::ops::BitOr;
use crate::{
Parse,
Parsed,
Streaming,
};
#[allow(dead_code)]
fn array_parse_zero<Stream, Context>(stream: Stream) -> Parsed<(), Stream, Context>
where
Stream: Streaming,
<Stream as Streaming>::Item: Into<char>,
Context: BitOr<Output = Context>,
{
let mut foo: [(); 0] = [];
Parse::<Stream, Context>::parse(&mut foo, stream)
}
}
#[cfg(feature = "either")]
impl<Stream, Context, L, R> Parse<Stream, Context> for either::Either<L, R>
where
L: Parse<Stream, Context>,
R: Parse<Stream, Context, Token = L::Token>,
{
type Token = L::Token;
fn parse(&mut self, stream: Stream) -> Parsed<Self::Token, Stream, Context> {
match self {
either::Either::Left(l) => l.parse(stream),
either::Either::Right(r) => r.parse(stream),
}
}
}