0

我开始用 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给局部变量是有效的修复,还是应该深度复制向量?
4

1 回答 1

1
  1. 当我永远不必合并时,我确定只执行导致最终解析的操作吗?

是的。 该文档指定

在有多个解析器的时间里,语义动作被记录下来,但不被执行。当解析器消失时,其记录的语义动作也会消失,并且永远不会执行。

关键在于所执行的语义动作(仅)与整体解析所接受的实际减少相关联的那些。

  1. 首先将 $list 分配给局部变量是一个有效的修复方法,还是应该深度复制该向量?

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

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

浅拷贝就足够了。

于 2019-09-22T12:28:30.230 回答