好几天没有写笔记了。今天早晨的时候刚刚把自己简化的一些SQL语句语法树实现,把代码贴这里做记录。
发现JavaCC还是相当强的,词法和语法分析放到了一起。不过jjtree在使用中还是觉得有这么几点用着不爽的地方:
1 生成的节点似乎不能在jjt文件里个性化,这个很郁闷。必须生成完了以后再一个个修改。
2 一般这种文法文件都暴长,没有找到include这种特性
3 没有附带的语法提示功能。
不过,文档倒还好,都看懂了。在readme引导下,那些例子的确可以让人在一天或者两天之内可以写一个比较像样的jj或者jjt文件。
下面的文法文件实现了SQL的Create Table,Drop Table, Insert, Update, Delete, Constraint 几个语句,有一些常用的操作符还没有实现,比如Between,只是实现平常的一些操作符就够恶心的了。
嗯,我也是刚学会一两天而已,写的本应该很烂。。
不多说,下面贴下代码做个纪念,还要继续做。做完了以后再发最终的。当然,只是DB的一个大作业,作业的目的是实现完整性检查,是没有必要实现所有SQL功能的,所以只是挑了几个语句实现。
/*
TODO:
implement operation of like, in, between and, not between and, is null
implement statement of alter table
*/
options {
MULTI=true;
NODE_EXTENDS="InterpreterNode";
TRACK_TOKENS=true;
IGNORE_CASE = true;
}
PARSER_BEGIN(SSQLParser)
/** SSQL Language parser. */
public class SSQLParser {
public static void main(String args[])
{
SSQLParser parser = new SSQLParser(System.in);
try {
SSQLParser.CompilationUnit();
} catch (ParseException e) {
e.printStackTrace();
}
@SuppressWarnings("unused")
Node n = parser.rootNode();
}
public Node rootNode() {
return jjtree.rootNode();
}
}
PARSER_END(SSQLParser)
SKIP : /* WHITE SPACE */
{
" "
| "/t"
| "/n"
| "/r"
| <SINGLE_LINE_COMMENT: "//" (~["/n","/r"])* ("/n"|"/r"|"/r/n")>
}
TOKEN : /* LITERALS */
{
< NUMBER_LITERAL:
<INTEGER_LITERAL>
| <FLOATING_POINT_LITERAL>
>
|
< #INTEGER_LITERAL:
<DECIMAL_LITERAL>
>
|
< #DECIMAL_LITERAL: "0" | ["1"-"9"] (["0"-"9"])* >
|
< #FLOATING_POINT_LITERAL:
(["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)?
| "." (["0"-"9"])+ (<EXPONENT>)?
| (["0"-"9"])+ <EXPONENT>
>
|
< #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
|
< STRING_LITERAL:
(
"/""
( (~["/"","/n","/r"])
)*
"/""
)
|
(
"/'"
( (~["/'","/n","/r"])
)*
"/'"
)
>
}
void CompilationUnit() :
{
}
{
[Statement()]
(
LOOKAHEAD(2)
";" Statement()
)*
[";"]
<EOF>
}
void Statement() #void :{}
{
CreateTableStatement()
|
DropTableStatement()
|
DescribeTableStatement()
|
SelectStatement()
|
UpdateStatement()
|
DeleteStatement()
|
InsertIntoStatement()
}
/* Create Table ***************************/
void CreateTableStatement():{}
{
"create" "table" SimpleName()
"("
ColumnDefinition()
(
"," (ColumnDefinition() | NamedConstraint())
)*
")"
}
void ColumnDefinition() :{}
{
SimpleName() Type() ( NonnameConstraint() )*
}
void NonnameConstraint() #void :{}
{
("not" "null" #NotNullConstraintInline)
|
("unique" #UniqueConstraintInline)
|
("primary" "key" #PrimaryKeyConstraintInline)
|
CheckConstraintInline()
|
ForeignKeyConstraintInline()
}
void CheckConstraintInline():{}
{
"check" "(" Expression() ")"
}
void ForeignKeyConstraintInline():{}
{
"foreign" "key" "references" SimpleName() "(" SimpleName() ")"
}
void NamedConstraint() #void :{}
{
LOOKAHEAD(3)
NotNullConstraint()
|
LOOKAHEAD(3)
UniqueConstraint()
|
LOOKAHEAD(3)
PrimaryKeyConstraint()
|
LOOKAHEAD(3)
CheckConstraint()
|
ForeignKeyConstraint()
}
void NotNullConstraint():{}
{
"constraint" SimpleName() "not" "null"
"("
SimpleName() ("," SimpleName())*
")"
}
void UniqueConstraint():{}
{
"constraint" SimpleName() "unique"
"("
SimpleName() ("," SimpleName())*
")"
}
void PrimaryKeyConstraint():{}
{
"constraint" SimpleName() "primary" "key"
"("
SimpleName() ("," SimpleName())*
")"
}
void CheckConstraint():{}
{
"constraint" SimpleName() "check"
"("
Expression()
")"
}
void ForeignKeyConstraint():{}
{
"constraint" SimpleName() "foreign" "key" "(" SimpleName() ")"
"references" SimpleName() "(" SimpleName() ")"
}
/* Drop Table ************************/
void DropTableStatement():{}
{
"drop" "table" SimpleName()
}
/* Describe Table ************************/
void DescribeTableStatement():{}
{
("desc" | "describe") SimpleName()
}
/* Select ************************/
void SelectStatement():{}
{
"select" SelectorList() "from" TableList()
["where" Expression()]
["order" "by" OrderList()]
}
void SelectorList():{}
{
"*"
|
Selector() ("," Selector())*
}
void Selector():{}
{
Name() ["as" SimpleName()]
}
void TableList():{}
{
SimpleName()( "," SimpleName() )*
}
void OrderList():{}
{
OrderNode()
("," OrderNode())*
}
void OrderNode() #void:
{
Token t = null;
}
{
LOOKAHEAD(2)
AscendingOrder()
|
DescendingOrder()
}
void AscendingOrder():{}
{
Name() ["asc"]
}
void DescendingOrder():{}
{
Name() "desc"
}
/* Update ************************/
void UpdateStatement():{}
{
"update" SimpleName()
"set" SetList()
["where" Expression()]
}
void SetList():{}
{
Setter()
( "," Setter() )*
}
void Setter():{}
{
SimpleName() "=" Expression()
}
/* Delete ************************/
void DeleteStatement():{}
{
"delete"
(
"*" "from" SimpleName()
|
"from" SimpleName() ["where" Expression()]
)
}
/* Insert ************************/
void InsertIntoStatement():{}
{
"insert" "into" SimpleName() ["(" ColumnList() ")"]
"values" "(" ExpressionList() ")"
}
void ExpressionList():{}
{
Expression()
( "," Expression() )*
}
void ColumnList():{}
{
SimpleName()
("," SimpleName())*
}
/* Expression ************************/
void Expression() #void:
{}
{
ConditionalOrExpression()
}
void ConditionalOrExpression() #void :
{}
{
ConditionalAndExpression()
( "or" ConditionalAndExpression() #OrNode(2) )*
}
void ConditionalAndExpression() #void :
{}
{
EqualityExpression()
( "and" EqualityExpression() #AndNode(2) )*
}
void EqualityExpression() #void :
{}
{
RelationalExpression()
(
"=" RelationalExpression() #EQNode(2)
|
("<>" | "!=") RelationalExpression() #NENode(2)
)*
}
void RelationalExpression() #void :
{}
{
AdditiveExpression()
(
"<" AdditiveExpression() #LTNode(2)
|
">" AdditiveExpression() #GTNode(2)
|
"<=" AdditiveExpression() #LENode(2)
|
">=" AdditiveExpression() #GENode(2)
)*
}
void AdditiveExpression() #void :
{}
{
MultiplicativeExpression()
(
"+" MultiplicativeExpression() #AddNode(2)
|
"-" MultiplicativeExpression() #SubtractNode(2)
)*
}
void MultiplicativeExpression() #void :
{}
{
UnaryExpression()
(
"*" UnaryExpression() #MulNode(2)
|
"/" UnaryExpression() #DivNode(2)
|
"%" UnaryExpression() #ModNode(2)
)*
}
void UnaryExpression() #void :
{}
{
"not" UnaryExpression() #NotNode(1)
|
PrimaryExpression()
}
void PrimaryExpression() #void :
{
String name;
}
{
Literal()
|
Name()
|
"(" Expression() ")"
}
/* Basics ****************************/
void Type() #void : {}
{
"string" #StringType
|
"number" #NumberType
|
"boolean" #BoolType
}
void Literal()#void:{}
{
NumberLiteral()
|
StringLiteral()
|
BooleanLiteral()
}
void NumberLiteral():
{
Token t = null;
}
{
t = <NUMBER_LITERAL>
{
jjtThis.value
= Float.parseFloat(t.image);
}
}
void StringLiteral():
{
Token t = null;
}
{
t = <STRING_LITERAL> { jjtThis.value = t.image.substring(1, t.image.length()-1); }
}
void BooleanLiteral() #void:{}
{
"true" #TrueLiteral
|
"false" #FalseLiteral
}
void Name()#void:{}
{
SimpleName()
|
QualifiedName()
}
void SimpleName():
{
Token t = null;
}
{
t = <IDENTIFIER> { jjtThis.value = t.image; }
}
void QualifiedName():
{
Token t = null;
}
{
t = <QUALIFIEDNAME> { jjtThis.value = t.image; }
}
TOKEN : /* IDENTIFIERS */
{
< IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* >
|
< QUALIFIEDNAME: <IDENTIFIER>"."<IDENTIFIER> >
|
< #LETTER: ["a"-"z","A"-"Z"]>
|
< #DIGIT: ["0"-"9"] >
}