#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