解析器组合器中的递归耗尽堆栈空间

时间:2015-05-20 19:27:24

标签: java parsing recursion grammar parser-combinators

我一直在用Java创建一个简单的解析器组合库,并且我第一次尝试使用程序结构来定义标记和解析器语法,见下文:

final Combinator c2 = new CombinatorBuilder()
    /*
    .addParser("SEXPRESSION", of(Option.of(new Terminal("LPAREN"), zeroOrMore(new ParserPlaceholder("EXPRESSION")), new Terminal("RPAREN"))))
    .addParser("QEXPRESSION", of(Option.of(new Terminal("LBRACE"), zeroOrMore(new ParserPlaceholder("EXPRESSION")), new Terminal("RBRACE"))))
    */
    .addParser("SEXPRESSION", of(Option.of(new Terminal("LPAREN"), new ParserPlaceholder("EXPRESSION"), new Terminal("RPAREN"))))
    .addParser("QEXPRESSION", of(Option.of(new Terminal("LBRACE"), new ParserPlaceholder("EXPRESSION"), new Terminal("RBRACE"))))
    .addParser("EXPRESSION", of(
        Option.of(new Terminal("NUMBER")),
        Option.of(new Terminal("SYMBOL")),
        Option.of(new Terminal("STRING")),
        Option.of(new Terminal("COMMENT")),
        Option.of(new ParserPlaceholder("SEXPRESSION")),
        Option.of(new ParserPlaceholder("QEXPRESSION"))
)).build()

如果我使用builer定义第一个Parser“SEXPRESSION”,我可以解释结构:

addParser的参数:

  1. 解析器名称
  2. ImmutableList的{​​{1}}
  3. Option

    Option.of的参数:

    1. Element个数组,其中每个元素都是TerminalParserPlaceholder,后来替换名称匹配的实际Parser
    2. 这个想法是能够从另一个引用一个Parser,从而表达更复杂的语法。

      我遇到的问题是,在解析RPAREN')'作为“SEXPRESSIONS”和“表达“解析者有一个或多个”基数。

      我确信我可以发挥创意并想出一些限制递归调用深度的方法,也许是通过确保当“SEXPRESSION”解析器切换到“EXPRESSION”解析器然后将其移交给“SEXPRESSION”解析器,没有令牌,然后辍学?但如果存在标准解决方案,我不想要一个hacky解决方案。

      有什么想法吗?

      由于

1 个答案:

答案 0 :(得分:1)

不要回答这个问题,但我不认为使用VM参数调用应用程序来增加堆栈大小有任何问题。

这可以通过添加标志-XssNm在Java中完成,其中N是调用应用程序的内存量。

默认的Java堆栈大小是512 KB,坦率地说,几乎没有任何内存。除了次要的优化之外,我觉得使用那个小内存来实现复杂的递归解决方案是困难的,尤其是因为Java在递归方面的效率最低。

所以,这个标志的一些例子,如下:

  • -Xss4M 4 MB
  • -Xss2G 2 GB

在您调用java启动应用程序之后,或者如果您使用的是Eclipse之类的IDE,您可以进入并在运行配置中手动设置命令行参数。

希望这有帮助!