野牛阵列移位减少冲突



我是Bison的新手,很长一段时间以来,我一直在尝试创建一个数组和用于串联等的规则,但我不知道为什么我在这里得到了移位减少,以及如何解决它:

arr:
  T_OPEN expr       {$$ = (void *)(new vector<int>());((vector<int>*)$$)->push_back($2);}
| arr ',' expr      {((vector<int>*)($1))->push_back($3);}
| arr T_CLOSE       {}
| arr '@' arr       {/*will add it later*/}

T_OPEN为"[",T_CLOSE为"]"。@应该将这两个数组连接起来。arr的类型为void*。部分:

arr '@' arr

导致转变减少冲突。任何解决方案都将不胜感激

等产品

arr: arr '@' arr;

总是会产生偏移减少冲突,因为它们是模糊的。假设您在源中有两个@运算符:

...1 @ ...2 @ ...3

这应该被解析为:吗

arr1: ...1 @ ...2
arr2: ...3
arr3: arr1 @ arr2

arr1: ...1
arr2: ...2 @ ...3
arr3: arr1 @ arr2

换句话说,@是向左关联还是向右关联?语法没有具体说明,所以它是模棱两可的。

一种常见的解决方法是使用优先级声明(请参阅bash手册),但它可以直接用语法编写(请参阅下文)。

然而,即使将@运算符放在一边,您的语法也不能真正达到您想要的效果。首先,您可能希望基本数组文字符合以下语法:[注意1]

arr: '[' expr_list ']'    { $$ = $2; }
   | '[' ']'              { $$ = new std::vector<int>; }
expr_list
   : expr                 { $$ = new std::vector<int>; $$->push_back($1); }
   | expr_list ',' expr   { $1->push_back($3); }

然后您可以定义串联表达式:

arr_concat
   : arr
   | arr_concat '@' arr   { std::copy($3->begin(), $3->end,
                                      std::back_inserter(*$1));
                            delete $3; // Note 2
                          }

注意,上面的产生是关于@的结合性的明确的。不可能有歧义。


注意事项:

  1. 在这里,我假设您已经声明了一个语义联合,其中一个类型是std::vector<int>*,因为所有这些void*类型转换都是丑陋且不安全的。它可能类似于:

    %union {
       std::vector<int>*   array_pointer;
       // ...
    }
    %type <array_pointer> arr expr_list arr_concat
    %%
    
  2. delete对于避免内存泄漏是必要的,但在哪里执行取决于您的内存管理方法。不幸的是,一旦您决定保留指向向量而不是实际向量的指针(在这种情况下,您几乎没有选择,因为每次减少都复制向量是荒谬的),那么您就要负责内存管理了。一旦语义值被合并到其他语义值中,就立即删除它们是一个简单的解决方案,但这意味着您必须小心指向所分配对象的指针的其他副本。如果您注意每个分配的对象只有一个指针,那么立即的delete就可以了;否则,您将需要某种垃圾收集,可能基于引用计数。

相关内容

  • 没有找到相关文章

最新更新