1

我正在为资产交换格式构建解析器。我在野牛文件中包含了 %token-table 指令,但是,从弹性代码中,我无法访问表或与之关联的常量。那是在尝试编译此代码时:

Frame|FrameTransformMatrix|Mesh|MeshNormals|MeshMaterialList|Material {
    printf("A keyword: %s\n", yytext);
    yylval.charptr_type = yytext;

    int i;
    for (i = 0; i < YYNTOKENS; i++)
    {
        if (yytname[i] != 0
            && yytname[i][0] == '"'
            && !strncmp(yytname[i] + 1, yytext, strlen(yytext))
            && yytname[i][strlen(yytext) + 1] == '"'
            && yytname[i][strlen(yytext) + 2] == 0)
            return i;
    }
}

gcc 说 YYNTOKENS 和 yytname 都没有声明。那么令牌表是否最终被弃用并被清除,或者是怎么回事?

4

3 回答 3

1
于 2012-10-14T04:17:46.117 回答
1

There's a quick and easy way around the 'static' issue. I was trying to print a human readable abstract syntax tree with string representations of each non-terminal for my C to 6502 compiler. Here's what I did...

In your .y file in the last section, create a non-static variable called token_table

%%
#include <stdio.h>

extern char yytext[];
extern int column;
const char ** token_table;
...

Now, in the main method that calls yyparse, assign yytname to token_table

int main(int argc, char ** argv) {
    FILE * myfile;
    yydebug = 1;
    token_table = yytname;
    ...

Now, you can access token_table in any compilation unit simply by declaring it as an extern, as in:

extern const char ** token_table;

/* Using it later in that same compilation unit */
printf("%s", token_table[DOWHILE - 258 + 3]); /* prints "DOWHILE" */

For each node in your AST, if you assign it the yytokentype value found in y.tab.h, you simply subtract 258 and add 3 to index into token_table (yytname). You have to subtract 258 b/c that is where yytokentype starts enumerating at and you have to add 3 b/c yytname adds the three reserved symbols ("$end", "error", and "$undefined") at the start of the table.

For instance, my generated bison file has:

static const char *const yytname[] =
{
    "$end", "error", "$undefined", "DOWHILE", "UAND", "UMULT", "UPLUS",
    "UMINUS", "UBANG", "UTILDE", "ARR", "NOOP", "MEMBER", "POSTINC",
    ...

And, the defines header (run bison with the --defines=y.tab.h option):

/* Tokens.  */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
   /* Put the tokens into the symbol table, so that GDB and other debuggers
      know about them.  */
   enum yytokentype {
     DOWHILE = 258,
     UAND = 259,
     UMULT = 260,
     ...
于 2013-06-16T22:47:22.777 回答
0

The easiest way to avoid the static symbol problem is to #include the lexer directly in the third section of the bison input file:

/* token declarations and such */
%%
/* grammar rules */
%%

#include "lex.yy.c"

int main() {
  /* the main routine that calls yyparse */
}

Then you just compile the .tab.c file, and that's all you need.

于 2013-06-17T04:02:36.760 回答