choice work

This commit is contained in:
Greg Shuflin 2022-10-20 23:47:06 -07:00
parent bdaf712a25
commit 6633d10af0

View File

@ -31,21 +31,8 @@ where
I: Clone, I: Clone,
{ {
fn parse(&self, input: I) -> ParseResult<I, O, E> { fn parse(&self, input: I) -> ParseResult<I, O, E> {
let parser1 = &self.0; let parsers = vec![&self.0 as &dyn Parser<I, O, E>, &self.1];
let parser2 = &self.1; choice_loop(input, parsers)
//TODO need a more principled way to return an error when no choices work
let mut err = None;
for parser in [parser1 as &dyn Parser<I, O, E>, parser2].iter() {
match parser.parse(input.clone()) {
Ok(result) => return Ok(result),
Err(e) => {
err = Some(e);
}
}
}
Err(err.unwrap())
} }
} }
@ -57,22 +44,8 @@ where
I: Clone, I: Clone,
{ {
fn parse(&self, input: I) -> ParseResult<I, O, E> { fn parse(&self, input: I) -> ParseResult<I, O, E> {
let parser1 = &self.0; let parsers = vec![&self.0 as &dyn Parser<I, O, E>, &self.1, &self.2];
let parser2 = &self.1; choice_loop(input, parsers)
let parser3 = &self.2;
//TODO need a more principled way to return an error when no choices work
let mut err = None;
for parser in [parser1 as &dyn Parser<I, O, E>, parser2, parser3].iter() {
match parser.parse(input.clone()) {
Ok(result) => return Ok(result),
Err(e) => {
err = Some(e);
}
}
}
Err(err.unwrap())
} }
} }
@ -85,23 +58,8 @@ where
I: Clone, I: Clone,
{ {
fn parse(&self, input: I) -> ParseResult<I, O, E> { fn parse(&self, input: I) -> ParseResult<I, O, E> {
let parser1 = &self.0; let parsers = vec![&self.0 as &dyn Parser<I, O, E>, &self.1, &self.2, &self.3];
let parser2 = &self.1; choice_loop(input, parsers)
let parser3 = &self.2;
let parser4 = &self.3;
//TODO need a more principled way to return an error when no choices work
let mut err = None;
for parser in [parser1 as &dyn Parser<I, O, E>, parser2, parser3, parser4].iter() {
match parser.parse(input.clone()) {
Ok(result) => return Ok(result),
Err(e) => {
err = Some(e);
}
}
}
Err(err.unwrap())
} }
} }
@ -115,32 +73,14 @@ where
I: Clone, I: Clone,
{ {
fn parse(&self, input: I) -> ParseResult<I, O, E> { fn parse(&self, input: I) -> ParseResult<I, O, E> {
let parser1 = &self.0; let parsers = vec![
let parser2 = &self.1; &self.0 as &dyn Parser<I, O, E>,
let parser3 = &self.2; &self.1,
let parser4 = &self.3; &self.2,
let parser5 = &self.4; &self.3,
&self.4,
//TODO need a more principled way to return an error when no choices work ];
let mut err = None; choice_loop(input, parsers)
for parser in [
parser1 as &dyn Parser<I, O, E>,
parser2,
parser3,
parser4,
parser5,
]
.iter()
{
match parser.parse(input.clone()) {
Ok(result) => return Ok(result),
Err(e) => {
err = Some(e);
}
}
}
Err(err.unwrap())
} }
} }
@ -155,26 +95,26 @@ where
I: Clone, I: Clone,
{ {
fn parse(&self, input: I) -> ParseResult<I, O, E> { fn parse(&self, input: I) -> ParseResult<I, O, E> {
let parser1 = &self.0; let parsers = vec![
let parser2 = &self.1; &self.0 as &dyn Parser<I, O, E>,
let parser3 = &self.2; &self.1,
let parser4 = &self.3; &self.2,
let parser5 = &self.4; &self.3,
let parser6 = &self.5; &self.4,
&self.5,
];
choice_loop(input, parsers)
}
}
fn choice_loop<I, O, E>(input: I, parsers: Vec<&dyn Parser<I, O, E>>) -> ParseResult<I, O, E>
where
I: Clone,
{
//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 [ for parser in parsers.iter() {
parser1 as &dyn Parser<I, O, E>,
parser2,
parser3,
parser4,
parser5,
parser6,
]
.iter()
{
match parser.parse(input.clone()) { match parser.parse(input.clone()) {
Ok(result) => return Ok(result), Ok(result) => return Ok(result),
Err(e) => { Err(e) => {
@ -183,7 +123,6 @@ where
} }
} }
Err(err.unwrap()) Err(err.unwrap())
}
} }
#[cfg(test)] #[cfg(test)]
@ -200,4 +139,16 @@ mod tests {
); );
assert_eq!(p.parse("gnostika twentynine"), Ok((1, " twentynine"))); assert_eq!(p.parse("gnostika twentynine"), Ok((1, " twentynine")));
} }
#[test]
fn test_several_choices() {
let p = choice((
literal("a").to(1),
literal("q").to(10),
repeated(literal("chutney")).to(200),
literal("banana").to(10000),
));
assert_eq!(p.parse("q drugs").unwrap(), (10, " drugs"));
}
} }