More representation work
This commit is contained in:
parent
e6e1d14eee
commit
e47bcbe760
@ -104,8 +104,12 @@ where
|
||||
|
||||
fn representation(&self) -> Representation {
|
||||
let at_least = self.at_least.unwrap_or(0);
|
||||
let at_most = self.at_most.unwrap_or(u32::MAX);
|
||||
let production = EBNF::Repeated(Box::new(self.inner_parser.representation().production()));
|
||||
//TODO flesh this out better
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -204,6 +208,19 @@ where
|
||||
|
||||
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>
|
||||
|
@ -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>
|
||||
where
|
||||
P: Parser<I, O1, E>,
|
||||
F: Fn(O1) -> O2,
|
||||
{
|
||||
move |input| {
|
||||
let production = parser.representation().production();
|
||||
(move |input| {
|
||||
parser
|
||||
.parse(input)
|
||||
.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),
|
||||
LabeledTerminal(String),
|
||||
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 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
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::Alternation(items) => {
|
||||
for item in intersperse_option(items.iter()) {
|
||||
@ -58,7 +78,27 @@ impl fmt::Display for EBNF {
|
||||
EBNF::Nonterminal(name) => write!(f, "{name}"),
|
||||
EBNF::StringTerminal(term) => write!(f, r#""{term}""#),
|
||||
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 = output.unwrap();
|
||||
assert_eq!(output.0, vec!["bongo", "bongo", "bongo", "bongo"]);
|
||||
assert_eq!(parser.representation().show(), r#"["bongo" ' '+]*"#);
|
||||
|
||||
let bongos = repeated(literal("bongo"));
|
||||
let output = bongos.parse("tra la la").unwrap();
|
||||
assert_eq!(output.0.len(), 0);
|
||||
assert_eq!(output.1, "tra la la");
|
||||
|
||||
assert_eq!(bongos.representation().show(), r#""bongo"*"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
Reference in New Issue
Block a user