如何增加野牛的堆栈大小(并解决"内存耗尽")

use*_*977 6 stack parsing bison

我的基于野牛的解析器开始窒息我最近生成的一些中等大小的文件.

它引发了一个关于"内存耗尽"的例外.

野牛手册页说这可能是由于使用了右手递归.不试图重写语法(我在一个紧迫的截止日期),我想简单地增加堆栈以使解析器解析此文件.我试图跟随bison手册页和#define YYMAXDEPTH到一些大于默认10000的数字,但是这不起作用.当我查看bison的输出时,似乎YYMAXDEPTH仅在定义YYSTACK_RELOCATE时有条件地使用,并且仅在这种情况下定义了YYSTACK_RELOCATE:

#if (! defined yyoverflow \
     && (! defined __cplusplus \
         || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
             && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
Run Code Online (Sandbox Code Playgroud)

由于我使用C++进行编译,因此上述#ifdef失败,因此未定义YYSTACK_RELOCATE.

这是一个错误还是一个功能?谁知道增加堆栈大小的正确方法是什么?

顺便说一下,这是堆栈溢出的bison生成代码的片段:

....
....
if (yyss + yystacksize - 1 <= yyssp)
{
  /* Get the current used size of the three stacks, in elements.  */
  YYSIZE_T yysize = yyssp - yyss + 1;

#ifdef yyoverflow
  {
    /* Give user a chance to reallocate the stack.  Use copies of
       these so that the &'s don't force the real ones into
       memory.  */
    YYSTYPE *yyvs1 = yyvs;
    yytype_int16 *yyss1 = yyss;
    YYLTYPE *yyls1 = yyls;

    /* Each stack pointer address is followed by the size of the
       data in use in that stack, in bytes.  This used to be a
       conditional around just the two extra args, but that might
       be undefined if yyoverflow is a macro.  */
    yyoverflow (YY_("memory exhausted"),
                &yyss1, yysize * sizeof (*yyssp),
                &yyvs1, yysize * sizeof (*yyvsp),
                &yyls1, yysize * sizeof (*yylsp),
                &yystacksize);

    yyls = yyls1;
    yyss = yyss1;
    yyvs = yyvs1;
  }
#else /* no yyoverflow */
# ifndef YYSTACK_RELOCATE
  goto yyexhaustedlab;             // <====== Overflows and throws exception here
# else
  ......
  ......
Run Code Online (Sandbox Code Playgroud)

ric*_*ici 5

通常,C ++对象(与C数据类型不同)无法通过进行重定位memcpy。因此,bison拒绝重新定位其堆栈,除非它以某种方式知道堆栈对象是“琐碎的”,并且如果这些对象是C ++对象,则假定它们不是。

YYMAXDEPTH是解析器将分配的最大堆栈,但初始堆栈大小为YYINITDEPTH。由于C ++堆栈无法重定位,因此初始大小必须足以容纳任何输入,因此需要增加YYINITDEPTH,而不是YYMAXDEPTH

或者,您可以弄清楚如何告诉bison C ++堆栈对象是可重定位的(如果可以),或者您可以尝试更新版本的bison:据称,v3更愿意让您烧死自己,但我还没有我自己尝试过 最后,您可以定义yyoverflow以提供自己的堆栈重定位机制:不幸的是,这没有文档记录,并且不必要地复杂。