В Bison возможно, что yylval будет структурой, а не объединением? Я знаю, что могу определить yylval как объединение с %union{}
, но есть ли способ определить yylval как структуру? чтобы вернуть строку и строку идентификатора для примера и получить доступ к этой информации по действию некоторого грамматического правила на бизоне.
Возможно, yylval будет структурой, а не объединением?
Ответы (2)
Да, вы можете #define YYSTYPE
быть любым типом вместо использования %union
. Однако это редко бывает полезно1. Если вам нужна информация об исходной позиции, лучше использовать %position
в сочетании с %union
.
Также возможно (и распространено) использование структур внутри объявления %union
. Это позволяет некоторым правилам легко возвращать несколько значений (эффективно).
1Основная проблема заключается в том, что если вы используете %type
для указания использования одного поля структуры, использование других полей в том же действии будет болезненным. Вам нужно делать все вручную, тем самым теряя преимущества проверки типов объединения bison
Если вы хотите сохранить информацию о местоположении (номер строки и номер столбца) для ваших токенов, вы можете использовать средство определения местоположения Bison, которое хранит объект местоположения для каждого токена и нетерминала отдельно от семантического значения. В действии вы указываете местоположение символа как @n
.
Стек местоположений создается и поддерживается автоматически bison, если он видит, что вы упомянули местоположение где-либо в правиле.
По умолчанию тип данных местоположения:
typedef struct YYLTYPE {
int first_line;
int first_column;
int last_line;
int last_column;
} YYLTYPE;
Информация о расположении токенов должна быть установлена лексером. Если вы используете API по умолчанию, он хранится в глобальной переменной yylloc
. Синтаксический анализатор создаст информацию о местоположении для нетерминалов, используя диапазон от начала первого элемента продукции до конца последнего элемента. (Для пустых производств создается объект местоположения нулевой длины, начинающийся и заканчивающийся начальной позицией токена просмотра вперед.)
Оба эти значения по умолчанию можно переопределить, если это необходимо. Подробнее см. в руководстве по Bison.
Flex будет отслеживать номера строк, если их об этом попросят с помощью %option yylineno
, но не отслеживает позиции столбцов, что немного раздражает. Кроме того, для yylloc
требуется как начальный, так и конечный номер строки; yylineno
в flex-действии будет номером строки в конце токена. Чаще всего вы будете использовать макрос YY_USER_ACTION
для сохранения значения yylloc
; пример реализации (взятый из этого ответа, который вы должны прочитать, если используете этот код):
%option yylineno
%{
#define YY_USER_ACTION \
yylloc.first_line = yylloc.last_line; \
yylloc.first_column = yylloc.last_column; \
if (yylloc.first_line == yylineno) \
yylloc.last_column += yyleng; \
else { \
int col; \
for (col = 1; yytext[yyleng - col] != '\n'; ++col) {} \
yylloc.last_column = col; \
yylloc.last_line = yylineno; \
}
%}
#define YYSTYPE struct { int token; char *literal };
, возможно ли это?
- person linrongbin; 08.01.2020
#define YYSTYPE
; это обязательно доставит вам неприятности. Вы должны убедиться, что объявления видны везде, где они необходимы, а это значит, что они должны быть в сгенерированном bison заголовке. Для этого поместите объявление struct
(struct MyToken { ... }
) в блок code requires
вашего определения bison, а затем используйте %define api.value.type {struct MyToken}
, как описано в руководство bison. Если вам нужен более подробный ответ, задайте новый вопрос.
- person rici; 08.01.2020