小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

用Lex和Yacc做一個(gè)簡(jiǎn)單的SQL解釋器

 Keamou 2009-11-18

前段時(shí)間做了一個(gè)簡(jiǎn)單的內(nèi)存數(shù)據(jù)庫(kù),需要提供點(diǎn)簡(jiǎn)單的SQL支持,在參考了《Lex與Yacc》和網(wǎng)上的相關(guān)資料后,以《Lex與Yacc》中的SQL解釋器為基礎(chǔ),做了修改,最后生成了一個(gè)簡(jiǎn)單的SQL解釋器。
這個(gè)SQL解釋器由于本身內(nèi)存數(shù)據(jù)庫(kù)提供的功能限制,提供的SQL也有很多的限制:
1、select不支持按字段取值,一次查詢獲取所有字段
2、查詢條件之間的關(guān)系只支持AND
3、UPDATE一次只更新一個(gè)字段
4、不支持函數(shù)

在SQL解釋器中,關(guān)鍵是我們要構(gòu)建我們的語(yǔ)法結(jié)構(gòu),也就是最終通過(guò)SQL解釋器要生成的一個(gè)程序能識(shí)別的結(jié)構(gòu)。負(fù)責(zé)的SQL支持對(duì)應(yīng)負(fù)責(zé)的負(fù)責(zé)的結(jié)構(gòu),因?yàn)槲覀冎С值腟QL簡(jiǎn)單,所以相對(duì)應(yīng)的結(jié)構(gòu)也就很簡(jiǎn)單了。

主題程序由3個(gè)文件組成,sql_plan.h parser_lex.l parser_yacc.y。其中,sql_plan.h是語(yǔ)法結(jié)構(gòu)的定義,parser_lex.l是詞法解釋和主程序入口部分,parser_yacc.y是語(yǔ)法解釋部分。

#ifndef __SQL_DEFINE__
#define __SQL_DEFINE__

#define NAME_SIZE   24
#define MAX_BUFFER_SIZE  8192

typedef enum
{
    SQL_SELECT = 1,
    SQL_INSERT,
    SQL_UPDATE,
    SQL_DELETE,
    SQL_COUNT_ALL
}sql_action;

typedef struct{
    char field_name[NAME_SIZE];
    char field_value[256];
}FieldNameValue;

typedef struct{
    int list_len;
    FieldNameValue fnv_par[5];
}FieldNameValue_List;

typedef struct{
    int    action;    
    char tab_name[256];
    FieldNameValue_List w_fnv_list;
    char u_field_name[256];
    char u_field_value[256];
    int pos;
    char buffer[MAX_BUFFER_SIZE];
}SQL_PLAN;

extern SQL_PLAN sql_plan;

#endif
sql_plan.h



parser_lex.l
%{

#include "parser_yacc.h"
#include "sql_define.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int lineno = 1;
void yyerror(char *s);

void TrimString(char *str)
{
        char *copied, *tail = NULL;
        if ( str == NULL )
                return;

        for( copied = str; *str; str++ )
        {
                if ( *str != ' ' && *str != '\t' && *str != '\n' && 
                     *str != '\r' && *str != '\'' && *str != ';')
                {
                    *copied++ = *str;
                    tail = copied;                         
                }
                else
                {
                    if ( tail )
                        *copied++ = *str;
                }
        }

        if ( tail )
             *tail = 0;
        else
             *copied = 0;

        return;
}

char *_xInput;
int _xLen = 0;

int myinput(char *buff,int max)
{
    if(!_xLen) return 0;
    if(max > _xLen) max = _xLen   ;
    memcpy(buff,_xInput,max);
    _xInput += max;
    _xLen -= max;
    return   max;
}

#define YY_INPUT(b, r, m) (r = myinput(b, m))

%}

%%

and        { return AND; }
CHAR(ACTER)?    { return CHARACTER; }
CLOSE        { return CLOSE; }
CREATE        { return CREATE; }
CURRENT        { return CURRENT; }
CURSOR        { return CURSOR; }
count        { return COUNT; }
DECLARE        { return DECLARE; }
delete        { return DELETE; }
DOUBLE        { return DOUBLE; }
FETCH        { return FETCH; }
FLOAT        { return FLOAT; }
FOR        { return FOR; }
from        { return FROM; }
insert        { return INSERT; }
INT(EGER)?    { return INTEGER; }
into        { return INTO; }
NOT        { return NOT; }
NULL        { return NULLX; }
NUMERIC        { return NUMERIC; }
OF        { return OF; }
OPEN        { return OPEN; }
OR        { return OR; }
REAL        { return REAL; }
select        { return SELECT; }
set        { return SET; }
table        { return TABLE; }
update        { return UPDATE; }
values        { return VALUES; }
where        { return WHERE; }

    /* punctuation */
"=" { return L_EQ; }

"<>"     |
"<"    |
">"    |
"<="    |
">="        { return COMPARISON; }

[-+*/:(),.;]    { return yytext[0]; }

    /* names */

[A-Za-z][A-Za-z0-9_]*    { strcpy(yylval.nameval,yytext); return NAME; }

    /* numbers */

-?[0-9]+    { yylval.intval = atoi(yytext); return INTNUM; }
[0-9]+"."[0-9]* { yylval.floatval = atof(yytext); return FLOATNUM; }

[0-9]+[eE][+-]?[0-9]+    |
[0-9]+"."[0-9]*[eE][+-]?[0-9]+ |
"."[0-9]*[eE][+-]?[0-9]+    { return APPROXNUM; }

    /* strings */
'[^'\n]*'    { TrimString(yytext); strcpy(yylval.strval,yytext); return STRING; }    
        
'[^\'\n]*$    { yyerror("Unterminated string"); }

\n        lineno++;

[ \t\r]+    ;    /* white space */

"--".*$        ;    /* comment */

%%

void yyerror(char *s)
{
    printf("%d: %s at %s\n", lineno, s, yytext);
}

int yywrap()    {return 1;}

main(int argc, char **argv)
{
    int pos;
    int ret;    
    char *buffer;
    char prompt_buffer[MAX_BUFFER_SIZE];
    char last_prompt_buffer[MAX_BUFFER_SIZE];
    int count;
            
    while(1)
    {
        printf("mdbsql>>");    
        fgets(prompt_buffer, sizeof(prompt_buffer), stdin);        
        
        _xInput = prompt_buffer;
        _xLen = strlen(prompt_buffer);
        
        if (prompt_buffer[0]=='\\')
        {
            strcpy(prompt_buffer, last_prompt_buffer);
            _xLen = strlen(prompt_buffer);
        }
        if (strncmp(prompt_buffer, "quit", 4)==0 || 
            strncmp(prompt_buffer, "exit", 4)==0
            )
        {
            break;
        }
                
        memset(&sql_plan, 0, sizeof(sql_plan) );
        strcpy(last_prompt_buffer, prompt_buffer);
        if(!yyparse())
        {                            
            if (sql_plan.action == SQL_SELECT)
            {                              
                  printf("%d records are retrieved\n", count);
              }
              else if (sql_plan.action == SQL_DELETE)
              {
                  printf("%d records are deleted\n", ret);
              }
              else if (sql_plan.action == SQL_UPDATE)
              {
                  printf("%d records are updated\n", ret);
              }
              else if (sql_plan.action == SQL_INSERT)
              {
                  if (ret>0) printf("1 record is inserted\n");
              }
              else if (sql_plan.action == SQL_COUNT_ALL)
              {
                  if (ret>0) printf("1 record is retrieved\n");
              }
        }
        else
        {    
            printf("SQL parse failed\n");
        }        
    }
}


parser_yacc.y
%{

#include "parser_yacc.h"
#include "sql_define.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int lineno = 1;
void yyerror(char *s);

void TrimString(char *str)
{
        char *copied, *tail = NULL;
        if ( str == NULL )
                return;

        for( copied = str; *str; str++ )
        {
                if ( *str != ' ' && *str != '\t' && *str != '\n' && 
                     *str != '\r' && *str != '\'' && *str != ';')
                {
                    *copied++ = *str;
                    tail = copied;                         
                }
                else
                {
                    if ( tail )
                        *copied++ = *str;
                }
        }

        if ( tail )
             *tail = 0;
        else
             *copied = 0;

        return;
}

char *_xInput;
int _xLen = 0;

int myinput(char *buff,int max)
{
    if(!_xLen) return 0;
    if(max > _xLen) max = _xLen   ;
    memcpy(buff,_xInput,max);
    _xInput += max;
    _xLen -= max;
    return   max;
}

#define YY_INPUT(b, r, m) (r = myinput(b, m))

%}

%%

and        { return AND; }
CHAR(ACTER)?    { return CHARACTER; }
CLOSE        { return CLOSE; }
CREATE        { return CREATE; }
CURRENT        { return CURRENT; }
CURSOR        { return CURSOR; }
count        { return COUNT; }
DECLARE        { return DECLARE; }
delete        { return DELETE; }
DOUBLE        { return DOUBLE; }
FETCH        { return FETCH; }
FLOAT        { return FLOAT; }
FOR        { return FOR; }
from        { return FROM; }
insert        { return INSERT; }
INT(EGER)?    { return INTEGER; }
into        { return INTO; }
NOT        { return NOT; }
NULL        { return NULLX; }
NUMERIC        { return NUMERIC; }
OF        { return OF; }
OPEN        { return OPEN; }
OR        { return OR; }
REAL        { return REAL; }
select        { return SELECT; }
set        { return SET; }
table        { return TABLE; }
update        { return UPDATE; }
values        { return VALUES; }
where        { return WHERE; }

    /* punctuation */
"=" { return L_EQ; }

"<>"     |
"<"    |
">"    |
"<="    |
">="        { return COMPARISON; }

[-+*/:(),.;]    { return yytext[0]; }

    /* names */

[A-Za-z][A-Za-z0-9_]*    { strcpy(yylval.nameval,yytext); return NAME; }

    /* numbers */

-?[0-9]+    { yylval.intval = atoi(yytext); return INTNUM; }
[0-9]+"."[0-9]* { yylval.floatval = atof(yytext); return FLOATNUM; }

[0-9]+[eE][+-]?[0-9]+    |
[0-9]+"."[0-9]*[eE][+-]?[0-9]+ |
"."[0-9]*[eE][+-]?[0-9]+    { return APPROXNUM; }

    /* strings */
'[^'\n]*'    { TrimString(yytext); strcpy(yylval.strval,yytext); return STRING; }    
        
'[^\'\n]*$    { yyerror("Unterminated string"); }

\n        lineno++;

[ \t\r]+    ;    /* white space */

"--".*$        ;    /* comment */

%%

void yyerror(char *s)
{
    printf("%d: %s at %s\n", lineno, s, yytext);
}

int yywrap()    {return 1;}

main(int argc, char **argv)
{
    int pos;
    int ret;    
    char *buffer;
    char prompt_buffer[MAX_BUFFER_SIZE];
    char last_prompt_buffer[MAX_BUFFER_SIZE];
    int count;
            
    while(1)
    {
        printf("mdbsql>>");    
        fgets(prompt_buffer, sizeof(prompt_buffer), stdin);        
        
        _xInput = prompt_buffer;
        _xLen = strlen(prompt_buffer);
        
        if (prompt_buffer[0]=='\\')
        {
            strcpy(prompt_buffer, last_prompt_buffer);
            _xLen = strlen(prompt_buffer);
        }
        if (strncmp(prompt_buffer, "quit", 4)==0 || 
            strncmp(prompt_buffer, "exit", 4)==0
            )
        {
            break;
        }
                
        memset(&sql_plan, 0, sizeof(sql_plan) );
        strcpy(last_prompt_buffer, prompt_buffer);
        if(!yyparse())
        {                            
            if (sql_plan.action == SQL_SELECT)
            {                              
                  printf("%d records are retrieved\n", count);
              }
              else if (sql_plan.action == SQL_DELETE)
              {
                  printf("%d records are deleted\n", ret);
              }
              else if (sql_plan.action == SQL_UPDATE)
              {
                  printf("%d records are updated\n", ret);
              }
              else if (sql_plan.action == SQL_INSERT)
              {
                  if (ret>0) printf("1 record is inserted\n");
              }
              else if (sql_plan.action == SQL_COUNT_ALL)
              {
                  if (ret>0) printf("1 record is retrieved\n");
              }
        }
        else
        {    
            printf("SQL parse failed\n");
        }        
    }
}


mdbsql:    parser_yacc.o parser_lex.o
    gcc -o $@ parser_yacc.o parser_lex.o  -lfl

parser_yacc.c parser_yacc.h:    parser_yacc.y
    yacc -vdt parser_yacc.y
    mv y.tab.h parser_yacc.h
    mv y.tab.c parser_yacc.c
    mv y.output parser_yacc.out

parser_lex.o:    parser_yacc.h parser_lex.c

parser_lex.c : parser_lex.l
    flex $<
    mv lex.yy.c $*.c
Makefile




上述程序在cygwin、redhat as5下測(cè)試過(guò)

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多