choice module

This commit is contained in:
Greg Shuflin 2022-10-16 19:21:43 -07:00
parent e584668efc
commit eaafdaa777
3 changed files with 36 additions and 28 deletions

26
src/choice.rs Normal file
View File

@ -0,0 +1,26 @@
use crate::parser::Parser;
pub fn choice<P1, P2, I, O, E>(parser1: P1, parser2: P2) -> impl Parser<I, O, E>
where
P1: Parser<I, O, E>,
P2: Parser<I, O, E>,
I: Copy,
{
move |input| match parser1.parse(input) {
ok @ Ok(..) => ok,
Err(_e) => parser2.parse(input),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::combinators::one_or_more;
use crate::primitives::literal;
#[test]
fn test_choice() {
let p = choice(literal("gnostika").to(1), one_or_more(literal(" ")).to(2));
assert_eq!(p.parse("gnostika twentynine"), Ok((1, " twentynine")));
}
}

View File

@ -1,43 +1,24 @@
#![feature(assert_matches)]
#![allow(dead_code)] //TODO eventually turn this off #![allow(dead_code)] //TODO eventually turn this off
mod bnf; mod bnf;
mod choice;
mod combinators; mod combinators;
mod parser; mod parser;
mod primitives; mod primitives;
mod sequence; mod sequence;
use parser::{ParseResult, Parser}; pub use parser::{ParseResult, Parser};
fn choice<P1, P2, I, O, E>(parser1: P1, parser2: P2) -> impl Parser<I, O, E>
where
P1: Parser<I, O, E>,
P2: Parser<I, O, E>,
I: Copy,
{
move |input| match parser1.parse(input) {
ok @ Ok(..) => ok,
Err(_e) => parser2.parse(input),
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::combinators::one_or_more; use crate::choice::choice;
use crate::primitives::literal; use crate::primitives::literal;
use std::assert_matches::assert_matches;
use std::collections::HashMap; use std::collections::HashMap;
#[test] #[test]
fn test_parsing() { fn test_parsing() {
let output = literal("a")("a yolo"); let output = literal("a")("a yolo");
assert_matches!(output.unwrap(), ("a", " yolo")); assert_eq!(output.unwrap(), ("a", " yolo"));
}
#[test]
fn test_choice() {
let p = choice(literal("gnostika").to(1), one_or_more(literal(" ")).to(2));
assert_eq!(p.parse("gnostika twentynine"), Ok((1, " twentynine")));
} }
/* /*
@ -48,7 +29,7 @@ mod tests {
<object> ::= "{" [<property>] {"," <property>}* "}" <object> ::= "{" [<property>] {"," <property>}* "}"
<property> ::= <string> ":" <value> <property> ::= <string> ":" <value>
*/ */
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
enum JsonValue { enum JsonValue {
Null, Null,
Bool(bool), Bool(bool),
@ -66,6 +47,6 @@ mod tests {
let json_value = choice(json_null, choice(json_true, json_false)); let json_value = choice(json_null, choice(json_true, json_false));
assert_matches!(json_value.parse("true"), Ok((JsonValue::Bool(true), ""))); assert_eq!(json_value.parse("true"), Ok((JsonValue::Bool(true), "")));
} }
} }

View File

@ -112,15 +112,16 @@ mod test {
use super::*; use super::*;
use crate::combinators::zero_or_more; use crate::combinators::zero_or_more;
use crate::primitives::{identifier, literal}; use crate::primitives::{identifier, literal};
use std::assert_matches::assert_matches;
#[test] #[test]
fn test_tuple2() { fn test_tuple2() {
let p = tuple2(identifier, tuple2(literal(" "), literal("ruts"))); let p = tuple2(identifier, tuple2(literal(" "), literal("ruts")));
assert_matches!(p.parse("fort1 ruts"), Ok((r, "")) if r.0 == "fort1" && r.1 == (" ", "ruts") ); let (output, _rest) = p.parse("fort1 ruts").unwrap();
assert_eq!(output, ("fort1".into(), (" ", "ruts")));
let p = identifier.then(literal(" ")).then(literal("ruts")); let p = identifier.then(literal(" ")).then(literal("ruts"));
assert_matches!(p.parse("fort1 ruts"), Ok((r, "")) if r.0.0 == "fort1" && r.0.1== " " && r.1 == "ruts"); let (output, _rest) = p.parse("fort1 ruts").unwrap();
assert_eq!(output, (("fort1".into(), " "), "ruts"));
} }
#[test] #[test]