More representation work
This commit is contained in:
parent
e6e1d14eee
commit
e47bcbe760
@ -104,8 +104,12 @@ where
|
|||||||
|
|
||||||
fn representation(&self) -> Representation {
|
fn representation(&self) -> Representation {
|
||||||
let at_least = self.at_least.unwrap_or(0);
|
let at_least = self.at_least.unwrap_or(0);
|
||||||
let at_most = self.at_most.unwrap_or(u32::MAX);
|
//TODO flesh this out better
|
||||||
let production = EBNF::Repeated(Box::new(self.inner_parser.representation().production()));
|
let _at_most = self.at_most.unwrap_or(u32::MAX);
|
||||||
|
let production = EBNF::Repeated {
|
||||||
|
inner: Box::new(self.inner_parser.representation().production()),
|
||||||
|
more_than_once: at_least >= 1,
|
||||||
|
};
|
||||||
Representation::new().with_production(production)
|
Representation::new().with_production(production)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -204,6 +208,19 @@ where
|
|||||||
|
|
||||||
Ok((results, input))
|
Ok((results, input))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn representation(&self) -> Representation {
|
||||||
|
let inner = &self.inner_repeated.inner_parser;
|
||||||
|
let at_least = self.inner_repeated.at_least.unwrap_or(0);
|
||||||
|
let inner_production = inner.representation().production();
|
||||||
|
let delimiter_production = self.delimiter.representation().production();
|
||||||
|
|
||||||
|
let production = EBNF::Repeated {
|
||||||
|
inner: Box::new(EBNF::Sequence(vec![inner_production, delimiter_production])),
|
||||||
|
more_than_once: at_least >= 1,
|
||||||
|
};
|
||||||
|
Representation::new().with_production(production)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn optional<I, O, E>(parser: impl Parser<I, O, E>) -> impl Parser<I, Option<O>, E>
|
pub fn optional<I, O, E>(parser: impl Parser<I, O, E>) -> impl Parser<I, Option<O>, E>
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
use crate::Parser;
|
use crate::{representation::Representation, Parser, ParserExtension};
|
||||||
|
|
||||||
pub fn map<P, F, I, O1, O2, E>(parser: P, map_fn: F) -> impl Parser<I, O2, E>
|
pub fn map<P, F, I, O1, O2, E>(parser: P, map_fn: F) -> impl Parser<I, O2, E>
|
||||||
where
|
where
|
||||||
P: Parser<I, O1, E>,
|
P: Parser<I, O1, E>,
|
||||||
F: Fn(O1) -> O2,
|
F: Fn(O1) -> O2,
|
||||||
{
|
{
|
||||||
move |input| {
|
let production = parser.representation().production();
|
||||||
|
(move |input| {
|
||||||
parser
|
parser
|
||||||
.parse(input)
|
.parse(input)
|
||||||
.map(|(result, rest)| (map_fn(result), rest))
|
.map(|(result, rest)| (map_fn(result), rest))
|
||||||
}
|
})
|
||||||
|
.to_anno()
|
||||||
|
.with_repr(Representation::new().with_production(production))
|
||||||
}
|
}
|
||||||
|
@ -38,13 +38,33 @@ pub enum EBNF {
|
|||||||
StringTerminal(String),
|
StringTerminal(String),
|
||||||
LabeledTerminal(String),
|
LabeledTerminal(String),
|
||||||
Alternation(Vec<EBNF>),
|
Alternation(Vec<EBNF>),
|
||||||
Repeated(Box<EBNF>),
|
Sequence(Vec<EBNF>),
|
||||||
|
Repeated {
|
||||||
|
inner: Box<EBNF>,
|
||||||
|
more_than_once: bool,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EBNF {
|
||||||
|
fn needs_wrapping(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
EBNF::None => false,
|
||||||
|
EBNF::Nonterminal(_) => false,
|
||||||
|
EBNF::CharTerminal(_) => false,
|
||||||
|
EBNF::StringTerminal(_) => false,
|
||||||
|
EBNF::LabeledTerminal(_) => false,
|
||||||
|
EBNF::Sequence(items) => items.len() > 1,
|
||||||
|
EBNF::Alternation(_) => true,
|
||||||
|
EBNF::Repeated { .. } => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for EBNF {
|
impl fmt::Display for EBNF {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
EBNF::None => write!(f, "none"),
|
//TODO should try to show the name if possible
|
||||||
|
EBNF::None => write!(f, "<no-representation>"),
|
||||||
EBNF::CharTerminal(ch) => write!(f, "'{ch}'"),
|
EBNF::CharTerminal(ch) => write!(f, "'{ch}'"),
|
||||||
EBNF::Alternation(items) => {
|
EBNF::Alternation(items) => {
|
||||||
for item in intersperse_option(items.iter()) {
|
for item in intersperse_option(items.iter()) {
|
||||||
@ -58,7 +78,27 @@ impl fmt::Display for EBNF {
|
|||||||
EBNF::Nonterminal(name) => write!(f, "{name}"),
|
EBNF::Nonterminal(name) => write!(f, "{name}"),
|
||||||
EBNF::StringTerminal(term) => write!(f, r#""{term}""#),
|
EBNF::StringTerminal(term) => write!(f, r#""{term}""#),
|
||||||
EBNF::LabeledTerminal(s) => write!(f, "<{s}>"),
|
EBNF::LabeledTerminal(s) => write!(f, "<{s}>"),
|
||||||
EBNF::Repeated(inner) => write!(f, "[ {inner} ]"),
|
EBNF::Repeated {
|
||||||
|
inner,
|
||||||
|
more_than_once,
|
||||||
|
} => {
|
||||||
|
let sigil = if *more_than_once { '+' } else { '*' };
|
||||||
|
if inner.needs_wrapping() {
|
||||||
|
write!(f, "[{inner}]{sigil}")
|
||||||
|
} else {
|
||||||
|
write!(f, "{inner}{sigil}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EBNF::Sequence(items) => {
|
||||||
|
for item in intersperse_option(items.iter()) {
|
||||||
|
if let Some(item) = item {
|
||||||
|
write!(f, "{item}")?;
|
||||||
|
} else {
|
||||||
|
write!(f, " ")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write!(f, "")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,11 +81,14 @@ fn test_repeated() {
|
|||||||
let output = parser.parse("bongo bongo bongo bongo");
|
let output = parser.parse("bongo bongo bongo bongo");
|
||||||
let output = output.unwrap();
|
let output = output.unwrap();
|
||||||
assert_eq!(output.0, vec!["bongo", "bongo", "bongo", "bongo"]);
|
assert_eq!(output.0, vec!["bongo", "bongo", "bongo", "bongo"]);
|
||||||
|
assert_eq!(parser.representation().show(), r#"["bongo" ' '+]*"#);
|
||||||
|
|
||||||
let bongos = repeated(literal("bongo"));
|
let bongos = repeated(literal("bongo"));
|
||||||
let output = bongos.parse("tra la la").unwrap();
|
let output = bongos.parse("tra la la").unwrap();
|
||||||
assert_eq!(output.0.len(), 0);
|
assert_eq!(output.0.len(), 0);
|
||||||
assert_eq!(output.1, "tra la la");
|
assert_eq!(output.1, "tra la la");
|
||||||
|
|
||||||
|
assert_eq!(bongos.representation().show(), r#""bongo"*"#);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user