21 namespace Deveel.Data.Sql.Parser {
33 public abstract string Dialect {
get; }
35 protected StringLiteral StringLiteral {
get;
private set; }
37 protected NumberLiteral NumberLiteral {
get;
private set; }
39 protected NumberLiteral PositiveLiteral {
get;
private set; }
41 protected IdentifierTerminal Identifier {
get;
private set; }
43 protected KeyTerm Comma {
get;
private set; }
45 protected KeyTerm Dot {
get;
private set; }
47 protected KeyTerm Colon {
get;
private set; }
49 protected KeyTerm As {
get;
private set; }
51 protected abstract NonTerminal MakeRoot();
54 var comment =
new CommentTerminal(
"multiline_comment",
"/*",
"*/");
55 var lineComment =
new CommentTerminal(
"singleline_comment",
"--",
"\n",
"\r\n");
56 NonGrammarTerminals.Add(comment);
57 NonGrammarTerminals.Add(lineComment);
61 StringLiteral =
new StringLiteral(
"string",
"'", StringOptions.AllowsAllEscapes, typeof(
StringLiteralNode));
62 NumberLiteral =
new NumberLiteral(
"number", NumberOptions.DisableQuickParse | NumberOptions.AllowSign, typeof(
NumberLiteralNode));
63 PositiveLiteral =
new NumberLiteral(
"positive", NumberOptions.IntOnly, typeof(
IntegerLiteralNode));
67 Identifier =
new IdentifierTerminal(
"simple_id");
68 var idStringLiteral =
new StringLiteral(
"simple_id_quoted");
69 idStringLiteral.AddStartEnd(
"\"", StringOptions.NoEscapes);
71 idStringLiteral.SetOutputTerminal(
this, Identifier);
75 RegisterOperators(10,
"*",
"/",
"%");
76 RegisterOperators(9,
"+",
"-");
77 RegisterOperators(8,
"=",
">",
"<",
">=",
"<=",
"<>",
"!=");
78 RegisterOperators(8, Key(
"LIKE"), Key(
"IN"), Key(
"IS"), Key(
"IS") + Key(
"NOT"));
79 RegisterOperators(7,
"^",
"&",
"|");
80 RegisterOperators(6, Key(
"NOT"));
81 RegisterOperators(5, Key(
"AND"));
82 RegisterOperators(4, Key(
"OR"));
100 MarkPunctuation(
",",
"(",
")",
"AS");
105 protected KeyTerm
Key(
string term) {
107 if (!KeyTerms.TryGetValue(term, out keyTerm))
108 KeyTerms[term] = keyTerm = ToTerm(term);
122 if (objectname != null)
125 objectname =
new NonTerminal(
"object_name", typeof(
ObjectNameNode));
126 objectname.Rule = MakePlusRule(objectname, Dot, Identifier);
131 if (datatype != null)
134 datatype =
new NonTerminal(
"datatype", typeof (
DataTypeNode));
135 var numberPrecision =
new NonTerminal(
"number_precision");
136 var characterType =
new NonTerminal(
"character_type");
137 var localeOpt =
new NonTerminal(
"locale_opt");
138 var encodingOp =
new NonTerminal(
"encoding_opt");
139 var booleanType =
new NonTerminal(
"boolean_type");
140 var integerType =
new NonTerminal(
"integer_type");
141 var decimalType =
new NonTerminal(
"decimal_type");
142 var floatType =
new NonTerminal(
"float_type");
143 var dateType =
new NonTerminal(
"date_type");
144 var intervalType =
new NonTerminal(
"interval_type");
145 var intervalFormatOpt =
new NonTerminal(
"interval_format_opt");
146 var datatypeSize =
new NonTerminal(
"datatype_size");
147 var longVarchar =
new NonTerminal(
"long_varchar");
148 var binaryType =
new NonTerminal(
"binary_type");
149 var longVarbinary =
new NonTerminal(
"long_varbinary");
150 var userType =
new NonTerminal(
"user_type");
151 var rowType =
new NonTerminal(
"row_type");
152 var userTypeMetaOpt =
new NonTerminal(
"user_type_meta_opt");
153 var userTypeMetaList =
new NonTerminal(
"user_type_meta_list");
154 var userTypeMeta =
new NonTerminal(
"user_type_meta", typeof(
DataTypeMetaNode));
156 datatype.Rule = characterType |
166 characterType.Rule = Key(
"CHAR") + datatypeSize + localeOpt + encodingOp |
167 Key(
"VARCHAR") + datatypeSize + localeOpt + encodingOp |
168 longVarchar + datatypeSize + localeOpt + encodingOp;
169 localeOpt.Rule = Empty | Key(
"LOCALE") + StringLiteral;
170 encodingOp.Rule = Empty | Key(
"ENCODING") + StringLiteral;
171 dateType.Rule = Key(
"DATE") | Key(
"TIME") | Key(
"TIMESTAMP");
172 booleanType.Rule = Key(
"BOOLEAN") | Key(
"BIT");
173 integerType.Rule = Key(
"INT") |
178 decimalType.Rule = Key(
"DECIMAL") + numberPrecision |
179 Key(
"NUMERIC") + numberPrecision |
180 Key(
"NUMBER") + numberPrecision;
181 floatType.Rule = Key(
"FLOAT") |
184 binaryType.Rule = Key(
"BINARY") + datatypeSize |
185 Key(
"VARBINARY") + datatypeSize |
187 longVarbinary + datatypeSize;
188 longVarchar.Rule = Key(
"LONG") + Key(
"VARCHAR");
189 longVarbinary.Rule = Key(
"LONG") + Key(
"VARBINARY");
190 rowType.Rule =
ObjectName() +
"%" + Key(
"ROWTYPE");
191 userType.Rule =
ObjectName() + userTypeMetaOpt;
192 userTypeMetaOpt.Rule = Empty |
"(" + userTypeMetaList +
")";
193 userTypeMetaList.Rule = MakeStarRule(userTypeMetaList, Comma, userTypeMeta);
194 userTypeMeta.Rule = Identifier +
"=" + StringLiteral;
195 intervalType.Rule = Key(
"INTERVAL") + intervalFormatOpt;
196 intervalFormatOpt.Rule = Key(
"YEAR") + Key(
"TO") + Key(
"MONTH") |
197 Key(
"DAY") + Key(
"TO") + Key(
"SECOND");
199 datatypeSize.Rule = Empty |
"(" + PositiveLiteral +
")";
201 numberPrecision.Rule = Empty |
202 "(" + PositiveLiteral +
")" |
203 "(" + PositiveLiteral +
"," + PositiveLiteral +
")";
209 var list =
new NonTerminal(
"sql_expression_list");
210 list.Rule = MakePlusRule(list, Comma, SqlExpression());
215 var selectIntoOpt =
new NonTerminal(
"select_into_opt");
216 var selectSet =
new NonTerminal(
"select_set");
217 var selectRestrictOpt =
new NonTerminal(
"select_restrict_opt");
218 var selectItem =
new NonTerminal(
"select_item", typeof(
SelectItemNode));
219 var selectAsOpt =
new NonTerminal(
"select_as_opt");
220 var selectSource =
new NonTerminal(
"select_source");
221 var selectItemList =
new NonTerminal(
"select_item_list");
222 var fromClauseOpt =
new NonTerminal(
"from_clause_opt");
223 var fromClause =
new NonTerminal(
"from_clause", typeof(
FromClauseNode));
224 var fromSource =
new NonTerminal(
"from_source");
227 var joinOpt =
new NonTerminal(
"join_opt");
228 var joinType =
new NonTerminal(
"join_type");
229 var join =
new NonTerminal(
"join", typeof (
JoinNode));
230 var onOpt =
new NonTerminal(
"on_opt");
231 var whereClauseOpt =
new NonTerminal(
"where_clause_opt");
232 var groupByOpt =
new NonTerminal(
"group_by_opt");
233 var groupBy =
new NonTerminal(
"group_by", typeof(
GroupByNode));
234 var havingClauseOpt =
new NonTerminal(
"having_clause_opt");
235 var queryCompositeOpt =
new NonTerminal(
"query_composite_opt");
238 var allOpt =
new NonTerminal(
"all_opt");
239 var asOpt =
new NonTerminal(
"as_opt");
241 expression.Rule = Key(
"SELECT") + selectRestrictOpt +
249 selectRestrictOpt.Rule = Empty | Key(
"ALL") | Key(
"DISTINCT");
250 selectIntoOpt.Rule = Empty | Key(
"INTO") +
ObjectName();
251 selectSet.Rule = selectItemList |
"*";
252 selectItemList.Rule = MakePlusRule(selectItemList, Comma, selectItem);
253 selectItem.Rule = selectSource + selectAsOpt;
254 selectAsOpt.Rule = Empty |
257 selectSource.Rule = SqlExpression() |
ObjectName();
258 fromClauseOpt.Rule = Empty | fromClause;
259 fromClause.Rule = Key(
"FROM") + fromSource + joinOpt;
260 fromSource.Rule = fromTableSource |
262 fromTableSource.Rule =
ObjectName() + selectAsOpt;
263 fromQuerySource.Rule =
"(" + expression +
")" + selectAsOpt;
265 joinOpt.Rule = Empty | join;
266 join.Rule = joinType + fromSource + onOpt;
267 onOpt.Rule = Empty | Key(
"ON") + SqlExpression() + joinOpt;
268 joinType.Rule = Key(
"INNER") + Key(
"JOIN")|
269 Key(
"OUTER") + Key(
"JOIN") |
270 Key(
"LEFT") + Key(
"JOIN") |
271 Key(
"LEFT") + Key(
"OUTER") + Key(
"JOIN") |
272 Key(
"RIGHT") + Key(
"JOIN") |
273 Key(
"RIGHT") + Key(
"OUTER") + Key(
"JOIN") |
275 whereClauseOpt.Rule = Empty | Key(
"WHERE") + SqlExpression();
276 groupByOpt.Rule = Empty | groupBy;
277 groupBy.Rule = Key(
"GROUP") + Key(
"BY") + SqlExpressionList() + havingClauseOpt;
278 havingClauseOpt.Rule = Empty | Key(
"HAVING") + SqlExpression();
279 queryCompositeOpt.Rule = Empty | queryComposite;
280 queryComposite.Rule = Key(
"UNION") + allOpt + expression |
281 Key(
"INTERSECT") + allOpt + expression |
282 Key(
"EXCEPT") + allOpt + expression;
283 allOpt.Rule = Empty | Key(
"ALL");
284 asOpt.Rule = Empty | As;
286 MarkTransient(selectSource);
292 if (sqlExpression != null)
293 return sqlExpression;
295 sqlExpression =
new NonTerminal(
"sql_expression");
302 var term =
new NonTerminal(
"term");
303 var sqlSimpleExpression =
new NonTerminal(
"sql_simple_expression");
304 var unaryOp =
new NonTerminal(
"unary_op");
305 var binaryOp =
new NonTerminal(
"binary_op");
306 var binaryOpSimple =
new NonTerminal(
"binary_op_simple");
307 var logicalOp =
new NonTerminal(
"logical_op");
308 var subqueryOp =
new NonTerminal(
"subquery_op");
309 var caseTestExpressionOpt =
new NonTerminal(
"case_test_expression_opt");
310 var caseWhenThenList =
new NonTerminal(
"case_when_then_list");
311 var caseWhenThen =
new NonTerminal(
"case_when_then", typeof(
CaseSwitchNode));
312 var caseElseOpt =
new NonTerminal(
"case_else_opt");
316 var functionCallArgsOpt =
new NonTerminal(
"function_call_args_opt");
317 var functionCallArgsList =
new NonTerminal(
"function_call_args_list");
318 var notOpt =
new NonTerminal(
"not_opt");
319 var grouped =
new NonTerminal(
"grouped");
320 var anyOp =
new NonTerminal(
"any_op");
321 var allOp =
new NonTerminal(
"all_op");
323 sqlExpression.Rule = sqlSimpleExpression |
324 sqlBetweenExpression |
326 SqlQueryExpression();
327 sqlConstantExpression.Rule = StringLiteral | NumberLiteral | Key(
"TRUE") | Key(
"FALSE") | Key(
"NULL");
328 sqlSimpleExpression.Rule = term | sqlBinaryExpression | sqlUnaryExpression;
329 term.Rule = sqlReferenceExpression |
331 sqlConstantExpression |
332 functionCallExpression |
335 grouped.Rule = ImplyPrecedenceHere(30) +
"(" + sqlExpression +
")";
336 sqlUnaryExpression.Rule = unaryOp + term;
337 unaryOp.Rule = Key(
"NOT") |
"+" |
"-" |
"~";
338 sqlBinaryExpression.Rule = sqlSimpleExpression + binaryOp + sqlSimpleExpression;
339 binaryOpSimple.Rule = ToTerm(
"+") |
"-" |
"*" |
"/" |
"%" |
">" |
"<" |
"=" |
"<>";
340 binaryOp.Rule = binaryOpSimple | allOp | anyOp | logicalOp | subqueryOp;
341 logicalOp.Rule = Key(
"AND") | Key(
"OR") | Key(
"IS") | Key(
"IS") + Key(
"NOT") +
"&" |
"|";
342 subqueryOp.Rule = Key(
"IN") | Key(
"NOT") + Key(
"IN");
343 anyOp.Rule = Key(
"ANY") + binaryOpSimple;
344 allOp.Rule = Key(
"ALL") + binaryOpSimple;
345 sqlBetweenExpression.Rule = sqlSimpleExpression + notOpt + Key(
"BETWEEN") + sqlSimpleExpression + Key(
"AND") +
347 sqlCaseExpression.Rule = Key(
"CASE") + caseTestExpressionOpt + caseWhenThenList + caseElseOpt + Key(
"END");
348 caseTestExpressionOpt.Rule = Empty | sqlExpression;
349 caseElseOpt.Rule = Empty | Key(
"ELSE") + sqlExpression;
350 caseWhenThenList.Rule = MakePlusRule(caseWhenThenList, caseWhenThen);
351 caseWhenThen.Rule = Key(
"WHEN") + sqlExpression + Key(
"THEN") + sqlExpression;
353 functionCallExpression.Rule =
ObjectName() + functionCallArgsOpt;
354 functionCallArgsOpt.Rule = Empty |
"(" + functionCallArgsList +
")";
355 functionCallArgsList.Rule = MakeStarRule(functionCallArgsList, Comma, sqlExpression);
357 sqlVarefExpression.Rule = Colon + Identifier;
359 notOpt.Rule = Empty | Key(
"NOT");
361 MarkTransient(sqlExpression, term, sqlSimpleExpression, grouped, functionCallArgsOpt);
363 binaryOp.SetFlag(TermFlags.InheritPrecedence);
364 binaryOpSimple.SetFlag(TermFlags.InheritPrecedence);
365 logicalOp.SetFlag(TermFlags.InheritPrecedence);
366 subqueryOp.SetFlag(TermFlags.InheritPrecedence);
367 unaryOp.SetFlag(TermFlags.InheritPrecedence);
369 return sqlExpression;
The node that represents a switch in a CASE expression
This is a simple identifier within a SQL grammar.
virtual void ReservedWords()
NonTerminal SqlExpression()
Represents a composed name for an object within the system.
NonTerminal SqlExpressionList()
NonTerminal sqlExpression
An expression that encapsulates a unary operator for a given operand.
An SQL BETWEEN expression node that evaluates to true if the Expression given is between MinValue (in...
Describes the name of an object within a database.
The node in an SQL query that defines the sources from which to retrieve the data queried...
A node in the grammar tree that defines a sub-query in a FROM clause.
Handles a numeric literal value, belonging to a wider group than integer numbers, spanning from real ...
Represents the node that is a database table as source of a query.
The root node of an expression used to select a set of items from a set of sources defined...
An expression node that references an object within the database context (such as a table...
A node containing a constant literal string passed within an SQL command.
References a variable within a SQL execution context.
A single item selected within a query node tree.
NonTerminal SqlQueryExpression()
A node describing the JOIN between two sources within a query.
A node that describes the GROUP BY clause in a SQL query.
An node that represents a constant value set within a context of an SQL command.
Describes the information of a data type as found in a SQL string.
Composes two queries to obtain a set that is the result of a given composition function.
Represents an expression that evaluates between two other expressions.
A node in a SQL command tree that is used to request a function.
Encapsulates a number that is any falling in the group of integers.
An SQL node describing an in-line CASE conditional expression.