Open zesterer opened 1 year ago
Personally, I think there may be some worth to having some kind of 'visitor' or something - maybe an API like the following? We can make it internal for now and expose it only through other methods if we want.
/// We provide both 'enter' and 'leave' so we know when we're moving up or down the tree. There are alternative ways to handle
/// this also.
pub(crate) trait ParserVisitor {
fn enter_parser(&mut self, info: ParserInfo);
fn leave_parser(&mut self, info: ParserInfo);
}
pub(crate) trait Visitable {
/// This should be implemented as roughly `visitor.enter_parser(...); self.parser.visit(...); visitor.leave_parser(...);`
fn visit<V: ParserVisitor>(&self, visitor: V);
}
pub(crate) struct ParserInfo {
name: &str,
size_hint: (usize, Option<usize>),
// Whatever other fields we find useful
...
}
I can certainly see this being a useful way to approach this feature.
Trying out an API like I described - seeing how well your implementation converts
It would be useful to have a way to introspect the parser to catch common problems and suggest improvements. See this branch for an example of how such passes could be implemented.
Useful passes:
repeated
/separated_by
that operate on parsers that can parse no inputs (i.e: catching this case)prefix.then(a).or(prefix.then(b))
instead ofprefix.then(a.or(b))
, for example)()
having.ignored()
applied to it, for example)empty().ignore_then(x)
).boxed()
(recurse through parser and sub-types, count nodes)Additionally, it would be useful to have some sort of profiling tool build into the crate, such as a way for individual parsers to record how many times they're being invoked to discover bottlenecks in the parser logic.