我在yacc中遇到了解析器堆栈溢出。我不确定当前的解析器堆栈大小是如何确定的。有没有办法获得当前的解析器堆栈大小,以便一旦令牌数达到最大堆栈深度,就可以报告错误? yacc中是否有一个包含此信息的变量?
答案 0 :(得分:1)
没有标准的方法来获取解析器堆栈大小,尽管显然它是内部可用的,因为解析器能够产生堆栈溢出错误(没有segfaulting或以其他方式调用未定义的行为)。你不需要自己检查;您只需打印提供给yyerror
的错误消息;如果堆栈溢出,错误消息将提到这一事实。
有几种方法可以最终得到一个不会调整堆栈大小的yàcc版本。一个是使用公共领域Berkeley yacc,通常称为byacc
;我所使用的版本(从1993年开始)将默认堆栈大小设置为500。
另一种可能性是使用Gnu bison
,用C ++编译器编译结果;默认情况下,这将使堆栈不可重定位,因为bison
不知道语义值联合是否可以轻易复制。 (较新版本的野牛可能没有此限制。)默认情况下,初始野牛堆栈大小为200.
炸毁堆栈的常用方法是对长列表使用正确的递归。以下是一个特别糟糕的变体:
program: /* empty */
| statement program
;
如果“程序”太长,将导致解析器堆栈溢出。将其更改为左递归通常就足够了:
program: /* empty */
| program statement
;