Возможно, yylval будет структурой, а не объединением?

В Bison возможно, что yylval будет структурой, а не объединением? Я знаю, что могу определить yylval как объединение с %union{}, но есть ли способ определить yylval как структуру? чтобы вернуть строку и строку идентификатора для примера и получить доступ к этой информации по действию некоторого грамматического правила на бизоне.


person Joao Pedro    schedule 25.11.2018    source источник


Ответы (2)


Да, вы можете #define YYSTYPE быть любым типом вместо использования %union. Однако это редко бывает полезно1. Если вам нужна информация об исходной позиции, лучше использовать %position в сочетании с %union.

Также возможно (и распространено) использование структур внутри объявления %union. Это позволяет некоторым правилам легко возвращать несколько значений (эффективно).


1Основная проблема заключается в том, что если вы используете %type для указания использования одного поля структуры, использование других полей в том же действии будет болезненным. Вам нужно делать все вручную, тем самым теряя преимущества проверки типов объединения bison

person Chris Dodd    schedule 25.11.2018

Если вы хотите сохранить информацию о местоположении (номер строки и номер столбца) для ваших токенов, вы можете использовать средство определения местоположения 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;                            \
  }
%}
person rici    schedule 26.11.2018
comment
Я хочу сохранить в yylval как yytext, так и целое число токенов, например #define YYSTYPE struct { int token; char *literal };, возможно ли это? - person linrongbin; 08.01.2020
comment
@linrongbin: Конечно. Однако не используйте #define YYSTYPE; это обязательно доставит вам неприятности. Вы должны убедиться, что объявления видны везде, где они необходимы, а это значит, что они должны быть в сгенерированном bison заголовке. Для этого поместите объявление struct (struct MyToken { ... }) в блок code requires вашего определения bison, а затем используйте %define api.value.type {struct MyToken}, как описано в руководство bison. Если вам нужен более подробный ответ, задайте новый вопрос. - person rici; 08.01.2020