使用Lemon编写最简单的SQL解析器

使用SQLite自带的Lemon解析器生成工具,制作最简单的解析器。以解析器仅解析Create table语句。

以下的生成解析器所需的.y文件。

// All token codes are small integers with #defines that begin with "TK_"
%token_prefix TK_

// The type of the data attached to each token is Token.  This is also the
// default type for non-terminals.
// me:struct Token defined in sqliteInt.h
%token_type {Token}
%default_type {Token}

// The generated parser function takes a 4th argument as follows:
%extra_argument {Parse *pParse}

// This code runs whenever there is a syntax error
//
%syntax_error {
  //UNUSED_PARAMETER(yymajor);  /* Silence some compiler warnings */
  assert( TOKEN.z[0] );  /* The tokenizer always gives us a token */
  //sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
  printf("near \"%T\": syntax error", &TOKEN);
}

// The name of the generated procedure that implements the parser
// is as follows:
%name titaParser

// The following text is included near the beginning of the C source
// code file that implements the parser.
//
%include {
#include "Tita.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
} // end %include

cmdx ::= cmd.           { sqlite3FinishCoding(pParse); }

/ The CREATE TABLE statement 
//nm(Y)    table name
//dbnm(Z)  database name
cmd ::= create_table create_table_args SEMI.
create_table ::= createkw TABLE ifnotexists(E) nm(Y) dbnm(Z). {
   titaStartTable(pParse,&Y,&Z,E);
}

createkw(A) ::= CREATE(A).  {disableLookaside(pParse);}

//define the data type of ifnotexists that is non terminate symbol is int.
%type ifnotexists {int}
//if hasn't ifnotexists statemnet, set ifnotexists's value is 0.
ifnotexists(A) ::= .              {A = 0;}
ifnotexists(A) ::= IF NOT EXISTS. {A = 1;}

create_table_args ::= LP columnlist RP(E). {
  //sqlite3EndTable(pParse,&X,&E,F,0);
  titaEndTable(pParse,0,&E);
}

// An IDENTIFIER can be a generic identifier, or one of several
// keywords.  Any non-standard keyword can also be an identifier.
//
%token_class id  ID|INDEXED.

// The following directive causes tokens ABORT, AFTER, ASC, etc. to
// fallback to ID if they will not parse as their original value.
// This obviates the need for the "id" nonterminal.
//
%fallback ID
  ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW
  CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
  IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN
  QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW
  ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT
  .

// The name of a column or table can be any of the following:
//
%type nm {Token}
nm(A) ::= id(A).
nm(A) ::= STRING(A).

//dbnm(A) ::= .  ? can be empty
%type dbnm {Token}
dbnm(A) ::= .          {A.z=0; A.n=0;}
dbnm(A) ::= DOT nm(X). {A = X;}

//typetoken(Y):column type
columnlist ::= columnlist COMMA columnname.
columnlist ::= columnname.
//me:void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType)
columnname(A) ::= nm(A) typetoken(Y). {titaAddColumn(pParse,&A,&Y);}

// And "ids" is an identifer-or-string.
//
%token_class ids  ID|STRING.

%type typetoken {Token}
typetoken(A) ::= .   {A.n = 0; A.z = 0;}
typetoken(A) ::= typename(A).

%type typename {Token}
typename(A) ::= ids(A).
typename(A) ::= typename(A) ids(Y). {A.n=Y.n+(int)(Y.z-A.z);}

代码下载地址
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值