pub fn opaque<Input, F, O, S>(f: F) -> Opaque<F, Input, O, S> where
Input: Stream,
S: Default,
F: FnMut(&mut dyn FnMut(&mut dyn Parser<Input, Output = O, PartialState = S>)),
Expand description
Creates a parser from a function which takes a function that are given the actual parser.
Though convoluted this makes it possible to hide the concrete parser type without Box
or
losing the full information about the parser as is the case of parser
.
Since this hides the type this can also be useful for writing mutually recursive impl Parser
parsers to break the otherwise arbitrarily large type that rustc creates internally.
If you need a more general version (that does not need trait objects) try the parser!
macro.
#[derive(PartialEq, Debug)]
enum Expr {
Number(i64),
Pair(Box<Expr>, Box<Expr>),
}
fn expr<Input>() -> FnOpaque<Input, Expr>
where
Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
opaque!(
// `no_partial` disables partial parsing and replaces the partial state with `()`,
// letting us avoid naming that type
no_partial(choice((
from_str(many1::<String, _, _>(digit()))
.map(Expr::Number),
(char('('), expr(), char(','), expr(), char(')'))
.map(|(_, l, _, r, _)| Expr::Pair(Box::new(l), Box::new(r)))
))),
)
}
assert_eq!(
expr().easy_parse("123"),
Ok((Expr::Number(123), ""))
);