use std::default::Default;
use crate::input::{Pear, Input, Rewind, Token, Result};
use crate::macros::parser;
use crate::parsers::*;
pub trait Collection<A>: Default + Extend<A> {
#[inline(always)]
fn push(&mut self, item: A) {
self.extend(Some(item))
}
}
impl<A, T: Default + Extend<A>> Collection<A> for T { }
pub fn ok<I, P, O>(input: &mut Pear<I>, p: P) -> Option<O>
where I: Input, P: FnOnce(&mut Pear<I>) -> Result<O, I>
{
let save = input.emit_error;
input.emit_error = false;
let ok = p(input).ok();
input.emit_error = save;
ok
}
pub fn succeeds<I, P, O>(input: &mut Pear<I>, p: P) -> bool
where I: Input, P: FnOnce(&mut Pear<I>) -> Result<O, I>
{
ok(input, p).is_some()
}
#[parser(raw)]
pub fn last_of_many<I, O, P>(input: &mut Pear<I>, mut p: P) -> Result<O, I>
where I: Input, P: FnMut(&mut Pear<I>) -> Result<O, I>
{
loop {
let output = p()?;
if succeeds(input, eof) {
return Ok(output);
}
}
}
#[parser(raw)]
pub fn surrounded<I, O, F, P>(input: &mut Pear<I>, mut p: P, mut f: F) -> Result<O, I>
where I: Input,
F: FnMut(&I::Token) -> bool,
P: FnMut(&mut Pear<I>) -> Result<O, I>
{
skip_while(&mut f)?;
let output = p()?;
skip_while(&mut f)?;
Ok(output)
}
#[parser(raw)]
pub fn collect<C, I, O, P>(input: &mut Pear<I>, mut p: P) -> Result<C, I>
where C: Collection<O>, I: Input, P: FnMut(&mut Pear<I>) -> Result<O, I>
{
let mut collection = C::default();
loop {
if succeeds(input, eof) {
return Ok(collection);
}
collection.push(p()?);
}
}
#[parser(raw)]
pub fn collect_some<C, I, O, P>(input: &mut Pear<I>, mut p: P) -> Result<C, I>
where C: Collection<O>, I: Input, P: FnMut(&mut Pear<I>) -> Result<O, I>
{
let mut collection = C::default();
loop {
collection.push(p()?);
if succeeds(input, eof) {
return Ok(collection);
}
}
}
#[parser(raw)]
pub fn try_collect<C, I, O, P>(input: &mut Pear<I>, mut p: P) -> Result<C, I>
where C: Collection<O>, I: Input + Rewind, P: FnMut(&mut Pear<I>) -> Result<O, I>
{
let mut collection = C::default();
loop {
if succeeds(input, eof) {
return Ok(collection);
}
let start = input.mark(&crate::input::ParserInfo {
name: "try_collect",
raw: true
});
match ok(input, |i| p(i)) {
Some(val) => collection.push(val),
None => {
input.rewind_to(start);
break;
}
}
}
Ok(collection)
}
#[parser(raw)]
pub fn delimited_collect<C, I, T, S, O, P>(
input: &mut Pear<I>,
start: T,
mut item: P,
separator: S,
end: T,
) -> Result<C, I>
where C: Collection<O>,
I: Input,
T: Token<I> + Clone,
S: Into<Option<T>>,
P: FnMut(&mut Pear<I>) -> Result<O, I>,
{
eat(start)?;
let seperator = separator.into();
let mut collection = C::default();
loop {
if succeeds(input, |i| eat(i, end.clone())) {
break;
}
collection.push(item()?);
if let Some(ref separator) = seperator {
if !succeeds(input, |i| eat(i, separator.clone())) {
eat(end.clone())?;
break;
}
}
}
Ok(collection)
}
#[parser(raw)]
pub fn series<C, I, S, O, P>(
input: &mut Pear<I>,
mut item: P,
seperator: S,
) -> Result<C, I>
where C: Collection<O>,
I: Input,
S: Token<I> + Clone,
P: FnMut(&mut Pear<I>) -> Result<O, I>,
{
let mut collection = C::default();
loop {
collection.push(item()?);
if !succeeds(input, |i| eat(i, seperator.clone())) {
break;
}
}
Ok(collection)
}
#[parser(raw)]
pub fn trailing_series<C, I, S, O, P>(
input: &mut Pear<I>,
mut item: P,
seperator: S,
) -> Result<C, I>
where C: Collection<O>,
I: Input,
S: Token<I> + Clone,
P: FnMut(&mut Pear<I>) -> Result<O, I>,
{
let mut collection = C::default();
let mut have_some = false;
loop {
if have_some {
if let Some(item) = ok(input, |i| item(i)) {
collection.push(item);
} else {
break
}
} else {
collection.push(item()?);
have_some = true;
}
if !succeeds(input, |i| eat(i, seperator.clone())) {
break;
}
}
Ok(collection)
}
#[parser(raw)]
pub fn prefixed_series<C, I, T, O, P>(
input: &mut Pear<I>,
prefix: T,
item: P,
seperator: T,
) -> Result<C, I>
where C: Collection<O>,
I: Input,
T: Token<I> + Clone,
P: FnMut(&mut Pear<I>) -> Result<O, I>,
{
if !succeeds(input, |i| eat(i, prefix)) {
return Ok(C::default());
}
series(input, item, seperator)
}