В бизоне есть способ вернуть имя токена вместо его типа

Я работаю с Flex и Bison. в моем parse.y (bison) я определяю токены. Когда токен возвращается, он возвращает int. Мне было интересно, есть ли способ взять этот int и сопоставить его с фактическим именем в источнике bison. Например в моем parser.y

//define my tokens that are shared with my lexer (flex)
%token <tokenData> ID
%token <tokenData> NUMCONST

в моей грамматике я затем использую

number : NUMCONST   {std::cout<<"Line "<<$1->linenum<<" Token: [I want NUMCONST]"<<<std::endl;}

Я знаю, что могу отобразить int, возвращаемый лексером, но его нет, чтобы вернуть тип токена, такой как «NUMCONST» или «ID». Я хочу токен "type" вместо токена "int"


person ajputnam    schedule 08.09.2015    source источник


Ответы (2)


bison генерирует enum под названием yytokentype, который содержит нумерованный список всех лексем в грамматике. Он не обеспечивает эквивалентного сопоставления строк, содержащих все имена токенов.

Итак, вам придется реализовать это отображение самостоятельно. То есть реализация служебной функции, которая принимает параметр yytokentype и возвращает имя данного токена, которое вы впоследствии можете использовать в своих диагностических сообщениях. Еще одна, скучная switch ферма.

Сказав это, не должно быть слишком сложно написать служебный Perl скрипт или эквивалент, который читает <filename>.tab.h, полученный из bison, анализирует yytokentype перечисление и робо-генерирует функцию сопоставления. Вставьте это в свой Makefile с подходящим правилом зависимости, и вы получите автоматический робо-генератор функции сопоставления токена с именем.

person Sam Varshavchik    schedule 08.09.2015

Да, вы можете, но вам нужно включить эту функцию в вашем файле bison.

Если вы поместите директиву %token-table в свой файл bison, тогда bison сгенерирует таблицу имен токенов под названием yytname. (Вы также можете включить эту функцию с помощью флагов командной строки -k или --token-table.)

yytname[i] - это имя токена, чей «внутренний кодовый номер токена Bison» равен i. Это не то же самое, что число, возвращаемое yylex, потому что bison перекодирует токены, используя (недокументированную) таблицу с именем yytranslate.

Имена токенов в таблице yytname являются псевдонимами токенов, если вы используете эту функцию. Например, если ваша грамматика включает:

%token EQEQ "=="
%%
exp: exp "==" exp
   | exp '+' exp

имена токенов, соответствующих двум операторам, показанным в правиле exp, - это "==" и '+'.

yytname также включает имена нетерминалов на тот случай, если они вам понадобятся для каких-либо целей.

Вместо использования yytranslate[t] вы можете использовать YYTRANSLATE(t), что и делает сам сканер, созданный bison. Этот макрос переводит целые числа вне диапазона в 2, которому соответствует имя $undefined. Это имя также будет отображаться для любых односимвольных токенов, которые нигде не используются в грамматике Bison.

И yytname, и yytranslate объявлены static const в сканере, созданном bison, поэтому вы можете использовать их только в коде, который присутствует в этом файле. Если вы хотите предоставить функцию, которая выполняет перевод, вы можете поместить эту функцию в эпилог грамматики после второго %%. (Такая функция может понадобиться, если вы хотите найти имя, соответствующее номеру токена, например, в сканере.) Это может выглядеть примерно так:

const char token_name(int t) {
  return yytname[YYTRANSLATE(t)];
}

Обычно в этом нет необходимости. Если вы просто хотите отслеживать, что делает парсер, лучше включить средство трассировки.

person rici    schedule 08.09.2015
comment
Это правильный ответ, а не принятый. Не нужно разбирать выходной файл Bison. - person DanJAB; 31.10.2015