3 * This file is part of the GROMACS molecular simulation package.
5 * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016, by the GROMACS development team, led by
6 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7 * and including many others, as listed in the AUTHORS file in the
8 * top-level source directory and at http://www.gromacs.org.
10 * GROMACS is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public License
12 * as published by the Free Software Foundation; either version 2.1
13 * of the License, or (at your option) any later version.
15 * GROMACS is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with GROMACS; if not, see
22 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 * If you want to redistribute modifications to GROMACS, please
26 * consider that scientific software is very special. Version
27 * control is crucial - bugs must be traceable. We will be happy to
28 * consider code for inclusion in the official distribution, but
29 * derived work must not be called official GROMACS. Details are found
30 * in the README & COPYING files - if they are missing, get the
31 * official version at http://www.gromacs.org.
33 * To help us fund GROMACS development, we humbly ask that you cite
34 * the research papers on the package. Check out http://www.gromacs.org.
38 * \brief Grammar description and parser for the selection language.
40 * \author Teemu Murtola <teemu.murtola@gmail.com>
41 * \ingroup module_selection
44 /*! \internal \file parser.cpp
45 * \brief Generated (from parser.y by Bison) parser for the selection language.
47 * \ingroup module_selection
49 /*! \internal \file parser.h
50 * \brief Generated (from parser.y by Bison) parser include file.
52 * \ingroup module_selection
57 #include "gromacs/utility/scoped_cptr.h"
59 #include "parser_internal.h"
61 using gmx::scoped_guard_sfree;
62 using gmx::SelectionParserValue;
63 using gmx::SelectionParserValueList;
64 using gmx::SelectionParserValueListPointer;
65 using gmx::SelectionParserParameter;
66 using gmx::SelectionParserParameterList;
67 using gmx::SelectionParserParameterListPointer;
68 using gmx::SelectionTreeElement;
69 using gmx::SelectionTreeElementPointer;
72 #pragma warning(disable: 4065)
77 #include "parsetree.h"
80 #define YYLTYPE ::gmx::SelectionLocation
87 struct gmx_ana_selmethod_t *meth;
89 gmx::SelectionStringMatchType smt;
91 gmx::SelectionTreeElementPointer *sel;
92 gmx::SelectionParserValue *val;
93 gmx::SelectionParserValueListPointer *vlist;
94 gmx::SelectionParserParameter *param;
95 gmx::SelectionParserParameterListPointer *plist;
98 /* Invalid token to report lexer errors */
101 /* Simple input tokens */
105 %token <str> IDENTIFIER
108 /* Simple keyword tokens */
112 /* Variable tokens */
113 %token <sel> VARIABLE_NUMERIC
114 %token <sel> VARIABLE_GROUP
115 %token <sel> VARIABLE_POS
117 /* Selection method tokens */
118 %token <meth> KEYWORD_NUMERIC
119 %token <meth> KEYWORD_STR
120 %token <str> KEYWORD_POS
121 %token <meth> KEYWORD_GROUP
122 %token <meth> METHOD_NUMERIC
123 %token <meth> METHOD_GROUP
124 %token <meth> METHOD_POS
125 %token <meth> MODIFIER
126 /* Empty token that should precede any non-position KEYWORD/METHOD token that
127 * is not preceded by KEYWORD_POS. This is used to work around reduce/reduce
128 * conflicts that appear when a lookahead token would require a reduction of
129 * a rule with empty RHS before shifting, and there is an alternative reduction
130 * available. Replacing the empty RHS with a dummy token makes these conflicts
131 * only shift/reduce conflicts. Another alternative would be to remove the
132 * pos_mod non-terminal completely and split each rule that uses it into two,
133 * but this would require duplicating six rules in the grammar. */
140 /* Comparison operators have lower precedence than parameter reduction
141 * to make it possible to parse, e.g., "mindist from resnr 1 < 2" without
143 %nonassoc <str> CMP_OP
144 /* A dummy token that determines the precedence of parameter reduction */
145 %nonassoc PARAM_REDUCT
146 /* Boolean operator tokens */
150 /* Arithmetic operator tokens */
153 %right UNARY_NEG /* Dummy token for unary negation precedence */
155 %nonassoc NUM_REDUCT /* Dummy token for numerical keyword reduction precedence */
157 /* Simple non-terminals */
158 %type <i> integer_number
159 %type <r> real_number number
162 %type <smt> str_match_type
164 /* Expression non-terminals */
165 %type <sel> commands command cmd_plain
166 %type <sel> selection
172 /* Parameter/value non-terminals */
173 %type <plist> method_params method_param_list
174 %type <param> method_param
175 %type <vlist> value_list value_list_contents basic_value_list basic_value_list_contents
176 %type <val> value_item value_item_range basic_value_item
178 %destructor { free($$); } STR IDENTIFIER KEYWORD_POS CMP_OP string
179 %destructor { if($$) free($$); } PARAM pos_mod
180 %destructor { delete $$; } commands command cmd_plain selection
181 %destructor { delete $$; } sel_expr num_expr str_expr pos_expr
182 %destructor { delete $$; } method_params method_param_list method_param
183 %destructor { delete $$; } value_list value_list_contents basic_value_list basic_value_list_contents
184 %destructor { delete $$; } value_item value_item_range basic_value_item
189 %define api.push-pull push
192 %name-prefix "_gmx_sel_yy"
193 %parse-param { void *scanner }
197 /* The start rule: allow one or more commands */
198 commands: /* empty */
207 set($$, _gmx_sel_append_selection(get($2), get($1), scanner));
208 if (_gmx_sel_parser_should_finish(scanner)) {
216 /* A command is formed from an actual command and a separator */
217 command: cmd_plain CMD_SEP { $$ = $1; }
221 _gmx_sel_lexer_clear_method_stack(scanner);
222 if (_gmx_selparser_handle_error(scanner))
230 _gmx_sel_lexer_clear_pselstr(scanner);
236 /* Commands can be selections or variable assignments */
237 cmd_plain: /* empty */
246 SelectionTreeElementPointer s
247 = _gmx_sel_init_group_by_id($1, scanner);
248 SelectionTreeElementPointer p
249 = _gmx_sel_init_position(s, NULL, scanner);
251 set($$, _gmx_sel_init_selection(NULL, p, scanner));
257 scoped_guard_sfree nameGuard($1);
258 SelectionTreeElementPointer s
259 = _gmx_sel_init_group_by_name($1, scanner);
260 SelectionTreeElementPointer p
261 = _gmx_sel_init_position(s, NULL, scanner);
263 set($$, _gmx_sel_init_selection(NULL, p, scanner));
269 set($$, _gmx_sel_init_selection(NULL, get($1), scanner));
275 scoped_guard_sfree nameGuard($1);
276 set($$, _gmx_sel_init_selection($1, get($2), scanner));
279 | IDENTIFIER '=' sel_expr
282 scoped_guard_sfree nameGuard($1);
283 set($$, _gmx_sel_assign_variable($1, get($3), scanner));
286 | IDENTIFIER '=' num_expr
289 scoped_guard_sfree nameGuard($1);
290 set($$, _gmx_sel_assign_variable($1, get($3), scanner));
293 | IDENTIFIER '=' pos_expr
296 scoped_guard_sfree nameGuard($1);
297 set($$, _gmx_sel_assign_variable($1, get($3), scanner));
302 /* Selection is made of an expression and zero or more modifiers */
303 selection: pos_expr { $$ = $1; }
307 set($$, _gmx_sel_init_position(get($1), NULL, scanner));
311 | '(' selection ')' { $$ = $2; }
312 | selection MODIFIER method_params
315 set($$, _gmx_sel_init_modifier($2, get($3), get($1), scanner));
321 /********************************************************************
322 * BASIC NON-TERMINAL SYMBOLS
323 ********************************************************************/
327 | '-' TOK_INT { $$ = -$2; }
331 TOK_REAL { $$ = $1; }
332 | '-' TOK_REAL { $$ = -$2; }
335 number: integer_number { $$ = $1; }
336 | real_number { $$ = $1; }
339 string: STR { $$ = $1; }
340 | IDENTIFIER { $$ = $1; }
343 /********************************************************************
344 * ATOM SELECTION EXPRESSIONS
345 ********************************************************************/
347 /* Boolean expressions and grouping */
348 sel_expr: NOT sel_expr
351 SelectionTreeElementPointer arg(get($2));
352 SelectionTreeElementPointer sel(
353 new SelectionTreeElement(SEL_BOOLEAN, @$));
354 sel->u.boolt = BOOL_NOT;
359 | sel_expr AND sel_expr
362 SelectionTreeElementPointer arg1(get($1)), arg2(get($3));
363 SelectionTreeElementPointer sel(
364 new SelectionTreeElement(SEL_BOOLEAN, @$));
365 sel->u.boolt = BOOL_AND;
366 sel->child = arg1; sel->child->next = arg2;
370 | sel_expr OR sel_expr
373 SelectionTreeElementPointer arg1(get($1)), arg2(get($3));
374 SelectionTreeElementPointer sel(
375 new SelectionTreeElement(SEL_BOOLEAN, @$));
376 sel->u.boolt = BOOL_OR;
377 sel->child = arg1; sel->child->next = arg2;
381 | '(' sel_expr ')' { $$ = $2; }
384 /* Numeric comparisons */
385 sel_expr: num_expr CMP_OP num_expr
388 scoped_guard_sfree opGuard($2);
389 set($$, _gmx_sel_init_comparison(get($1), get($3), $2, scanner));
395 /* External groups */
396 sel_expr: GROUP string
399 scoped_guard_sfree nameGuard($2);
400 set($$, _gmx_sel_init_group_by_name($2, scanner));
406 set($$, _gmx_sel_init_group_by_id($2, scanner));
411 /* Position modifiers for selection methods */
412 pos_mod: EMPTY_POSMOD { $$ = NULL; }
413 | KEYWORD_POS { $$ = $1; }
416 /* Matching mode forcing for keyword matching */
418 '~' { $$ = gmx::eStringMatchType_RegularExpression; }
419 | '?' { $$ = gmx::eStringMatchType_Wildcard; }
420 | '=' { $$ = gmx::eStringMatchType_Exact; }
423 /* Keyword selections */
424 sel_expr: pos_mod KEYWORD_GROUP
427 scoped_guard_sfree posmodGuard($1);
428 set($$, _gmx_sel_init_keyword($2, SelectionParserValueListPointer(), $1, scanner));
432 | pos_mod KEYWORD_STR basic_value_list
435 scoped_guard_sfree posmodGuard($1);
436 set($$, _gmx_sel_init_keyword_strmatch($2, gmx::eStringMatchType_Auto, get($3), $1, scanner));
440 | pos_mod KEYWORD_STR str_match_type basic_value_list
443 scoped_guard_sfree posmodGuard($1);
444 set($$, _gmx_sel_init_keyword_strmatch($2, $3, get($4), $1, scanner));
448 | pos_mod KEYWORD_NUMERIC basic_value_list
451 scoped_guard_sfree posmodGuard($1);
452 set($$, _gmx_sel_init_keyword($2, get($3), $1, scanner));
458 /* Custom selection methods */
459 sel_expr: pos_mod METHOD_GROUP method_params
462 scoped_guard_sfree posmodGuard($1);
463 set($$, _gmx_sel_init_method($2, get($3), $1, scanner));
469 /********************************************************************
470 * NUMERICAL EXPRESSIONS
471 ********************************************************************/
473 /* Basic numerical values */
477 SelectionTreeElementPointer sel(
478 new SelectionTreeElement(SEL_CONST, @$));
479 _gmx_selelem_set_vtype(sel, INT_VALUE);
480 _gmx_selvalue_reserve(&sel->v, 1);
488 SelectionTreeElementPointer sel(
489 new SelectionTreeElement(SEL_CONST, @$));
490 _gmx_selelem_set_vtype(sel, REAL_VALUE);
491 _gmx_selvalue_reserve(&sel->v, 1);
498 /* Numeric selection methods */
499 num_expr: pos_mod KEYWORD_NUMERIC %prec NUM_REDUCT
502 scoped_guard_sfree posmodGuard($1);
503 set($$, _gmx_sel_init_keyword($2, SelectionParserValueListPointer(), $1, scanner));
507 | pos_mod KEYWORD_NUMERIC OF pos_expr
510 scoped_guard_sfree posmodGuard($1);
511 set($$, _gmx_sel_init_keyword_of($2, get($4), $1, scanner));
515 | pos_mod METHOD_NUMERIC method_params
518 scoped_guard_sfree posmodGuard($1);
519 set($$, _gmx_sel_init_method($2, get($3), $1, scanner));
525 /* Arithmetic evaluation and grouping */
526 num_expr: num_expr '+' num_expr
529 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '+', scanner));
532 | num_expr '-' num_expr
535 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '-', scanner));
538 | num_expr '*' num_expr
541 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '*', scanner));
544 | num_expr '/' num_expr
547 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '/', scanner));
550 | '-' num_expr %prec UNARY_NEG
553 set($$, _gmx_sel_init_arithmetic(get($2), SelectionTreeElementPointer(), '-', scanner));
556 | num_expr '^' num_expr
559 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '^', scanner));
562 | '(' num_expr ')' { $$ = $2; }
565 /********************************************************************
567 ********************************************************************/
572 SelectionTreeElementPointer sel(
573 new SelectionTreeElement(SEL_CONST, @$));
574 _gmx_selelem_set_vtype(sel, STR_VALUE);
575 _gmx_selvalue_reserve(&sel->v, 1);
580 | pos_mod KEYWORD_STR
583 scoped_guard_sfree posmodGuard($1);
584 set($$, _gmx_sel_init_keyword($2, SelectionParserValueListPointer(), $1, scanner));
590 /********************************************************************
591 * POSITION EXPRESSIONS
592 ********************************************************************/
594 /* Constant position expressions */
595 pos_expr: '[' number ',' number ',' number ']'
598 set($$, _gmx_sel_init_const_position($2, $4, $6, scanner));
603 /* Grouping of position expressions */
604 pos_expr: '(' pos_expr ')' { $$ = $2; }
607 /* Expressions with a position value */
608 pos_expr: METHOD_POS method_params
611 set($$, _gmx_sel_init_method($1, get($2), NULL, scanner));
617 /* Evaluation of positions using a keyword */
618 pos_expr: KEYWORD_POS OF sel_expr %prec PARAM_REDUCT
621 scoped_guard_sfree keywordGuard($1);
622 set($$, _gmx_sel_init_position(get($3), $1, scanner));
628 /********************************************************************
630 ********************************************************************/
632 sel_expr: VARIABLE_GROUP
635 set($$, _gmx_sel_init_variable_ref(get($1), scanner));
640 num_expr: VARIABLE_NUMERIC
643 set($$, _gmx_sel_init_variable_ref(get($1), scanner));
648 pos_expr: VARIABLE_POS
651 set($$, _gmx_sel_init_variable_ref(get($1), scanner));
656 /********************************************************************
658 ********************************************************************/
663 | method_param_list END_OF_METHOD
671 set($$, SelectionParserParameter::createList());
674 | method_param_list method_param
677 SelectionParserParameterListPointer list(get($1));
678 list->push_back(get($2));
679 set($$, std::move(list));
688 scoped_guard_sfree nameGuard($1);
689 set($$, SelectionParserParameter::create($1, get($2), @$));
694 value_list: value_list_contents { $$ = $1; }
695 | '{' value_list_contents '}' { $$ = $2; }
702 set($$, SelectionParserValue::createList());
705 | value_list_contents value_item
708 SelectionParserValueListPointer list(get($1));
709 list->push_back(get($2));
710 set($$, std::move(list));
713 | value_list_contents ',' value_item
716 SelectionParserValueListPointer list(get($1));
717 list->push_back(get($3));
718 set($$, std::move(list));
724 basic_value_list_contents { $$ = $1; }
725 | '{' basic_value_list_contents '}' { $$ = $2; }
728 basic_value_list_contents:
732 set($$, SelectionParserValue::createList(get($1)));
735 | basic_value_list_contents basic_value_item
738 SelectionParserValueListPointer list(get($1));
739 list->push_back(get($2));
740 set($$, std::move(list));
743 | basic_value_list_contents ',' basic_value_item
746 SelectionParserValueListPointer list(get($1));
747 list->push_back(get($3));
748 set($$, std::move(list));
753 value_item: sel_expr %prec PARAM_REDUCT
756 set($$, SelectionParserValue::createExpr(get($1)));
759 | pos_expr %prec PARAM_REDUCT
762 set($$, SelectionParserValue::createExpr(get($1)));
765 | num_expr %prec PARAM_REDUCT
768 set($$, SelectionParserValue::createExpr(get($1)));
771 | str_expr %prec PARAM_REDUCT
774 set($$, SelectionParserValue::createExpr(get($1)));
777 | value_item_range { $$ = $1; }
781 integer_number %prec PARAM_REDUCT
784 set($$, SelectionParserValue::createInteger($1, @$));
787 | real_number %prec PARAM_REDUCT
790 set($$, SelectionParserValue::createReal($1, @$));
793 | string %prec PARAM_REDUCT
796 scoped_guard_sfree stringGuard($1);
797 set($$, SelectionParserValue::createString($1, @$));
800 | value_item_range { $$ = $1; }
804 integer_number TO integer_number
807 set($$, SelectionParserValue::createIntegerRange($1, $3, @$));
810 | integer_number TO real_number
813 set($$, SelectionParserValue::createRealRange($1, $3, @$));
816 | real_number TO number
819 set($$, SelectionParserValue::createRealRange($1, $3, @$));