1 /* $Id: query_parser_bison.y 526090 2017-01-31 15:50:30Z asztalos $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Anatoliy Kuznetsov, Mike DiCuccio
27 *
28 * File Description:
29 * Bison grammar description for simple query language.
30 *
31 */
32
33 %{
34
35 #define YYSTYPE CQueryParseTree::TNode*
36 #define YYPARSE_PARAM parm
37 #define YYLEX_PARAM parm
38 #define YYMAXDEPTH 100000
39
40 #define YYDEBUG 1
41 #define YYERROR_VERBOSE 1
42
43
44 /// Add child node(s) to the parent
45 /// @internal
46 ///
47 inline static
QTreeAddNode(void * parm,CQueryParseTree::TNode * rnode,CQueryParseTree::TNode * node1,CQueryParseTree::TNode * node2)48 void QTreeAddNode(void* parm,
49 CQueryParseTree::TNode* rnode,
50 CQueryParseTree::TNode* node1,
51 CQueryParseTree::TNode* node2)
52 {
53 if (node1)
54 rnode->AddNode(node1);
55 if (node2)
56 rnode->AddNode(node2);
57
58 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
59 env->AttachQueryTree(rnode);
60 env->ForgetPoolNodes(node1, node2);
61 }
62
63
64 /// Add node to a list if parser environment is in the list parsing context
65 /// @internal
66 ///
67 inline static
AddFunc_Arg(void * parm,CQueryParseTree::TNode * node)68 void AddFunc_Arg(void* parm,
69 CQueryParseTree::TNode* node)
70 {
71 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
72 CQueryParseTree::TNode* func_node = env->GetContext();
73
74 if (func_node) {
75 func_node->AddNode(node);
76 }
77 env->ForgetPoolNodes(node, 0);
78 }
79
80 inline static
AddIn_Arg(void * parm,CQueryParseTree::TNode * node)81 void AddIn_Arg(void* parm,
82 CQueryParseTree::TNode* node)
83 {
84 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
85 CQueryParseTree::TNode* in_node = env->GetIN_Context();
86
87 if (in_node) {
88 in_node->AddNode(node);
89 }
90 env->ForgetPoolNodes(node, 0);
91 }
92
93 %}
94
95 %pure_parser /* Reentrant parser */
96
97 %token IDENT
98 %token STRING
99 %token NUM_INT
100 %token SELECT
101 %token FROM
102 %token WHERE
103 %token FUNCTION
104
105
106 %left AND
107 %left NOT
108 %left OR
109 %left SUB
110 %left XOR
111 %left RANGE
112 %left EQ
113 %left NOTEQ
114 %left GT
115 %left GE
116 %left LT
117 %left LE
118 %left BETWEEN
119 %left NOT_BETWEEN
120 %left LIKE
121 %left NOT_LIKE
122 %left IN
123 %left NOT_IN
124
125 %%
126
127 input :
128 exp
129 | select_clause
130 ;
131
132
133
134 select_clause :
135 /* select clause */
136 SELECT obj_list FROM obj_list opt_where
137 {
138 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
139
140 /* create a pseudo node to isolate select list in a dedicated subtree */
141 //CQueryParseTree::TNode* qnode = 0;
142 //qnode = env->QTree().CreateNode(CQueryParseNode::eList, 0, 0, "LIST");
143 //qnode->MoveSubnodes($2);
144 CQueryParseTree::TNode* qnode = env->GetContext();
145 if (qnode) {
146 qnode->InsertNode(qnode->SubNodeBegin(), $2);
147 }
148
149 //$1->InsertNode($1->SubNodeBegin(),qnode);
150
151 $1->AddNode($3);
152 $3->MoveSubnodes($4);
153 $3->InsertNode($3->SubNodeBegin(), $4);
154 if ($5) {
155 $1->AddNode($5);
156 }
157
158 env->ForgetPoolNode($1);
159 env->ForgetPoolNode($2);
160 env->ForgetPoolNode($3);
161 env->ForgetPoolNode($4);
162 env->ForgetPoolNode($5);
163
164 env->SetSELECT_Context(0);
165 env->SetContext(0);
166 env->SetFROM_Context(0);
167
168 $$ = $1;
169 env->AttachQueryTree($$);
170
171 }
172 ;
173
174 opt_where :
175 /* empty */
176 {
177 $$=0;
178 }
179 |
180 WHERE exp
181 {
182 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
183 $1->AddNode($2);
184 env->ForgetPoolNode($2);
185 $$ = $1;
186 }
187 ;
188
189 functional:
190 FUNCTION '(' exp_list ')'
191 {
192 $$ = $1;
193 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
194 env->AttachQueryTree($$);
195 $$->InsertNode($$->SubNodeBegin(), $3);
196 env->SetContext(0);
197 env->ForgetPoolNodes($1, $3);
198 }
199 | FUNCTION '(' ')'
200 {
201 $$ = $1;
202 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
203 env->AttachQueryTree($$);
204 env->SetContext(0);
205 env->ForgetPoolNode($1);
206 }
207 ;
208
209 obj_list:
210 scalar_value
211 {
212 $$ = $1;
213 }
214 | obj_list ',' scalar_value
215 {
216 $$ = $1;
217 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
218 AddFunc_Arg(parm, $3);
219 //$$->AddNode($3);
220 env->ForgetPoolNode($3);
221 }
222 ;
223
224 scalar_value :
225 /* integer constant */
226 NUM_INT
227 {
228 $$ = $1;
229 }
230 /* text */
231 | STRING
232 {
233 $$ = $1;
234 }
235 /* pure string identifier */
236 | IDENT
237 {
238 $$ = $1;
239 }
240 | functional
241 {
242 $$ = $1;
243 }
244 ;
245
246 scalar_list:
247 scalar_value
248 {
249 $$ = $1;
250 }
251 | scalar_list ',' scalar_value
252 {
253 $$ = $1;
254 AddIn_Arg(parm, $3);
255 }
256 ;
257
258 exp_list:
259 exp
260 {
261 $$ = $1;
262 }
263 | exp_list ',' exp
264 {
265 $$ = $1;
266 AddFunc_Arg(parm, $3);
267 }
268 ;
269
270 /* IN sub-expression */
271 in_sub_expr:
272 scalar_list
273 |
274 select_clause
275 ;
276
277 exp :
278 scalar_value
279 {
280 $$ = $1;
281 }
282 /* Function call */
283 | functional
284 {
285 $$ = $1;
286 }
287 /* Field search */
288 | STRING IDENT
289 {
290 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
291 $$ = env->QTree().CreateNode(CQueryParseNode::eFieldSearch, $1, $2);
292 env->AttachQueryTree($$);
293 env->ForgetPoolNodes($1, $2);
294 }
295 /* concatenated expressions are implicit ANDs */
296 | exp exp
297 {
298 yyerrok;
299 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
300 $$ = env->QTree().CreateNode(CQueryParseNode::eAnd, $1, $2);
301 $$->GetValue().SetExplicit(false);
302 env->AttachQueryTree($$);
303 env->ForgetPoolNodes($1, $2);
304 }
305
306 /* parenthetical balanced expressions */
307 | '(' exp ')'
308 {
309 $$ = $2;
310 }
311
312 /*
313 * LOGICAL OPS
314 */
315
316 /* AND */
317 | exp AND exp
318 {
319 QTreeAddNode(parm, $$ = $2, $1, $3);
320 }
321 /* MINUS */
322 | exp SUB exp
323 {
324 QTreeAddNode(parm, $$ = $2, $1, $3);
325 }
326 /* OR */
327 | exp OR exp
328 {
329 QTreeAddNode(parm, $$ = $2, $1, $3);
330 }
331 /* XOR */
332 | exp XOR exp
333 {
334 QTreeAddNode(parm, $$ = $2, $1, $3);
335 }
336 /* BETWEEN */
337 | scalar_value BETWEEN scalar_value AND scalar_value
338 {
339 $$ = $2;
340 $$->AddNode($1);
341 $$->AddNode($3);
342 $$->AddNode($5);
343
344 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
345 env->AttachQueryTree($$);
346 env->ForgetPoolNodes($1, $3);
347 env->ForgetPoolNodes($1, $5);
348 }
349 /* NOT BETWEEN */
350 | scalar_value NOT_BETWEEN scalar_value AND scalar_value
351 {
352 $$ = $2;
353 $$->AddNode($1);
354 $$->AddNode($3);
355 $$->AddNode($5);
356
357 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
358 env->AttachQueryTree($$);
359 env->ForgetPoolNodes($1, $3);
360 env->ForgetPoolNodes($1, $5);
361 }
362
363 /* RANGE */
364 | exp RANGE exp
365 {
366 QTreeAddNode(parm, $$ = $2, $1, $3);
367 }
368 /* LIKE */
369 | scalar_value LIKE scalar_value
370 {
371 QTreeAddNode(parm, $$ = $2, $1, $3);
372 }
373 /* NOT LIKE */
374 | scalar_value NOT_LIKE scalar_value
375 {
376 QTreeAddNode(parm, $$ = $2, $1, $3);
377 }
378 /* IN */
379 | scalar_value IN '(' in_sub_expr ')'
380 {
381 $$ = $2;
382 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
383 env->AttachQueryTree($$);
384 env->ForgetPoolNodes($1, $4);
385 $$->InsertNode($$->SubNodeBegin(), $4);
386 $$->InsertNode($$->SubNodeBegin(), $1);
387 env->SetIN_Context(0);
388 }
389 /* NOT IN */
390 | scalar_value NOT_IN '(' in_sub_expr ')'
391 {
392 $$ = $2;
393 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
394 env->AttachQueryTree($$);
395 env->ForgetPoolNodes($1, $4);
396 $$->InsertNode($$->SubNodeBegin(), $4);
397 $$->InsertNode($$->SubNodeBegin(), $1);
398 env->SetIN_Context(0);
399 }
400 /* == */
401 | exp EQ exp
402 {
403 QTreeAddNode(parm, $$ = $2, $1, $3);
404 }
405 /* != */
406 | exp NOTEQ exp
407 {
408 QTreeAddNode(parm, $$ = $2, $1, $3);
409 }
410 | exp GT exp
411 {
412 QTreeAddNode(parm, $$ = $2, $1, $3);
413 }
414 | exp GE exp
415 {
416 QTreeAddNode(parm, $$ = $2, $1, $3);
417 }
418 | exp LT exp
419 {
420 QTreeAddNode(parm, $$ = $2, $1, $3);
421 }
422 | exp LE exp
423 {
424 QTreeAddNode(parm, $$ = $2, $1, $3);
425 }
426 /* NOT
427 | exp NOT exp
428 {
429 QTreeAddNode(parm, $$ = $2, $1, $3);
430 }
431 */
432 /* unary NOT */
433 | NOT exp
434 {
435 QTreeAddNode(parm, $$ = $1, $2, 0);
436 }
437
438 /*
439 * error cases
440 */
441
442 | error STRING
443 {
444 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
445 if (env->GetParserTolerance() == CQueryParseTree::eSyntaxCheck) {
446 NCBI_THROW(CQueryParseException, eParserError,
447 "Syntax error.");
448 }
449 QTreeAddNode(parm, $$ = $2, 0, 0);
450 }
451 | error IDENT
452 {
453 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
454 if (env->GetParserTolerance() == CQueryParseTree::eSyntaxCheck) {
455 NCBI_THROW(CQueryParseException, eParserError,
456 "Syntax error.");
457 }
458 QTreeAddNode(parm, $$ = $2, 0, 0);
459 }
460 | error NUM_INT
461 {
462 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
463 if (env->GetParserTolerance() == CQueryParseTree::eSyntaxCheck) {
464 NCBI_THROW(CQueryParseException, eParserError,
465 "Syntax error.");
466 }
467 QTreeAddNode(parm, $$ = $2, 0, 0);
468 }
469 | exp error
470 {
471 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
472 if (env->GetParserTolerance() == CQueryParseTree::eSyntaxCheck) {
473 NCBI_THROW(CQueryParseException, eParserError,
474 "Syntax error.");
475 }
476 QTreeAddNode(parm, $$ = $1, 0, 0);
477 }
478
479 /* unbalanced parenthesis at the end-of-input */
480
481 | '(' exp error
482 {
483 yyerrok;
484 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
485 if (env->GetParserTolerance() == CQueryParseTree::eSyntaxCheck) {
486 NCBI_THROW(CQueryParseException, eParserError,
487 "Syntax error. Unbalanced parenthesis");
488 }
489 QTreeAddNode(parm, $$ = $2, 0, 0);
490 }
491 | exp OR error
492 {
493 yyerrok;
494 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
495 if (env->GetParserTolerance() == CQueryParseTree::eSyntaxCheck) {
496 NCBI_THROW(CQueryParseException, eParserError,
497 "Syntax error.");
498 }
499 QTreeAddNode(parm, $$ = $1, 0, 0);
500 }
501 | exp XOR error
502 {
503 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
504 if (env->GetParserTolerance() == CQueryParseTree::eSyntaxCheck) {
505 NCBI_THROW(CQueryParseException, eParserError,
506 "Syntax error.");
507 }
508 yyerrok;
509 QTreeAddNode(parm, $$ = $1, 0, 0);
510 }
511 | exp NOT error
512 {
513 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
514 if (env->GetParserTolerance() == CQueryParseTree::eSyntaxCheck) {
515 NCBI_THROW(CQueryParseException, eParserError,
516 "Syntax error.");
517 }
518 yyerrok;
519 QTreeAddNode(parm, $$ = $1, 0, 0);
520 }
521 | exp AND error
522 {
523 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
524 if (env->GetParserTolerance() == CQueryParseTree::eSyntaxCheck) {
525 NCBI_THROW(CQueryParseException, eParserError,
526 "Syntax error.");
527 }
528 yyerrok;
529 QTreeAddNode(parm, $$ = $1, 0, 0);
530 }
531 | exp SUB error
532 {
533 CQueryParserEnv* env = reinterpret_cast<CQueryParserEnv*>(parm);
534 if (env->GetParserTolerance() == CQueryParseTree::eSyntaxCheck) {
535 NCBI_THROW(CQueryParseException, eParserError,
536 "Syntax error.");
537 }
538 yyerrok;
539 QTreeAddNode(parm, $$ = $1, 0, 0);
540 }
541
542 /**
543 | AND exp error
544 {
545 $$ = CQueryParseTree::CreateOpNode(CQueryParseNode::eAnd, 0, $2);
546 }
547 | OR exp error
548 {
549 $$ = CQueryParseTree::CreateOpNode(CQueryParseNode::eOr, 0, $2);
550 }
551 **/
552 ;
553
554 %%
555
556