我是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
}
注意,上面的产生是关于@
的结合性的明确的。不可能有歧义。
注意事项:
在这里,我假设您已经声明了一个语义联合,其中一个类型是
std::vector<int>*
,因为所有这些void*
类型转换都是丑陋且不安全的。它可能类似于:%union { std::vector<int>* array_pointer; // ... } %type <array_pointer> arr expr_list arr_concat %%
delete
对于避免内存泄漏是必要的,但在哪里执行取决于您的内存管理方法。不幸的是,一旦您决定保留指向向量而不是实际向量的指针(在这种情况下,您几乎没有选择,因为每次减少都复制向量是荒谬的),那么您就要负责内存管理了。一旦语义值被合并到其他语义值中,就立即删除它们是一个简单的解决方案,但这意味着您必须小心指向所分配对象的指针的其他副本。如果您注意每个分配的对象只有一个指针,那么立即的delete
就可以了;否则,您将需要某种垃圾收集,可能基于引用计数。