我想传递令牌的实际字符串。如果我有一个名为 ID 的令牌,那么我希望我的 yacc 文件真正知道 ID 的名称。我想我必须使用 yylval 将字符串从 Flex 文件传递到 yacc 文件。我怎么做?
通过 yylval 返回字符串或任何复杂类型的关键是 yacc 在 y.tab.h 文件中创建的 YYSTYPE 联合。 YYSTYPE 是一个联合,其中包含 yacc 源文件中定义的每种标记类型的成员。例如,要返回与 yacc 源文件中的 SYMBOL 标记关联的字符串,您可以使用以下命令声明此 YYSTYPE 联合%union在 yacc 源文件中:
/*** Yacc's YYSTYPE Union ***/
/* The yacc parser maintains a stack (array) of token values while
it is parsing. This union defines all the possible values tokens
may have. Yacc creates a typedef of YYSTYPE for this union. All
token types (see %type declarations below) are taken from
the field names of this union. The global variable yylval which lex
uses to return token values is declared as a YYSTYPE union.
*/
%union {
long int4; /* Constant integer value */
float fp; /* Constant floating point value */
char *str; /* Ptr to constant string (strings are malloc'd) */
exprT expr; /* Expression - constant or address */
operatorT *operatorP; /* Pointer to run-time expression operator */
};
%type <str> SYMBOL
然后,在 LEX 源文件中存在与 SYMBOL 标记相匹配的模式。与该规则关联的代码负责返回表示 SYMBOL 的实际字符串。您不能只传递指向 yytext 缓冲区的指针,因为它是一个静态缓冲区,可以为每个匹配的标记重用。要返回匹配的文本,必须使用 _strdup() 在堆上复制静态 yytext 缓冲区,并通过 yyval.str 传递指向该字符串的指针。然后,yacc 规则与 SYMBOL 令牌的责任相匹配,以在使用完毕后释放堆分配的字符串。
[A-Za-z_][A-Za-z0-9_]* {{
int i;
/*
* condition letter followed by zero or more letters
* digits or underscores
* Convert matched text to uppercase
* Search keyword table
* if found
* return <keyword>
* endif
*
* set lexical value string to matched text
* return <SYMBOL>
*/
/*** KEYWORDS and SYMBOLS ***/
/* Here we match a keywords or SYMBOL as a letter
* followed by zero or more letters, digits or
* underscores.
*/
/* Convert the matched input text to uppercase */
_strupr(yytext); /* Convert to uppercase */
/* First we search the keyword table */
for (i = 0; i<NITEMS(keytable); i++) {
if (strcmp(keytable[i].name, yytext)==0)
return (keytable[i].token);
}
/* Return a SYMBOL since we did not match a keyword */
yylval.str=_strdup(yytext);
return (SYMBOL);
}}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)