Marwes / combine

A parser combinator library for Rust
https://docs.rs/combine/*/combine/
MIT License
1.28k stars 93 forks source link

Tools for debugging recursion problems? #330

Open jwiegley opened 2 years ago

jwiegley commented 2 years ago

Hello, I'm using combine to write a parser for a language that's not LL(1), and don't know if it's LALR(1). The code is here, with the original grammar all in comments:

https://github.com/jwiegley/motoko_parse/blob/main/src/lib.rs

When I try to runcargo test, I get the following error:

error: reached the recursion limit while instantiating `<(Ignore<&mut &mut combine::pars...<&str>>::parse_mode::<FirstMode>`
   --> /Users/johnw/Products/motoko_expr/target/.cargo-home/registry/src/github.com-1ecc6299db9ec823/combine-4.6.2/src/parser/sequence.rs:527:9
    |
527 |         self.0.parse_mode(mode, input, state).map(|(_, b)| b)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
note: `parse_mode` defined here
   --> /Users/johnw/Products/motoko_expr/target/.cargo-home/registry/src/github.com-1ecc6299db9ec823/combine-4.6.2/src/parser/mod.rs:267:5
    |
267 | /     fn parse_mode<M>(
268 | |         &mut self,
269 | |         mode: M,
270 | |         input: &mut Input,
...   |
274 | |         M: ParseMode,
275 | |         Self: Sized,
    | |____________________^
    = note: the full type name has been written to '/Users/johnw/Products/motoko_expr/target--custom/debug/deps/motoko_parse-3f75fd538faec618.long-type.txt'

At this point I've tried simplifying things and cutting down the use of closures to the bare minimum, etc., but I can't seem to move past this error. What would be the best approach to debugging something like this?

Thanks, John

jwiegley commented 2 years ago

I've worked around this for now with:

#![recursion_limit = "1024"]
Marwes commented 2 years ago

There isn't any tools directly to debug it (unless rustc provides some general ability to print out the entire, long type). But if you have a good idea of how your grammar looks you may be able to figure out where these large types appear as they would correlate to wide and deeply constructed parsers that use impl Parser.

If you know (or guess) where these large parsers are then you can use the parser! macro, the opaque parser or just box the parser to break this large parser up.

jwiegley commented 2 years ago

How do I determine which parsers are the deeply constructed ones? None of mine are beyond 20 lines long.

Marwes commented 2 years ago

"Deeply" in this case relates to multiple impl Parser returning functions calls, each call will create a larger and larger actual type, but you can break it up by using parser! or opaque.