博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
练手写了个SQLite解析器
阅读量:6136 次
发布时间:2019-06-21

本文共 3165 字,大约阅读时间需要 10 分钟。

hot3.png

    书看了大半,天马行空似懂非懂。返回头看看感觉没学到什么东西,所以还是动手尝试下。实际这个解析器只是sqlite语法的一个create table语法,而且也没完全实现(不支持check约束和指定数据库)。

   

     为了定一个模子我先写了一个create table 的antlr文法(如下)照着做的。

grammar sqlitcreatetable;@members{private boolean isType(String id){	id=id.toLowerCase();	return id.equals("int")|| id.equals("integer") 			||id.equals("bool")||id.equals("boolean")			||id.equals("long")			||id.equals("short")||id.equals("byte")			||id.equals("float")			||id.equals("real")||id.equals("double")			||id.equals("blob")			||id.equals("text")||id.equals("varchar")||id.equals("nvarchar")||id.equals("string")||id.equals("char");}}createTableStatment	:	'create' (temp='temp'|temp='temporary')? 'table' ('if' 'not' 'exists')?	 name	 columnList ';'?	 {	 	System.out.print(($temp.text!=null? "temporary ":"") + "table:"+$name.text);	 }	;columnList	:	'(' column (',' column)* ')' 	;	column	:		name	type typelimit?	constainst*	{	 	System.out.println("column:" +$name.text +" "+$type.text);	}	;typelimit	:	'(' a=INT ( ',' b=INT)? ')'	{		if($a.text!=null && $b.text!=null){			System.out.print("(" +$a.text+ ","+$b.text+")");		}else if($a.text!=null ){			System.out.print("(" +$a.text+")");		}	}	;	type	:	{ isType( input.LT(1).getText() ) }?ID	;constainst	:	'primary' 'key'	{System.out.print(" primary key"); }	|	'unique'	{System.out.print(" unique"); }	|	'default' '(' (v=INT|v=FLOAT|v=STRING) ')'	{System.out.print(" default("+$v.text+")"); }	|	'not' 'null'	{System.out.print(" not null"); }	|	'autoincrement' {System.out.print(" autoincrement"); }	;name	:	'[' ID ']'	|	ID	;ID  :	('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*    ;INT :	'0'..'9'+    ;FLOAT    :   ('0'..'9')+ '.' ('0'..'9')* EXPONENT?    |   '.' ('0'..'9')+ EXPONENT?    |   ('0'..'9')+ EXPONENT    ;COMMENT    :   '--' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}    |   '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}    ;STRING    :  '\'' ( ESC_SEQ | ~('\\'|'\'') )* '\''    ;fragmentEXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;fragmentHEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;fragmentESC_SEQ    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')    |   UNICODE_ESC    |   OCTAL_ESC    ;fragmentOCTAL_ESC    :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')    |   '\\' ('0'..'7') ('0'..'7')    |   '\\' ('0'..'7')    ;fragmentUNICODE_ESC    :   '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT    ;     WS  :   ( ' '        | '\t'        | '\r'        | '\n'        ) {$channel=HIDDEN;}    ;

 

 

   生成这个文法的代码调试输入create table 语句则会输出表、列、列类型和约束信息。

 

   sqlite的create table 语法还是比较简单的,用LL(1)即可以实现了。比较麻烦的还是词法分析部分,由于  Terence Parr讲解的例子里面未涉及到关键字的识别,所以对于关键字的识别我采用了向前看(n+1)来判断是否为某关键字。这个算法(isKW函数)或许是错误的方法请各位有经验的朋友指教。

    代码没神码好贴的了有兴趣的朋友下载代码编译跑跑。看看输入内容

" create temporary table\n/*MLComment*/ IF NOT EXISTS [table_name] (\n[a1] int  unique not null,b1 double(22) primary key,c1 string(1,2) AUTOINCREMENT,e1 float not null,ff char default(0.123) )--SLComment";

 

 在节点的保存上我采用了简单的收集需要的节点,而不是异形树或同型树之类,遍历的结果将输出这样的

MLCommentSLCommenttbl--temporaray table_nameColumn--a1 int unique not nullColumn--b1 double(22) primary keyColumn--c1 string(1,2) autoincrementColumn--e1 float not nullColumn--ff string default(0.123)

 

转载于:https://my.oschina.net/droidwolf/blog/285414

你可能感兴趣的文章
Qt Style Sheet实践(四):行文本编辑框QLineEdit及自动补全
查看>>
[物理学与PDEs]第3章习题1 只有一个非零分量的磁场
查看>>
深入浅出NodeJS——数据通信,NET模块运行机制
查看>>
onInterceptTouchEvent和onTouchEvent调用时序
查看>>
android防止内存溢出浅析
查看>>
4.3.3版本之引擎bug
查看>>
SQL Server表分区详解
查看>>
使用FMDB最新v2.3版本教程
查看>>
SSIS从理论到实战,再到应用(3)----SSIS包的变量,约束,常用容器
查看>>
STM32启动过程--启动文件--分析
查看>>
垂死挣扎还是涅槃重生 -- Delphi XE5 公布会归来感想
查看>>
淘宝的几个架构图
查看>>
Android扩展 - 拍照篇(Camera)
查看>>
JAVA数组的定义及用法
查看>>
充分利用HTML标签元素 – 简单的xtyle前端框架
查看>>
设计模式(十一):FACADE外观模式 -- 结构型模式
查看>>
iOS xcodebuile 自动编译打包ipa
查看>>
程序员眼中的 SQL Server-执行计划教会我如何创建索引?
查看>>
cmake总结
查看>>
数据加密插件
查看>>