use crate::parser::error::*;
use crate::parser::reader::Reader;
use crate::parser::{ParseFunc, ParseResult};
pub fn optional<T>(f: ParseFunc<T>, reader: &mut Reader) -> ParseResult<Option<T>> {
let start = reader.state;
match f(reader) {
Ok(r) => Ok(Some(r)),
Err(e) => {
if e.recoverable {
reader.state = start;
Ok(None)
} else {
Err(e)
}
}
}
}
pub fn recover<T>(f: ParseFunc<T>, reader: &mut Reader) -> ParseResult<T> {
match f(reader) {
Ok(r) => Ok(r),
Err(e) => Err(Error::new(e.pos, true, e.inner)),
}
}
pub fn nonrecover<T>(f: ParseFunc<T>, reader: &mut Reader) -> ParseResult<T> {
match f(reader) {
Ok(r) => Ok(r),
Err(e) => Err(Error::new(e.pos, false, e.inner)),
}
}
pub fn zero_or_more<T>(f: ParseFunc<T>, reader: &mut Reader) -> ParseResult<Vec<T>> {
let _start = reader.state;
let mut v: Vec<T> = Vec::new();
loop {
let initial_state = reader.state;
if reader.is_eof() {
return Ok(v);
}
match f(reader) {
Ok(r) => {
v.push(r);
}
Err(e) => {
return if e.recoverable {
reader.state.pos = initial_state.pos;
reader.state.cursor = initial_state.cursor;
Ok(v)
} else {
Err(e)
};
}
}
}
}
pub fn one_or_more<T>(f: ParseFunc<T>, reader: &mut Reader) -> ParseResult<Vec<T>> {
let _initial_state = reader.state;
match f(reader) {
Ok(first) => {
let mut v = vec![first];
loop {
let initial_state = reader.state;
match f(reader) {
Ok(r) => {
v.push(r);
}
Err(e) => {
return if e.recoverable {
reader.state.pos = initial_state.pos;
reader.state.cursor = initial_state.cursor;
Ok(v)
} else {
Err(e)
};
}
}
}
}
Err(Error { pos, inner, .. }) => Err(Error::new(pos, false, inner)),
}
}
pub fn choice<T>(fs: &[ParseFunc<T>], reader: &mut Reader) -> ParseResult<T> {
for (pos, f) in fs.iter().enumerate() {
let start = reader.state;
if pos == fs.len() - 1 {
return f(reader);
}
match f(reader) {
Err(Error {
recoverable: true, ..
}) => {
reader.state = start;
continue;
}
x => return x,
}
}
panic!("You can't call choice with an empty vector of choice")
}