2014-02-04 3 views
0

Я кодирование некоторые SQL манипуляции и я использую определение языка, связанное в этом посте: SQL lex yacc grammarпредыдущего маркер на YACC/Lex

Я вижу, что, когда я пытаюсь invoque функции на обнаружение имени таблицы базы 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 является «(».

Я понимаю, что для того, чтобы сделать вывод, что токен является таблицей, он должен прочитать следующий токен (в данном случае '('), но я не знаю, как получить реальное имя таблицы (пользователей). факт, это не предыдущий токен, а два раньше, так как пространство также считается токеном.

Я не знаю, пропущу ли я что-то, но я не могу найти способ получить имя.

ответ

3

Не читайте в парсере yytext - как вы обнаружили, это может быть непредсказуемо, какой токен он содержит, поскольку анализатор может прочитать перед собой токен, чтобы решить, когда сдвигать или уменьшать.

Вместо этого вы должны прочитать yytext в лексере (и только в лексере) и сделать его копию, если вам понадобится значение в синтаксическом анализаторе. Таким образом, вы в конечном итоге с правилом лексического анализатора, как:

[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 ... 
Смежные вопросы