Как использовать тип std :: option с директивой% type - PullRequest
0 голосов
/ 24 июня 2019

Я пытаюсь написать грамматику, которая разбирает код C Я новичок в зубров, и я пытаюсь учиться на примерах, которые я нахожу в Интернете. Я нахожусь в процессе написания АСТ. Если это грамматика, которую я определяю (самый базовый вариант использования)

declarator
: IDENTIFIER         { $$ = $1;}
| declarator '(' ')' { $$ = new functionDecl($1); }

Теперь, когда я компилирую этот код, выдается сообщение об ошибке, в котором «описатель» не имеет типа.

Я понимаю, что могу определить тип, используя декларацию% type. Но я хочу, чтобы «объявитель» был связан с типом варианта:

%code {

class Stmt 
{
   public:
     std::string id;
     Stmt(std::string aId)
     : id(aId)
     {}  
};
typedef std::variant<std::string, Stmt> decl_type;
}

%define api.value.type variant
%token <std::string> IDENTIFIER
%type <decl_type> declarator

Я также не могу скомпилировать этот код. Выдает ошибку, что decl_type неизвестен. Чего мне не хватает?

1 Ответ

1 голос
/ 25 июня 2019

Когда вы пишете

%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 различных типов.К сожалению, я не следил за этим в деталях, поэтому вы можете посмотреть сами.

...