Если вы хотите сохранить информацию о местоположении (номер строки и номер столбца) для своих токенов, вы можете использовать средство определения местоположения Bison, которое хранит объект местоположения для каждого токена и нетерминал отдельно от семантического значения.В действии вы обозначаете местоположение символа как @n
.
Стек локаций создается и поддерживается автоматически зубром, если он обнаруживает, что вы указали местоположение в любом месте правила.
По умолчанию тип данных местоположения:
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; \
}
%}