йылвал и союз - PullRequest
       70

йылвал и союз

17 голосов
/ 05 декабря 2009

Какова цель объединения в файле yacc? Это напрямую связано с yylval в файле flex? Если вы не используете yylval, тогда вам не нужно использовать union?

Ответы [ 2 ]

26 голосов
/ 05 декабря 2009

Цель union состоит в том, чтобы позволить хранить различные типы объектов в узлах, испускаемых flex.

Чтобы объяснить лучше, вы можете иметь, например:

%union
{
    int intValue;
    float floatValue;
    char *stringValue;
}

in .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;
}

Кроме того, вы можете использовать значение непосредственно в вашей гибкой грамматике :

nexp: nexp '+' nexp { $<floatValue>$ = $<floatValue>1 + $<floatValue>3 }

Наконец, если вы планируете использовать синтаксическое дерево ООП, вы можете определить объединение как

%union
{
    class ASTNode *node;
}

, в котором ASTNode является классом предка любого синтаксического узла.

14 голосов
/ 05 декабря 2009

Объявление %union изменяет тип yylval.

Руководство bison объясняет :

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

...
yylval = value;  /* Put value onto Bison stack. */
return INT;      /* Return the type of the token. */
...

Когда вы используете несколько типов данных, тип yylval является объединением, сделанным из объявления %union (see section Коллекция типов значений). Поэтому, когда вы сохраняете значение токена, вы должны использовать правильного члена объединения. Если объявление %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. */
...
...