Я в начале написания парсера SQL. Поэтому я создал файлы .l и .y.
.l файл:
%{
#include <stdio.h>
#include "parser.hpp"
void yyerror(char *s) {
fprintf (stderr, "%s\n", s);
}
extern FILE *yyin;
extern FILE *yyout;
int lineno = 1;
//todo: free?
char *tmp_str = (char *) malloc(100);
%}
%option noyywrap
alpha [a-zA-Z]
digit [0-9]
alnum {alpha}|{digit}
alnum_dash {alnum}|_
ID {alpha}+{alnum_dash}*
ICONST "0"|[0-9]{digit}*
FCONST "0"|{digit}*"."{digit}+
%%
"//".*\n ; // ingore comments
"(" { return LPAREN; }
")" { return RPAREN; }
"]" { return LBRACK; }
"[" { return RBRACK; }
"{" { return LBRACE; }
"}" { return RBRACE; }
";" { return SEMI; }
"." { return DOT; }
"," { return COMMA; }
"create"|"CREATE" { return CREATE; }
"show"|"SHOW" { return SHOW; }
"drop"|"DROP" { return DROP; }
"table"|"TABLE" { return TABLE; }
"int"|"INT" { return INT; }
"text"|"TEXT" { return TEXT; }
"real"|"REAL" { return REAL; }
{ID} {
sscanf(yytext, "%s", yylval.ident);
return ID;
}
{FCONST} {
sscanf(yytext, "%s", tmp_str);
yylval.val = tmp_str;
return FCONST;
}
{ICONST} {
sscanf(yytext, "%s", tmp_str);
yylval.val = tmp_str;
return ICONST;
}
"\n" { lineno += 1; }
[ \t\r\f]+ ; //ignore spaces
. { yyerror("Unknown character"); }
%%
.y файл:
%{
#include "../../App/Logic/TableManager.h"
#include <stdio.h>
#include <string>
#include <cstring>
extern FILE *yyin;
extern FILE *yyout;
extern int lineno;
extern int yylex();
void yyerror(char *s);
%}
%token CREATE SHOW DROP
%token TABLE
%token LPAREN RPAREN LBRACK RBRACK LBRACE RBRACE SEMI DOT COMMA
%token ID ICONST FCONST
%token INT REAL TEXT
%start expression
%type <ident> ID
%type <val> consts assign
%type <type> INT REAL TEXT type
%union {
char type[30];
char ident[100];
char *val;
}
%%
expression: statements SEMI;
statements: create_st body | create_st {addField("", "", "");} |
show_st | drop_st;
create_st: CREATE TABLE ID { initTable(yylval.ident); };
show_st: SHOW TABLE ID { };
drop_st: DROP TABLE ID {};
body: LPAREN decl RPAREN SEMI;
decl: variable | decl COMMA variable;
variable: ID type {
addField(yylval.ident, $2, "");
} | ID type assign {
addField(yylval.ident, $2, $3);
};
assign: LPAREN consts RPAREN { $$ = yylval.val; };
consts: ICONST | FCONST;
type: INT { strcpy($$, "int"); } |
REAL { strcpy($$, "real"); } |
TEXT { strcpy($$, "text"); };
%%
Я хочу создать таблицу, поэтому явведите "создать таблицу a (b int);"и не получаю ошибок, но когда я пытаюсь создать еще одну таблицу сразу после первого запроса, я получаю сообщение об ошибке.
Вот журнал отладки:
Starting parse
Entering state 0
Reading a token:create table a(b int);
Next token is token CREATE ()
Shifting token CREATE ()
Entering state 1
Reading a token: Next token is token TABLE ()
Shifting token TABLE ()
Entering state 9
Reading a token: Next token is token ID ()
Shifting token ID ()
Entering state 16
Reducing stack by rule 6 (line 39):
$1 = token CREATE ()
$2 = token TABLE ()
$3 = token ID ()
-> $$ = nterm create_st ()
Stack now 0
Entering state 6
Reading a token: Next token is token LPAREN ()
Shifting token LPAREN ()
Entering state 14
Reading a token: Next token is token ID ()
Shifting token ID ()
Entering state 19
Reading a token: Next token is token INT ()
Shifting token INT ()
Entering state 22
Reducing stack by rule 17 (line 59):
$1 = token INT ()
-> $$ = nterm type ()
Stack now 0 6 14 19
Entering state 25
Reading a token: Next token is token RPAREN ()
Reducing stack by rule 12 (line 49):
$1 = token ID ()
$2 = nterm type ()
-> $$ = nterm variable ()
Stack now 0 6 14
Entering state 21
Reducing stack by rule 10 (line 47):
$1 = nterm variable ()
-> $$ = nterm decl ()
Stack now 0 6 14
Entering state 20
Next token is token RPAREN ()
Shifting token RPAREN ()
Entering state 26
Reading a token: Next token is token SEMI ()
Shifting token SEMI ()
Entering state 30
Reducing stack by rule 9 (line 45):
$1 = token LPAREN ()
$2 = nterm decl ()
$3 = token RPAREN ()
$4 = token SEMI ()
-> $$ = nterm body ()
Stack now 0 6
Entering state 15
Reducing stack by rule 2 (line 36):
$1 = nterm create_st ()
$2 = nterm body ()
-> $$ = nterm statements ()
Stack now 0
Entering state 5
Reading a token:create table b(b int);
Next token is token CREATE ()
syntax error
Error: popping nterm statements ()
Stack now 0
Cleanup: discarding lookahead token CREATE ()
Stack now 0
1
Я полагаю, это происходит потому, что мой последнийсостояние не 0 (это 4-е), как говорится в выводе отладки. Но как сбросить состояния, чтобы подготовиться к еще одному запросу? Или может быть проблема другого рода. Спасибо.