Compare commits

...

5 Commits

Author SHA1 Message Date
Greg Shuflin
dfb151e2a3 More work on seq representation 2023-02-25 14:48:44 -08:00
Greg Shuflin
9a3745d25c implement representation for json_bool 2023-02-25 03:27:32 -08:00
Greg Shuflin
5aca3912fc Start making representation work 2023-02-25 03:00:29 -08:00
Greg Shuflin
377d515d40 cargo fmt 2023-02-25 02:50:43 -08:00
Greg Shuflin
f15488194c Remove some uses of closures in test 2023-02-25 02:50:20 -08:00
8 changed files with 122 additions and 25 deletions

View File

@ -1,4 +1,4 @@
use crate::parser::{ParseResult, Parser, ParserInput}; use crate::parser::{ParseResult, Parser, ParserInput, Representation};
pub fn choice2<P1, P2, I, O, E>(parser1: P1, parser2: P2) -> impl Parser<I, O, E> pub fn choice2<P1, P2, I, O, E>(parser1: P1, parser2: P2) -> impl Parser<I, O, E>
where where
@ -14,11 +14,13 @@ where
C: Choice<I, O, E>, C: Choice<I, O, E>,
I: ParserInput + Clone, I: ParserInput + Clone,
{ {
move |input| choices.parse(input) let rep = choices.representation();
(move |input| choices.parse(input), rep)
} }
pub trait Choice<I: Clone, O, E> { pub trait Choice<I: Clone, O, E> {
fn parse(&self, input: I) -> ParseResult<I, O, E>; fn parse(&self, input: I) -> ParseResult<I, O, E>;
fn representation(&self) -> Representation;
} }
impl<I, O, E, P1, P2> Choice<I, O, E> for (P1, P2) impl<I, O, E, P1, P2> Choice<I, O, E> for (P1, P2)
@ -31,6 +33,11 @@ where
let parsers = vec![&self.0 as &dyn Parser<I, O, E>, &self.1]; let parsers = vec![&self.0 as &dyn Parser<I, O, E>, &self.1];
choice_loop(input, parsers) choice_loop(input, parsers)
} }
fn representation(&self) -> Representation {
let parsers = vec![&self.0 as &dyn Parser<I, O, E>, &self.1];
repr_loop(parsers)
}
} }
impl<I, O, E, P1, P2, P3> Choice<I, O, E> for (P1, P2, P3) impl<I, O, E, P1, P2, P3> Choice<I, O, E> for (P1, P2, P3)
@ -44,6 +51,11 @@ where
let parsers = vec![&self.0 as &dyn Parser<I, O, E>, &self.1, &self.2]; let parsers = vec![&self.0 as &dyn Parser<I, O, E>, &self.1, &self.2];
choice_loop(input, parsers) choice_loop(input, parsers)
} }
fn representation(&self) -> Representation {
let parsers = vec![&self.0 as &dyn Parser<I, O, E>, &self.1, &self.2];
repr_loop(parsers)
}
} }
impl<I, O, E, P1, P2, P3, P4> Choice<I, O, E> for (P1, P2, P3, P4) impl<I, O, E, P1, P2, P3, P4> Choice<I, O, E> for (P1, P2, P3, P4)
@ -58,6 +70,11 @@ where
let parsers = vec![&self.0 as &dyn Parser<I, O, E>, &self.1, &self.2, &self.3]; let parsers = vec![&self.0 as &dyn Parser<I, O, E>, &self.1, &self.2, &self.3];
choice_loop(input, parsers) choice_loop(input, parsers)
} }
fn representation(&self) -> Representation {
let parsers = vec![&self.0 as &dyn Parser<I, O, E>, &self.1, &self.2, &self.3];
repr_loop(parsers)
}
} }
impl<I, O, E, P1, P2, P3, P4, P5> Choice<I, O, E> for (P1, P2, P3, P4, P5) impl<I, O, E, P1, P2, P3, P4, P5> Choice<I, O, E> for (P1, P2, P3, P4, P5)
@ -79,6 +96,17 @@ where
]; ];
choice_loop(input, parsers) choice_loop(input, parsers)
} }
fn representation(&self) -> Representation {
let parsers = vec![
&self.0 as &dyn Parser<I, O, E>,
&self.1,
&self.2,
&self.3,
&self.4,
];
repr_loop(parsers)
}
} }
impl<I, O, E, P1, P2, P3, P4, P5, P6> Choice<I, O, E> for (P1, P2, P3, P4, P5, P6) impl<I, O, E, P1, P2, P3, P4, P5, P6> Choice<I, O, E> for (P1, P2, P3, P4, P5, P6)
@ -102,6 +130,17 @@ where
]; ];
choice_loop(input, parsers) choice_loop(input, parsers)
} }
fn representation(&self) -> Representation {
let parsers = vec![
&self.0 as &dyn Parser<I, O, E>,
&self.1,
&self.2,
&self.3,
&self.4,
&self.5,
];
repr_loop(parsers)
}
} }
fn choice_loop<I, O, E>(input: I, parsers: Vec<&dyn Parser<I, O, E>>) -> ParseResult<I, O, E> fn choice_loop<I, O, E>(input: I, parsers: Vec<&dyn Parser<I, O, E>>) -> ParseResult<I, O, E>
@ -122,6 +161,14 @@ where
Err(err.unwrap()) Err(err.unwrap())
} }
fn repr_loop<I, O, E>(parsers: Vec<&dyn Parser<I, O, E>>) -> Representation
where
I: ParserInput + Clone,
{
let mut iter = parsers.iter().map(|p| p.representation());
Representation::from_choice(&mut iter)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -6,9 +6,11 @@ where
P: Parser<I, O1, E>, P: Parser<I, O1, E>,
F: Fn(O1) -> O2, F: Fn(O1) -> O2,
{ {
move |input| { let rep = parser.representation();
let p = move |input| {
parser parser
.parse(input) .parse(input)
.map(|(result, rest)| (map_fn(result), rest)) .map(|(result, rest)| (map_fn(result), rest))
} };
(p, rep)
} }

View File

@ -4,4 +4,4 @@ mod parser;
pub mod primitives; pub mod primitives;
pub mod sequence; pub mod sequence;
pub use parser::{ParseResult, Parser, ParserInput}; pub use parser::{ParseResult, Parser, ParserInput, Representation};

View File

@ -23,7 +23,7 @@ where
impl<'a, I: ParserInput, O, E> Parser<I, O, E> for BoxedParser<'a, I, O, E> { impl<'a, I: ParserInput, O, E> Parser<I, O, E> for BoxedParser<'a, I, O, E> {
fn representation(&self) -> Representation { fn representation(&self) -> Representation {
Representation::new("NOT IMPL'D") self.inner.representation()
} }
fn parse(&self, input: I) -> ParseResult<I, O, E> { fn parse(&self, input: I) -> ParseResult<I, O, E> {
self.inner.parse(input) self.inner.parse(input)

View File

@ -1,12 +1,34 @@
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone)]
pub struct Representation { pub struct Representation {
val: String val: String,
} }
impl Representation { impl Representation {
pub fn new(from: &str) -> Self { pub fn new(from: &str) -> Self {
Self { val: from.to_string() } Self {
val: from.to_string(),
}
}
pub fn from_choice(choice_parser_reps: &mut impl Iterator<Item = Representation>) -> Self {
let mut buf = String::new();
let mut iter = choice_parser_reps.peekable();
loop {
let rep = match iter.next() {
Some(r) => r,
None => break,
};
buf.push_str(&rep.val);
match iter.peek() {
Some(_) => {
buf.push_str(" | ");
}
None => {
break;
}
}
}
Representation::new(&buf)
} }
} }

View File

@ -9,11 +9,12 @@ pub fn literal_char(expected: char) -> impl Fn(&str) -> ParseResult<&str, char,
pub fn literal<'a>(expected: &'static str) -> impl Parser<&'a str, &'a str, &'a str> { pub fn literal<'a>(expected: &'static str) -> impl Parser<&'a str, &'a str, &'a str> {
println!("literal call expected: {}", expected); println!("literal call expected: {}", expected);
let rep = Representation::new(expected);
let p = move |input: &'a str| match input.get(0..expected.len()) { let p = move |input: &'a str| match input.get(0..expected.len()) {
Some(next) if next == expected => Ok((expected, &input[expected.len()..])), Some(next) if next == expected => Ok((expected, &input[expected.len()..])),
_ => Err(input), _ => Err(input),
}; };
(p, Representation::new("yolo")) (p, rep)
} }
pub fn any_char(input: &str) -> ParseResult<&str, char, &str> { pub fn any_char(input: &str) -> ParseResult<&str, char, &str> {
@ -50,15 +51,18 @@ where
F: Fn(&O) -> bool, F: Fn(&O) -> bool,
{ {
let orig_rep = parser.representation(); let orig_rep = parser.representation();
(move |input| { (
parser.parse(input).and_then(|(result, rest)| { move |input| {
if pred_fn(&result) { parser.parse(input).and_then(|(result, rest)| {
Ok((result, rest)) if pred_fn(&result) {
} else { Ok((result, rest))
Err(rest) } else {
} Err(rest)
}) }
}, Representation::new(&format!("{:?} if <PREDICATE>", orig_rep))) })
},
Representation::new(&format!("{:?} if <PREDICATE>", orig_rep)),
)
} }
/// Parses a standard identifier in a programming language /// Parses a standard identifier in a programming language

View File

@ -1,4 +1,4 @@
use crate::parser::{ParseResult, Parser, ParserInput}; use crate::parser::{ParseResult, Parser, ParserInput, Representation};
pub fn tuple2<P1, P2, I, O1, O2, E>(parser1: P1, parser2: P2) -> impl Parser<I, (O1, O2), E> pub fn tuple2<P1, P2, I, O1, O2, E>(parser1: P1, parser2: P2) -> impl Parser<I, (O1, O2), E>
where where
@ -14,7 +14,9 @@ where
I: ParserInput, I: ParserInput,
T: Sequence<I, O, E>, T: Sequence<I, O, E>,
{ {
move |input| sequence.parse(input) let rep = sequence.representation();
let p = move |input| sequence.parse(input);
(p, rep)
} }
/* TODO - eventually rewrite this parser combinator in Schala. Seeing what this /* TODO - eventually rewrite this parser combinator in Schala. Seeing what this
@ -24,6 +26,9 @@ where
pub trait Sequence<I, O, E> { pub trait Sequence<I, O, E> {
fn parse(&self, input: I) -> ParseResult<I, O, E>; fn parse(&self, input: I) -> ParseResult<I, O, E>;
fn representation(&self) -> Representation {
Representation::new("SEQ NOT DONE YET")
}
} }
impl<I, O1, O2, E, P1, P2> Sequence<I, (O1, O2), E> for (P1, P2) impl<I, O1, O2, E, P1, P2> Sequence<I, (O1, O2), E> for (P1, P2)

View File

@ -3,6 +3,7 @@ use parser_combinator::combinators::repeated;
use parser_combinator::primitives::{any_char, literal, literal_char, one_of, pred}; use parser_combinator::primitives::{any_char, literal, literal_char, one_of, pred};
use parser_combinator::sequence::seq; use parser_combinator::sequence::seq;
use parser_combinator::Parser; use parser_combinator::Parser;
use parser_combinator::Representation;
use proptest::prelude::*; use proptest::prelude::*;
@ -53,6 +54,7 @@ impl<'a, T, P> JsonParser<'a, T> for P where P: Parser<&'a str, T, &'a str> {}
fn json_null<'a>() -> impl JsonParser<'a, JsonValue> { fn json_null<'a>() -> impl JsonParser<'a, JsonValue> {
literal("null").to(JsonValue::Null) literal("null").to(JsonValue::Null)
} }
fn json_bool<'a>() -> impl JsonParser<'a, JsonValue> { fn json_bool<'a>() -> impl JsonParser<'a, JsonValue> {
choice(( choice((
literal("true").to(JsonValue::Bool(true)), literal("true").to(JsonValue::Bool(true)),
@ -61,8 +63,13 @@ fn json_bool<'a>() -> impl JsonParser<'a, JsonValue> {
} }
fn json_number<'a>() -> impl JsonParser<'a, JsonValue> { fn json_number<'a>() -> impl JsonParser<'a, JsonValue> {
let digit = || one_of("1234567890"); fn digit<'a>() -> impl JsonParser<'a, &'a str> {
let digits = || repeated(digit()).at_least(1); one_of("1234567890")
}
fn digits<'a>() -> impl JsonParser<'a, Vec<&'a str>> {
repeated(digit()).at_least(1)
}
let json_number_inner = choice(( let json_number_inner = choice((
seq((digits(), literal(".").ignore_then(digits()).optional())).map( seq((digits(), literal(".").ignore_then(digits()).optional())).map(
@ -229,3 +236,13 @@ fn parse_json_document() {
let parsed_json = json_object().parse(test_json); let parsed_json = json_object().parse(test_json);
assert!(parsed_json.is_ok()); assert!(parsed_json.is_ok());
} }
#[test]
fn test_representations() {
assert_eq!(json_null().representation(), Representation::new("null"));
assert_eq!(
json_bool().representation(),
Representation::new("true | false")
);
assert_eq!(json_number().representation(), Representation::new("null"));
}