Роль yylval в lex и yacc - PullRequest
       60

Роль yylval в lex и yacc

1 голос
/ 16 октября 2019

Я вижу много примеров, когда некоторые передают yytext yylval, а другие нет. Вот код для простого сумматора в lex и yacc

/* add.l */
digit [0-9]
%%
{digit}+ {sscanf(yytext, "%d", &yylval);
return(INT);
}
\+ return(PLUS);
\n return(NL);
. ;
%%
int yywrap() { return 1; }

и

/* add.y */
/* L = {INT PLUS INT NL} */
%token INT PLUS NL
%%
add: INT PLUS INT NL { printf("%d\n", $1 + $3);}
%%
#include "lex.yy.c"
yyerror(char *s) { printf("%s\n", s); }
main() {
 return yyparse();
}

Я не вижу такого кода, как printf (yylval) и т. Д. Почему код sscanf(yytext, "%d", &yylval) существует здесь,Используется ли здесь как-то yylval, что произойдет, если мы не добавим эту строку? Когда нам нужно включить такую ​​строку в lex?

Ответы [ 2 ]

3 голосов
/ 17 октября 2019

Глобальная переменная yylval используется для передачи семантического значения, связанного с токеном, от лексера к анализатору. Семантические значения символов доступны в действиях yacc как $1, $2 и т. Д. И устанавливаются для нетерминалов путем присвоения $$. Терминалы происходят от лексера, которому нужен какой-то способ передачи семантического значения парсеру. В реентерабельном сканере yylval обычно становится ссылочным аргументом для yylex, а не глобальной переменной, но в остальном служит той же цели.

В вашем конкретном примере токен INT имеет семантическое значениекоторый является значением целочисленного чтения. Поскольку в коде yacc нет объявлений %type / %union, семантические значения просто получают тип по умолчанию int, что просто прекрасно для хранения целочисленного значения.

0 голосов
/ 16 октября 2019

Взято из здесь (рекомендуется чтение):

В обычном (не входящем) парсере семантическое значение токена должно быть сохранено в глобальной переменной yylval. Когда вы используете только один тип данных для семантических значений, yylval имеет этот тип.

Это означает, что значения, связанные с токеном, хранятся в этой конкретной переменной.

...