Pass input out
This commit is contained in:
parent
e697b8ed21
commit
9efd9d78d1
@ -1,21 +1,19 @@
|
|||||||
use crate::Parser;
|
use crate::Parser;
|
||||||
|
|
||||||
pub fn choice<'a, I, O, E>(parsers: &'a [&'a dyn Parser<I, O, E>]) -> impl Parser<I, O, E> + 'a
|
pub fn choice<'a, I, O, E>(parsers: &'a [&'a dyn Parser<I, O, E>]) -> impl Parser<I, O, E> + 'a {
|
||||||
where
|
move |mut input: I| {
|
||||||
I: Clone,
|
|
||||||
{
|
|
||||||
move |input: I| {
|
|
||||||
//TODO need a more principled way to return an error when no choices work
|
//TODO need a more principled way to return an error when no choices work
|
||||||
let mut err = None;
|
let mut err = None;
|
||||||
|
|
||||||
for parser in parsers.iter() {
|
for parser in parsers.iter() {
|
||||||
match parser.parse(input.clone()) {
|
match parser.parse(input) {
|
||||||
Ok(res) => return Ok(res),
|
Ok(res) => return Ok(res),
|
||||||
Err(e) => {
|
Err((e, rest)) => {
|
||||||
err = Some(e);
|
err = Some(e);
|
||||||
|
input = rest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err.unwrap())
|
Err((err.unwrap(), input))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,16 +3,23 @@ use crate::Parser;
|
|||||||
pub fn repeated<P, I, O, E>(parser: P) -> impl Parser<I, Vec<O>, E>
|
pub fn repeated<P, I, O, E>(parser: P) -> impl Parser<I, Vec<O>, E>
|
||||||
where
|
where
|
||||||
P: Parser<I, O, E>,
|
P: Parser<I, O, E>,
|
||||||
I: Copy,
|
|
||||||
{
|
{
|
||||||
move |input: I| {
|
move |input: I| {
|
||||||
let mut acc = input;
|
let mut acc = input;
|
||||||
let mut results = vec![];
|
let mut results = vec![];
|
||||||
|
|
||||||
while let Ok((item, rest)) = parser.parse(acc) {
|
loop {
|
||||||
|
match parser.parse(acc) {
|
||||||
|
Ok((item, rest)) => {
|
||||||
results.push(item);
|
results.push(item);
|
||||||
acc = rest;
|
acc = rest;
|
||||||
}
|
}
|
||||||
|
Err((_err, rest)) => {
|
||||||
|
acc = rest;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok((results, acc))
|
Ok((results, acc))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ pub use map::*;
|
|||||||
pub use primitives::*;
|
pub use primitives::*;
|
||||||
pub use sequence::*;
|
pub use sequence::*;
|
||||||
|
|
||||||
type ParseResult<I, O, E> = Result<(O, I), E>;
|
type ParseResult<I, O, E> = Result<(O, I), (E, I)>;
|
||||||
|
|
||||||
pub trait Parser<I, O, E> {
|
pub trait Parser<I, O, E> {
|
||||||
fn parse(&self, input: I) -> ParseResult<I, O, E>;
|
fn parse(&self, input: I) -> ParseResult<I, O, E>;
|
||||||
@ -51,7 +51,7 @@ mod tests {
|
|||||||
let a = literal("bongo");
|
let a = literal("bongo");
|
||||||
let b = literal("sucy");
|
let b = literal("sucy");
|
||||||
let c = literal("ara");
|
let c = literal("ara");
|
||||||
let inputs = [&a as &dyn Parser<&str, &str, &str>, &b, &c];
|
let inputs = [&a as &dyn Parser<&str, &str, ()>, &b, &c];
|
||||||
let parser = choice(&inputs);
|
let parser = choice(&inputs);
|
||||||
|
|
||||||
let output = parser.parse("ara hajimete").unwrap();
|
let output = parser.parse("ara hajimete").unwrap();
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
use crate::{ParseResult, Parser};
|
use crate::{ParseResult, Parser};
|
||||||
|
|
||||||
pub fn literal(expected: &'static str) -> impl Fn(&str) -> ParseResult<&str, &str, &str> {
|
pub fn literal(expected: &'static str) -> impl Fn(&str) -> ParseResult<&str, &str, ()> {
|
||||||
move |input| match input.get(0..expected.len()) {
|
move |input| match input.get(0..expected.len()) {
|
||||||
Some(next) if next == expected => Ok((next, &input[expected.len()..])),
|
Some(next) if next == expected => Ok((next, &input[expected.len()..])),
|
||||||
_ => Err(input),
|
_ => Err(((), input)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn literal_char<'a>(expected: char) -> impl Parser<&'a str, char, &'a str> {
|
pub fn literal_char<'a>(expected: char) -> impl Parser<&'a str, char, ()> {
|
||||||
move |input: &'a str| match input.chars().next() {
|
move |input: &'a str| match input.chars().next() {
|
||||||
Some(ch) if ch == expected => Ok((expected, &input[ch.len_utf8()..])),
|
Some(ch) if ch == expected => Ok((expected, &input[ch.len_utf8()..])),
|
||||||
_ => Err(input),
|
_ => Err(((), input)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user