use crate::types::*;
use std::ops::Bound;
use std::ops::RangeBounds;
#[inline]
pub fn find<'a, Res, Par, Rep>(range: Rep, mut callback: Par) -> impl Parser<'a, Vec<Res>>
where
Par: Parser<'a, Res>,
Rep: RangeBounds<usize>,
{
move |ctx: ParserContext<'a>| {
let minimum: usize = match range.start_bound() {
Bound::Excluded(min) => *min,
Bound::Included(min) => *min,
Bound::Unbounded => 0,
};
let maximum: usize = match range.end_bound() {
Bound::Excluded(max) => *max,
Bound::Included(max) => *max + 1,
Bound::Unbounded => 0,
};
let mut temp_ctx = ctx.clone();
let mut results = Vec::new();
loop {
if maximum > 0 && results.len() == maximum {
break;
}
match callback.parse(temp_ctx) {
Ok((ret_ctx, result)) => {
temp_ctx = ret_ctx;
results.push(result);
}
Err((ret_ctx, error)) => {
temp_ctx = ret_ctx;
if results.len() < minimum {
return Err(ctx.with_data(SourceError::Ranges(vec![error])));
}
break;
}
}
}
let end = temp_ctx.bounds.end - ctx.bounds.end;
if end > 0 {
Ok(temp_ctx.with_data(results))
} else if minimum == 0 {
Ok(temp_ctx.with_data(results))
} else {
let error = SourceError::Ranges(vec![SourceError::Range(ctx.bounds.clone())]);
Err(ctx.with_data(error))
}
}
}
#[inline]
pub fn find_all<'a, Res, Par>(mut parser: Par) -> impl Parser<'a, Res>
where
Par: SequenceParser<'a, Res>,
{
move |ctx| {
parser
.find_all(ctx)
.map_error(|error| SourceError::Ranges(vec![error]))
}
}
#[inline]
pub fn find_any<'a, Res, Par>(mut parser: Par) -> impl Parser<'a, Res>
where
Par: BranchParser<'a, Res>,
{
move |ctx| parser.find_any(ctx)
}
#[inline]
pub fn find_separated<'a, Par, ParRes, Sep, SepRes, Rep>(
range: Rep,
mut callback: Par,
mut separator: Sep,
) -> impl Parser<'a, Vec<ParRes>>
where
Par: Parser<'a, ParRes>,
Sep: Parser<'a, SepRes>,
Rep: RangeBounds<usize>,
{
move |ctx: ParserContext<'a>| {
let minimum: usize = match range.start_bound() {
Bound::Excluded(val) => *val,
Bound::Included(val) => *val,
Bound::Unbounded => 0,
};
let maximum: usize = match range.end_bound() {
Bound::Excluded(val) => *val,
Bound::Included(val) => *val + 1,
Bound::Unbounded => 0,
};
let mut results = Vec::new();
let mut temp_ctx = ctx.clone();
loop {
if !results.is_empty() {
match separator.parse(temp_ctx) {
Err((ret_ctx, error)) => {
return if results.len() < minimum {
Err(ret_ctx.with_data(SourceError::Ranges(vec![error])))
} else {
Ok(ret_ctx.with_data(results))
};
}
Ok((ret_ctx, _)) => {
temp_ctx = ret_ctx;
}
}
}
if maximum > 0 && results.len() == maximum {
return Ok(temp_ctx.with_data(results));
}
match callback.parse(temp_ctx) {
Err((ret_ctx, error)) => {
return if results.len() < minimum {
Err(ret_ctx.with_data(SourceError::Ranges(vec![error])))
} else {
Ok(ret_ctx.with_data(results))
}
}
Ok((ret_ctx, result)) => {
temp_ctx = ret_ctx;
results.push(result);
}
}
}
}
}
#[inline]
pub fn find_until<'a, Skip, Res, Pred, Par>(
mut predicate: Pred,
mut callback: Par,
) -> impl Parser<'a, Vec<Res>>
where
Pred: Parser<'a, Skip>,
Par: Parser<'a, Res>,
{
move |ctx: ParserContext<'a>| {
let mut temp_ctx = ctx.clone();
let mut results = Vec::new();
loop {
match predicate.parse(temp_ctx.clone()) {
Ok((_, _)) => {
break;
}
Err(_) => {}
}
match callback.parse(temp_ctx) {
Ok((ret_ctx, result)) => {
temp_ctx = ret_ctx;
results.push(result);
}
Err((ret_ctx, error)) => {
return Err(ret_ctx.with_data(SourceError::Ranges(vec![error])))
}
}
}
Ok(ctx.expand(temp_ctx).with_data(results))
}
}
#[inline]
pub fn find_when<'a, Res, Skip, Pred, Par>(
mut predicate: Pred,
mut parser: Par,
) -> impl Parser<'a, Res>
where
Pred: Parser<'a, Skip>,
Par: Parser<'a, Res>,
{
move |ctx: ParserContext<'a>| predicate.parse(ctx.clone()).and_then(|_| parser.parse(ctx))
}
#[inline]
pub fn find_when_not<'a, Pred, PredRes, Par, ParRes>(
mut predicate: Pred,
mut parser: Par,
) -> impl Parser<'a, ParRes>
where
Pred: Parser<'a, PredRes>,
Par: Parser<'a, ParRes>,
{
move |ctx: ParserContext<'a>| match predicate.parse(ctx.clone()) {
Ok((ctx, _)) => {
let error = SourceError::Range(ctx.bounds.clone());
Err(ctx.with_data(error))
}
Err(_) => parser.parse(ctx),
}
}