Продукция, как
arr: arr '@' arr;
всегда будет вызывать конфликты сдвига и сокращения, потому что они неоднозначны. Предположим, у вас есть два оператора @
в исходном коде:
...1 @ ...2 @ ...3
Это должно быть проанализировано как:
arr1: ...1 @ ...2
arr2: ...3
arr3: arr1 @ arr2
or
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
сделает свое дело; в противном случае вам понадобится какая-то сборка мусора, возможно, на основе подсчета ссылок.
person
rici
schedule
29.11.2015