235 lines
5.9 KiB
Rust
235 lines
5.9 KiB
Rust
use std::marker::PhantomData;
|
|
|
|
use crate::{
|
|
representation::{Representation, EBNF},
|
|
ParseResult, Parser,
|
|
};
|
|
|
|
pub fn repeated<P, I, O, E>(parser: P) -> Repeated<P, I, O, E>
|
|
where
|
|
P: Parser<I, O, E>,
|
|
{
|
|
Repeated::new(parser)
|
|
}
|
|
|
|
pub struct Repeated<P, I, O, E>
|
|
where
|
|
P: Parser<I, O, E>,
|
|
{
|
|
inner_parser: P,
|
|
phantom: PhantomData<(I, O, E)>,
|
|
at_least: Option<u32>,
|
|
at_most: Option<u32>,
|
|
}
|
|
|
|
impl<P, I, O, E> Repeated<P, I, O, E>
|
|
where
|
|
P: Parser<I, O, E>,
|
|
{
|
|
fn new(inner_parser: P) -> Self {
|
|
Self {
|
|
inner_parser,
|
|
phantom: PhantomData,
|
|
at_least: None,
|
|
at_most: None,
|
|
}
|
|
}
|
|
pub fn at_least(self, at_least: u32) -> Self {
|
|
Self {
|
|
at_least: Some(at_least),
|
|
..self
|
|
}
|
|
}
|
|
pub fn at_most(self, at_most: u32) -> Self {
|
|
Self {
|
|
at_most: Some(at_most),
|
|
..self
|
|
}
|
|
}
|
|
pub fn separated_by<D>(self, delimiter: D) -> SeparatedBy<D, P, I, O, E>
|
|
where
|
|
D: Parser<I, (), E>,
|
|
E: Default,
|
|
{
|
|
SeparatedBy {
|
|
inner_repeated: self,
|
|
delimiter,
|
|
allow_trailing: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<P, I, O, E> Parser<I, Vec<O>, E> for Repeated<P, I, O, E>
|
|
where
|
|
P: Parser<I, O, E>,
|
|
E: Default,
|
|
{
|
|
fn parse(&self, mut input: I) -> ParseResult<I, Vec<O>, E> {
|
|
let at_least = self.at_least.unwrap_or(0);
|
|
let at_most = self.at_most.unwrap_or(u32::MAX);
|
|
|
|
let mut results = vec![];
|
|
let mut count = 0;
|
|
|
|
if at_most == 0 {
|
|
return Ok((vec![], input));
|
|
}
|
|
|
|
loop {
|
|
match self.inner_parser.parse(input) {
|
|
Ok((item, rest)) => {
|
|
results.push(item);
|
|
input = rest;
|
|
count += 1;
|
|
if count >= at_most {
|
|
break;
|
|
}
|
|
}
|
|
Err((_err, rest)) => {
|
|
input = rest;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if count < at_least {
|
|
return Err((Default::default(), input));
|
|
}
|
|
Ok((results, input))
|
|
}
|
|
|
|
fn name(&self) -> Option<String> {
|
|
self.inner_parser.name()
|
|
}
|
|
|
|
fn representation(&self) -> Representation {
|
|
let at_least = self.at_least.unwrap_or(0);
|
|
//TODO flesh this out better
|
|
let _at_most = self.at_most.unwrap_or(u32::MAX);
|
|
let production = EBNF::Repeated {
|
|
inner: Box::new(self.inner_parser.representation().production()),
|
|
more_than_once: at_least >= 1,
|
|
};
|
|
Representation::new().with_production(production)
|
|
}
|
|
}
|
|
|
|
pub struct SeparatedBy<D, P, I, O, E>
|
|
where
|
|
D: Parser<I, (), E>,
|
|
P: Parser<I, O, E>,
|
|
E: Default,
|
|
{
|
|
inner_repeated: Repeated<P, I, O, E>,
|
|
delimiter: D,
|
|
allow_trailing: bool,
|
|
}
|
|
|
|
impl<D, P, I, O, E> SeparatedBy<D, P, I, O, E>
|
|
where
|
|
D: Parser<I, (), E>,
|
|
P: Parser<I, O, E>,
|
|
E: Default,
|
|
{
|
|
pub fn allow_trailing(self, allow_trailing: bool) -> Self {
|
|
Self {
|
|
allow_trailing,
|
|
..self
|
|
}
|
|
}
|
|
}
|
|
impl<D, P, I, O, E> Parser<I, Vec<O>, E> for SeparatedBy<D, P, I, O, E>
|
|
where
|
|
D: Parser<I, (), E>,
|
|
P: Parser<I, O, E>,
|
|
E: Default,
|
|
{
|
|
fn parse(&self, mut input: I) -> ParseResult<I, Vec<O>, E> {
|
|
let at_least = self.inner_repeated.at_least.unwrap_or(0);
|
|
let at_most = self.inner_repeated.at_most.unwrap_or(u32::MAX);
|
|
let inner = &self.inner_repeated.inner_parser;
|
|
let delimiter = &self.delimiter;
|
|
|
|
if at_most == 0 {
|
|
return Ok((vec![], input));
|
|
}
|
|
|
|
let mut results = Vec::new();
|
|
let mut count: u32 = 0;
|
|
|
|
match inner.parse(input) {
|
|
Ok((item, rest)) => {
|
|
results.push(item);
|
|
input = rest;
|
|
}
|
|
Err((err, rest)) => {
|
|
if at_least > 0 {
|
|
return Err((err, rest));
|
|
} else {
|
|
return Ok((vec![], rest));
|
|
}
|
|
}
|
|
}
|
|
|
|
loop {
|
|
match delimiter.parse(input) {
|
|
Ok(((), rest)) => {
|
|
input = rest;
|
|
count += 1;
|
|
}
|
|
Err((_err, rest)) => {
|
|
input = rest;
|
|
break;
|
|
}
|
|
}
|
|
match inner.parse(input) {
|
|
Ok((item, rest)) => {
|
|
input = rest;
|
|
results.push(item);
|
|
}
|
|
Err((err, rest)) => {
|
|
if self.allow_trailing {
|
|
input = rest;
|
|
break;
|
|
} else {
|
|
return Err((err, rest));
|
|
}
|
|
}
|
|
}
|
|
if count >= at_most {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if count < at_least {
|
|
//return Err(??, rest) <- need to handle errors better
|
|
unimplemented!();
|
|
}
|
|
|
|
Ok((results, input))
|
|
}
|
|
|
|
fn representation(&self) -> Representation {
|
|
let inner = &self.inner_repeated.inner_parser;
|
|
let at_least = self.inner_repeated.at_least.unwrap_or(0);
|
|
let inner_production = inner.representation().production();
|
|
let delimiter_production = self.delimiter.representation().production();
|
|
|
|
let production = EBNF::Repeated {
|
|
inner: Box::new(EBNF::Sequence(vec![inner_production, delimiter_production])),
|
|
more_than_once: at_least >= 1,
|
|
};
|
|
Representation::new().with_production(production)
|
|
}
|
|
}
|
|
|
|
pub fn optional<I, O, E>(parser: impl Parser<I, O, E>) -> impl Parser<I, Option<O>, E>
|
|
where
|
|
I: Clone,
|
|
{
|
|
move |input: I| match parser.parse(input.clone()) {
|
|
Ok((output, rest)) => Ok((Some(output), rest)),
|
|
Err(_e) => Ok((None, input)),
|
|
}
|
|
}
|