I've been using Parsatron to great effect for a few days now, but I've recently been running into stack overflow errors. The issue is most easily demonstrated by:
(run (many (char \a)) (take 1000 (repeat \a)))
;; [Thrown class java.lang.StackOverflowError]
I investigated trying to rewrite many using loop and recur, but it's not obvious how to do so given that the recursive call happens within an inner function. I've implemented a simple trampolining strategy to slow stack consumption. With this pull request I can run up to (run (many (char\a)) (take 10000 (repeat \a))) without triggering an overflow error.
(run (many (char\a)) (take 10000 (repeat \a)))
Working on converting many to be iterative instead of recursive so as to keep it's stack consumption constant.
Add primitive trampolining to slow stack consumption.
I like the spirit of this. I completely agree with you that The Parsatron, if it is to be usable for serious projects, needs to not blow the stack. I'm interested why you chose to use a record and loop/recur, essentially a hand-rolled trampoline, when Clojure there's clojure.core/trampoline ?
Only in case people want their parsers to evaluate to actual functions, e.x.: (>> (char \+) (always +). Using clojure.core/trampoline would definitely be cleaner.
(>> (char \+) (always +)