Когда вы пишете
%define api.value.type variant
, вы говорите зубру реализовать семантические значения с собственной реализацией типа варианта .
Это выделено в [руководство по бизонам] (% определить вариант api.value.type) в заметке с заметным пометкой Предупреждение: :
Предупреждение: Мы не используем Boost.Variant
по двум причинам.Во-первых, казалось неприемлемым требовать Boost
на компьютере пользователя (т. Е. На машине, на которой будет скомпилирован сгенерированный парсер, а не на машине, на которой был запущен бизон).Во-вторых, для каждого возможного семантического значения Boost.Variant
хранит не только значение, но и тег, указывающий его тип.Но синтаксический анализатор уже «знает» тип семантического значения, так что это будет дублировать информацию.
Мы также не используем std::variant
в C ++ 17: мы хотим поддерживать все стандарты C ++,и, конечно, std::variant
также хранит тег для записи текущего типа.
(Стоит прочитать весь раздел о вариантах Bison, если вы хотите их использовать.)
Youможет определить семантический тип бизона как std::variant
, конечно:
%define api.value.type std::variant<std::string, Stmt>
Но это может быть не то, что вы хотите, потому что бизон ничего не знает о std::variant
и не будет ничего делатьчтобы помочь вам с синтаксисом доступа к значению варианта.Обычно, как указывает страница вариантов Bison, Bison может выводить тип семантического значения символа грамматики (конечно, используя ваши объявления %type
), но если вы не используетеunion
или тип варианта Bison, тогда все, что знает Bison, это значение std::variant
.Если вам случается знать, что это определенный тип (например, потому что вы знаете, каковы типы ваших терминальных символов), и вы хотите проверить значение, используя этот тип, вам придется использовать std::variant::get
, что-токак $2.get<NodeList>
.
В списке рассылки Bison обсуждалось улучшение обработки Bison различных типов.К сожалению, я не следил за этим в деталях, поэтому вы можете посмотреть сами.