C Bison GLR 常量堆栈项

C Bison GLR const stack item

我开始用 Bison 编写一个简单的 LR(1) 解析器。在处理列表时,我使用了向量的简单实现,例如在解析表达式列表时:

tuple-expression-list: expression[first] ',' expression[second] { 
    foo_vector_init(&$$); 
    foo_vector_push_back(&$$, $first); 
    foo_vector_push_back(&$$, $second); }

tuple-expression-list: tuple-expression-list[list] ',' expression[expr] { 
    foo_vector_push_back(&$list, $expr); $$ = $list; }

这很好用。但后来语法发生了变化,我不得不选择 GLR 解析器。突然编译器抱怨 $list 是常量。我发现对于 GLR 解析器:

  1. 当解析器拆分操作被记录并且不执行时,直到:
    • 除一个解析器外,所有解析器都已死亡
    • 合并了两个解析器
  2. 永远不要在动作中修改 yyval(这是前瞻)。

问题:

  1. 当我永远不必合并时,我确定只执行导致最终解析的操作吗?
  2. 首先将 $list 分配给局部变量是有效修复还是我应该深入复制向量?
  1. when I never have to merge am I sure that only the actions that result in the final parse are executed?

是的。 The documentation 指定

During the time that there are multiple parsers, semantic actions are recorded, but not performed. When a parser disappears, its recorded semantic actions disappear as well, and are never performed.

关键在于执行的语义动作(仅)与整体解析接受的实际归约相关联。

  1. Is assigning $list to a local variable first a valid fix or should I copy the vector deeply?

如果不了解您的特定向量实现或语法中存在的其他语义操作,则很难确定。假设

  • 这样的赋值会生成向量的浅表副本(与现有对象的指针或引用相反),并且
  • 向量的前面内容在执行相关语义操作的任何可能的归约行中都不会发生变化,并且
  • 副本,而不是原件,作为动作的语义值呈现,

一个浅拷贝就足够了。