我开始用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 解析器:
- 当解析器拆分操作被记录并且直到以下任一之前才会执行:
- 除了一个解析器之外,所有解析器都死了
- 两个解析器合并
- 永远不应该修改操作中的
yyval
(这是前瞻(。
问题:
- 当我永远不必合并时,我确定只执行导致最终解析的操作吗?
- 首先将
$list
分配给局部变量是有效的修复还是我应该深度复制向量?
- 当我永远不必合并时,我确定只执行导致最终解析的操作吗?
是的。 文档指定
在有多个解析器期间,语义操作是 已录制,但未执行。当解析器消失时,其记录 语义操作也会消失,并且永远不会执行。
关键恰恰是,执行的语义操作(仅(与整体解析接受的实际减少相关联。
- 首先将$list分配给局部变量是有效的修复还是我应该深度复制向量?
如果不了解您的特定向量实现或语法中存在哪些其他语义操作,就很难确定。 假设
- 这样的赋值生成矢量的浅拷贝(例如,与指针或对现有对象的引用相反(,并且
- 向量的上述内容在执行相关语义操作的任何可能的归约行中都不会发生变化,并且 副本,
- 而不是原始副本,呈现为操作的语义值,
浅拷贝就足够了。