Как сбросить состояние при разборе выражения? - PullRequest
0 голосов
/ 30 сентября 2019

Я в начале написания парсера 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-е), как говорится в выводе отладки. Но как сбросить состояния, чтобы подготовиться к еще одному запросу? Или может быть проблема другого рода. Спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...