значение yylval не определено с помощью flex и bison

#gcc #bison #flex-lexer #compiler-construction

#gcc #bison #гибкий лексер #построение компилятора

Вопрос:

Я просмотрел почти все материалы в Интернете. Но я все еще не понимаю, почему lexer не может идентифицировать yylval.

Вот случай: я определил кучу ADT в node.h и реализовал их в node.c , моя цель — сгенерировать AST после того, как эти структуры будут должным образом сохранены. Но я застрял с файлом bison.

Во-первых, я меняю %union на union YYSTYPE {...}; и typedef union YYSTYPE YYSTYPE; , я не понимаю, зачем мне это нужно делать, с некоторыми другими файлами, размещенными в Интернете, кажется, хорошо работает %uinion .

Затем я застрял с yylval вещами. Я сделал bison -d кое-что и уже проверил это в parser.c (я указал вывод bison), так что, я думаю, extern YYSTYPE yylval; должно сработать. Но это не так. Итак, мне интересно, есть ли другой способ решить необъявленную проблему yylval.

Я использую только два типа YYSTYPE структуры, int и char * , могу ли я разделить объединение YYSYTPE и struct для AST? Это означает, что нетерминалы не будут иметь связанных типов. У вас, ребята, есть какие-нибудь другие идеи??

Комментарии:

1. Мне все еще интересно, что вы имеете в виду под «разделением объединения YYSTYPE и структуры для AST», и я не думаю, что это необходимо. У вас возникли проблемы при использовании %union и %type в bison?

2. @neuront Да, я согласен с вами. Нам не нужно явно указывать YYSTYPE в bison. Но дело в том, что я не могу пройти через это, не сделав этого. Другими словами, хотя %union и %union YYSTYPE работает таким же образом, однако в моем случае я должен выбрать последнее. Я не знаю, почему? Для %union и %type я знаю взаимосвязь между ними. Я просто знаю, как устранить ошибку с помощью YYSTYPE undefined . Когда я искал в Интернете, я обнаружил, что это распространенная проблема.

Ответ №1:

На случай, если это поможет другим, я обнаружил (OpenBSD lex v2.5.4 yacc), что в том числе

 extern YYSTYPE yylval;
  

в моем исходном коде lex было недостаточно для предотвращения проблемы ‘yylval не определен’, даже несмотря на то, что файл y.tab.c содержит:

 #ifndef YYSTYPE
typedef int YYSTYPE;
#endif
  

Я исправил это, поместив явное определение в исходный код lex:

 #define YYSTYPE int
extern YYSTYPE yyltype
  

Однако мне неясно, будет ли определение таким образом распространяться на языковой стандарт исходного файла yacc…

Ответ №2:

Вы должны использовать %union. Вам не нужно вводить значение объединения.

Вы используете bison -d для получения файла заголовка с любыми объявлениями (такими как типы для терминалов, нетерминалы и токены). Пример:

bison -d parser.y Это приведет к получению двух файлов, parser.tab.c и parser.tab.h. Вы можете включить последний файл в свой файл lexer, чтобы он знал о ваших %token определениях. Этот файл также содержит определение yylval и его типа.

Вам не следует разделять объединение, потому что вы, скорее всего, расширите его и оно понадобится для обмена данными между лексером и анализатором.

Ответ №3:

Установлен ли у вас %pure-parser (или аналогичный) в вашем файле .y? Это отключает обычные объявления lex, поскольку они не вводятся повторно.

https://www.gnu.org/software/bison/manual/html_node/Pure-Decl.html