我正在编写一些SQL操作,并使用本文链接的语言定义:SQL lex yacc grammar
我看到,当我试图调用一个函数来检测insert语句的表名时,我在yytext上得到了以下标记。我的代码这样调用函数:

insert_statement:
        INSERT INTO table opt_column_commalist values_or_query_spec
    ;
[..]
table:
        NAME {setGlobalTablename(yytext);}
    |   NAME '.' NAME
    ;
[..]

当我使用这样的有效查询运行它时:
INSERT INTO users (uid,username,ocupation,age) VALUES (1,'john','tech','30');

我在yytext值中调用的函数中得到的标记是“(”。
我明白,要断定令牌是一个表,它必须读取下一个令牌(在本例中为“(”),但我不知道如何获取真正的表名(用户)。实际上,它不是前一个令牌,而是前两个,因为空间也被认为是一个令牌。
我不知道我是否理解错了什么,但我找不到取名字的方法。

最佳答案

不要在解析器中读取yytext——因为您发现它包含的令牌可能是不可预测的,因为解析器可能会预先读取一个令牌,以决定何时移动或减少。
相反,您应该读取lexer中的yytext(并且仅在lexer中),如果您需要解析器中的值,则应复制它。所以你最终得到了一个lexer规则,比如:

[a-zA-Z][a-zA-Z0-9]*    { yylval.str = strdup(yytext); return NAME }

在解析器中:
%union {
    char *str;
      :
}
%token <str> NAME
     :
%%
     :
table:  NAME { setGlobalTableName($1); }
     |  NAME '.' NAME  ...

10-04 11:16