Uns*_*bra 5 recursion parsing clojure
我是 Clojure 的新手,无法弄清楚如何在某些情况下避免堆栈溢出。在尝试使用我发现的名为kern 的解析器组合器库将解析项目移植到 Clojure 时,出现了一种这样的情况。
Kern 定义了“many-till”解析器的递归实现:source
这对于小输入来说效果很好:
(def input-text "The blue {cat} and the red {dog} became best friends with the white {wolf} END {not included}")
(def between-brackets "parser that grabs all text between brackets"
(between (sym* \{) (sym* \}) (<+> (many (none-of* "}")))))
(def parse-enclosed-words "parser that attempts to grab text between brackets,
skips a character when it can't, and halts when it hits the string END"
(many-till (<|> between-brackets (skip any-char)) (token* "END")))
(filter #(some? %) (value parse-enclosed-words input-text)) ;; => ("cat" "dog" "wolf")
Run Code Online (Sandbox Code Playgroud)
不幸的是,随着输入字符串的增长,解析器会遇到堆栈溢出:
(def file-input-text (slurp (io/resource "[input-text-20x-repeated.txt][2]") ))
(filter #(some? %) (value parse-enclosed-words file-input-text)) ;; => Unhandled java.lang.StackOverflowError
Run Code Online (Sandbox Code Playgroud)
据我通过在线阅读得知,这可能是由于该函数使用了堆栈消耗递归。我尝试使用“recur”关键字重写函数,但由于递归调用不在尾部位置,这似乎不起作用。
如何修改 Many-Till 以避免堆栈溢出?