Какова цель объединения в файле yacc? Является ли это напрямую связано с yylval в файле flex? Если вы не используете yylval, вам не нужно использовать union?
Yylval и union
Ответ 1
Цель union
состоит в том, чтобы разрешить сохранение объектов разных типов в узлах, испускаемых flex.
Чтобы лучше объяснить, вы можете, например:
%union
{
int intValue;
float floatValue;
char *stringValue;
}
в .y
, если вы хотите предоставить базовую поддержку типов int
, float
и string
. Что вы можете сделать с этим?
Две вещи:
Во-первых, вы можете автоматически устанавливать правильные значения при создании токенов. Подумайте о файле .l
предыдущего примера, вы можете:
[a-zA-Z][a-zA-Z0-9]* {
yylval.stringValue = strdup(yytext);
return IDENTIFIER;
}
[0-9]+ {
yylval.intValue = atoi(yytext);
return INTEGER;
}
[0-9]*\.[0-9]+"f"? {
yylval.floatValue = new atof(yytext);
return FLOAT;
}
Кроме того, вы можете использовать значение непосредственно в своей грамматике flex:
nexp: nexp '+' nexp { $<floatValue>$ = $<floatValue>1 + $<floatValue>3 }
Наконец, если вы планируете использовать дерево синтаксиса ООП, вы можете определить объединение как
%union
{
class ASTNode *node;
}
в котором ASTNode
является предковым классом любого вида синтаксиса node.
Ответ 2
Объявление %union
изменяет тип yylval
.
Руководство bison
объясняет:
В обычном (нерентабельном) синтаксическом анализаторе семантическое значение токена должно храниться в глобальной переменной
yylval
. Когда вы используете только один тип данных для семантических значений,yylval
имеет этот тип. Таким образом, если типint
(по умолчанию), вы можете записать это вyylex
:... yylval = value; /* Put value onto Bison stack. */ return INT; /* Return the type of the token. */ ...
Когда вы используете несколько типов данных, тип
yylval
- это объединение, сделанное из объявления%union
(см. раздел "Коллекция типов значений" ). Поэтому, когда вы храните значение токена, вы должны использовать правильный член союза. Если объявление%union
выглядит следующим образом:%union { int intval; double val; symrec *tptr; }
тогда код в
yylex
может выглядеть следующим образом:... yylval.intval = value; /* Put value onto Bison stack. */ return INT; /* Return the type of the token. */ ...