如何在yacc中使用yylval和字符串

neu*_*cer 5 yacc bison lexical-analysis

我想传递令牌的实际字符串.如果我有一个名为ID的令牌,那么我希望我的yacc文件实际知道调用了什么ID.我必须使用yylval将字符串传递给flex文件中的yacc文件.我怎么做?

Jon*_*onN 17

通过yylval返回字符串或任何复杂类型的关键是yacc在y.tab.h文件中创建的YYSTYPE联合.YYSTYPE是一个联合,其中包含yacc源文件中定义的每种令牌类型的成员.例如,要返回与yacc源文件中的SYMBOL标记关联的字符串,请在yacc源文件中使用%union声明此YYSTYPE联合:

/*** 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
Run Code Online (Sandbox Code Playgroud)

然后在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);
}}
Run Code Online (Sandbox Code Playgroud)


小智 7

请参阅有关与YACC接口的Flex手册部分.

15与Yacc接口

flex的主要用途之一是作为yacc解析器生成器的伴侣.yacc解析器期望调用名为yylex()的例程来查找下一个输入标记.该例程应该返回下一个标记的类型,并将任何相关值放在全局yylval中.要将flex与yacc一起使用,可以指定yacc的`-d'选项,以指示它生成包含yacc输入中出现的所有%标记定义的文件y.tab.h.然后,此文件包含在flex扫描仪中.例如,如果其中一个令牌为TOK_NUMBER,则部分扫描程序可能如下所示:

     %{
     #include "y.tab.h"
     %}

     %%

     [0-9]+        yylval = atoi( yytext ); return TOK_NUMBER;
Run Code Online (Sandbox Code Playgroud)

  • 这根本没有解释如何返回一个字符串,因为默认情况下YYSTYPE(这里没有提到)是int. (9认同)