3 * This file is part of the GROMACS molecular simulation package.
5 * Copyright (c) 2009,2010,2011,2012, by the GROMACS development team, led by
6 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
7 * others, as listed in the AUTHORS file in the top-level source
8 * 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
54 #include "gromacs/legacyheaders/smalloc.h"
56 #include "parser_internal.h"
58 using gmx::scoped_ptr_sfree;
59 using gmx::SelectionParserValue;
60 using gmx::SelectionParserValueList;
61 using gmx::SelectionParserValueListPointer;
62 using gmx::SelectionParserParameter;
63 using gmx::SelectionParserParameterList;
64 using gmx::SelectionParserParameterListPointer;
65 using gmx::SelectionTreeElement;
66 using gmx::SelectionTreeElementPointer;
69 #pragma warning(disable: 4065)
74 #include "parsetree.h"
82 struct gmx_ana_selmethod_t *meth;
84 gmx::SelectionStringMatchType smt;
86 gmx::SelectionTreeElementPointer *sel;
87 gmx::SelectionParserValue *val;
88 gmx::SelectionParserValueListPointer *vlist;
89 gmx::SelectionParserParameter *param;
90 gmx::SelectionParserParameterListPointer *plist;
93 /* Invalid token to report lexer errors */
96 /* Tokens for help requests */
98 %token <str> HELP_TOPIC
100 /* Simple input tokens */
104 %token <str> IDENTIFIER
107 /* Simple keyword tokens */
111 /* Variable tokens */
112 %token <sel> VARIABLE_NUMERIC
113 %token <sel> VARIABLE_GROUP
114 %token <sel> VARIABLE_POS
116 /* Selection method tokens */
117 %token <meth> KEYWORD_NUMERIC
118 %token <meth> KEYWORD_STR
119 %token <str> KEYWORD_POS
120 %token <meth> KEYWORD_GROUP
121 %token <meth> METHOD_NUMERIC
122 %token <meth> METHOD_GROUP
123 %token <meth> METHOD_POS
124 %token <meth> MODIFIER
125 /* Empty token that should precede any non-position KEYWORD/METHOD token that
126 * is not preceded by KEYWORD_POS. This is used to work around reduce/reduce
127 * conflicts that appear when a lookahead token would require a reduction of
128 * a rule with empty RHS before shifting, and there is an alternative reduction
129 * available. Replacing the empty RHS with a dummy token makes these conflicts
130 * only shift/reduce conflicts. Another alternative would be to remove the
131 * pos_mod non-terminal completely and split each rule that uses it into two,
132 * but this would require duplicating six rules in the grammar. */
139 /* Comparison operators have lower precedence than parameter reduction
140 * to make it possible to parse, e.g., "mindist from resnr 1 < 2" without
142 %nonassoc <str> CMP_OP
143 /* A dummy token that determines the precedence of parameter reduction */
144 %nonassoc PARAM_REDUCT
145 /* Boolean operator tokens */
149 /* Arithmetic operator tokens */
152 %right UNARY_NEG /* Dummy token for unary negation precedence */
154 %nonassoc NUM_REDUCT /* Dummy token for numerical keyword reduction precedence */
156 /* Simple non-terminals */
157 %type <i> integer_number
158 %type <r> real_number number
161 %type <smt> str_match_type
163 /* Expression non-terminals */
164 %type <sel> commands command cmd_plain
165 %type <sel> selection
171 /* Parameter/value non-terminals */
172 %type <plist> method_params method_param_list
173 %type <param> method_param
174 %type <vlist> value_list value_list_contents basic_value_list basic_value_list_contents
175 %type <val> value_item value_item_range basic_value_item
176 %type <vlist> help_topic
178 %destructor { free($$); } HELP_TOPIC 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
185 %destructor { delete $$; } help_topic
190 %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))
214 /* A command is formed from an actual command and a separator */
215 command: cmd_plain CMD_SEP { $$ = $1; }
219 _gmx_selparser_error(scanner, "invalid selection '%s'",
220 _gmx_sel_lexer_pselstr(scanner));
221 _gmx_sel_lexer_clear_method_stack(scanner);
222 if (_gmx_sel_is_lexer_interactive(scanner))
224 _gmx_sel_lexer_clear_pselstr(scanner);
236 /* Commands can be selections or variable assignments */
237 cmd_plain: /* empty */
240 _gmx_sel_handle_empty_cmd(scanner);
253 SelectionTreeElementPointer s
254 = _gmx_sel_init_group_by_id($1, scanner);
255 SelectionTreeElementPointer p
256 = _gmx_sel_init_position(s, NULL, scanner);
258 set($$, _gmx_sel_init_selection(NULL, p, scanner));
264 scoped_ptr_sfree nameGuard($1);
265 SelectionTreeElementPointer s
266 = _gmx_sel_init_group_by_name($1, scanner);
267 SelectionTreeElementPointer p
268 = _gmx_sel_init_position(s, NULL, scanner);
270 set($$, _gmx_sel_init_selection(NULL, p, scanner));
276 set($$, _gmx_sel_init_selection(NULL, get($1), scanner));
282 scoped_ptr_sfree nameGuard($1);
283 set($$, _gmx_sel_init_selection($1, get($2), scanner));
286 | IDENTIFIER '=' sel_expr
289 scoped_ptr_sfree nameGuard($1);
290 set($$, _gmx_sel_assign_variable($1, get($3), scanner));
293 | IDENTIFIER '=' num_expr
296 scoped_ptr_sfree nameGuard($1);
297 set($$, _gmx_sel_assign_variable($1, get($3), scanner));
300 | IDENTIFIER '=' pos_expr
303 scoped_ptr_sfree nameGuard($1);
304 set($$, _gmx_sel_assign_variable($1, get($3), scanner));
314 _gmx_sel_handle_help_cmd(get($2), scanner);
319 help_topic: /* empty */
322 set($$, SelectionParserValue::createList());
325 | help_topic HELP_TOPIC
328 SelectionParserValueListPointer list(get($1));
329 list->push_back(SelectionParserValue::createString($2));
335 /* Selection is made of an expression and zero or more modifiers */
336 selection: pos_expr { $$ = $1; }
340 set($$, _gmx_sel_init_position(get($1), NULL, scanner));
344 | '(' selection ')' { $$ = $2; }
345 | selection MODIFIER method_params
348 set($$, _gmx_sel_init_modifier($2, get($3), get($1), scanner));
354 /********************************************************************
355 * BASIC NON-TERMINAL SYMBOLS
356 ********************************************************************/
360 | '-' TOK_INT { $$ = -$2; }
364 TOK_REAL { $$ = $1; }
365 | '-' TOK_REAL { $$ = -$2; }
368 number: integer_number { $$ = $1; }
369 | real_number { $$ = $1; }
372 string: STR { $$ = $1; }
373 | IDENTIFIER { $$ = $1; }
376 /********************************************************************
377 * ATOM SELECTION EXPRESSIONS
378 ********************************************************************/
380 /* Boolean expressions and grouping */
381 sel_expr: NOT sel_expr
384 SelectionTreeElementPointer arg(get($2));
385 SelectionTreeElementPointer sel(
386 new SelectionTreeElement(SEL_BOOLEAN));
387 sel->u.boolt = BOOL_NOT;
392 | sel_expr AND sel_expr
395 SelectionTreeElementPointer arg1(get($1)), arg2(get($3));
396 SelectionTreeElementPointer sel(
397 new SelectionTreeElement(SEL_BOOLEAN));
398 sel->u.boolt = BOOL_AND;
399 sel->child = arg1; sel->child->next = arg2;
403 | sel_expr OR sel_expr
406 SelectionTreeElementPointer arg1(get($1)), arg2(get($3));
407 SelectionTreeElementPointer sel(
408 new SelectionTreeElement(SEL_BOOLEAN));
409 sel->u.boolt = BOOL_OR;
410 sel->child = arg1; sel->child->next = arg2;
414 | '(' sel_expr ')' { $$ = $2; }
417 /* Numeric comparisons */
418 sel_expr: num_expr CMP_OP num_expr
421 scoped_ptr_sfree opGuard($2);
422 set($$, _gmx_sel_init_comparison(get($1), get($3), $2, scanner));
428 /* External groups */
429 sel_expr: GROUP string
432 scoped_ptr_sfree nameGuard($2);
433 set($$, _gmx_sel_init_group_by_name($2, scanner));
439 set($$, _gmx_sel_init_group_by_id($2, scanner));
444 /* Position modifiers for selection methods */
445 pos_mod: EMPTY_POSMOD { $$ = NULL; }
446 | KEYWORD_POS { $$ = $1; }
449 /* Matching mode forcing for keyword matching */
451 '~' { $$ = gmx::eStringMatchType_RegularExpression; }
452 | '?' { $$ = gmx::eStringMatchType_Wildcard; }
453 | '=' { $$ = gmx::eStringMatchType_Exact; }
456 /* Keyword selections */
457 sel_expr: pos_mod KEYWORD_GROUP
460 scoped_ptr_sfree posmodGuard($1);
461 set($$, _gmx_sel_init_keyword($2, SelectionParserValueListPointer(), $1, scanner));
465 | pos_mod KEYWORD_STR basic_value_list
468 scoped_ptr_sfree posmodGuard($1);
469 set($$, _gmx_sel_init_keyword_strmatch($2, gmx::eStringMatchType_Auto, get($3), $1, scanner));
473 | pos_mod KEYWORD_STR str_match_type basic_value_list
476 scoped_ptr_sfree posmodGuard($1);
477 set($$, _gmx_sel_init_keyword_strmatch($2, $3, get($4), $1, scanner));
481 | pos_mod KEYWORD_NUMERIC basic_value_list
484 scoped_ptr_sfree posmodGuard($1);
485 set($$, _gmx_sel_init_keyword($2, get($3), $1, scanner));
491 /* Custom selection methods */
492 sel_expr: pos_mod METHOD_GROUP method_params
495 scoped_ptr_sfree posmodGuard($1);
496 set($$, _gmx_sel_init_method($2, get($3), $1, scanner));
502 /********************************************************************
503 * NUMERICAL EXPRESSIONS
504 ********************************************************************/
506 /* Basic numerical values */
510 SelectionTreeElementPointer sel(
511 new SelectionTreeElement(SEL_CONST));
512 _gmx_selelem_set_vtype(sel, INT_VALUE);
513 _gmx_selvalue_reserve(&sel->v, 1);
521 SelectionTreeElementPointer sel(
522 new SelectionTreeElement(SEL_CONST));
523 _gmx_selelem_set_vtype(sel, REAL_VALUE);
524 _gmx_selvalue_reserve(&sel->v, 1);
531 /* Numeric selection methods */
532 num_expr: pos_mod KEYWORD_NUMERIC %prec NUM_REDUCT
535 scoped_ptr_sfree posmodGuard($1);
536 set($$, _gmx_sel_init_keyword($2, SelectionParserValueListPointer(), $1, scanner));
540 | pos_mod METHOD_NUMERIC method_params
543 scoped_ptr_sfree posmodGuard($1);
544 set($$, _gmx_sel_init_method($2, get($3), $1, scanner));
550 /* Arithmetic evaluation and grouping */
551 num_expr: num_expr '+' num_expr
554 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '+', scanner));
557 | num_expr '-' num_expr
560 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '-', scanner));
563 | num_expr '*' num_expr
566 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '*', scanner));
569 | num_expr '/' num_expr
572 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '/', scanner));
575 | '-' num_expr %prec UNARY_NEG
578 set($$, _gmx_sel_init_arithmetic(get($2), SelectionTreeElementPointer(), '-', scanner));
581 | num_expr '^' num_expr
584 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '^', scanner));
587 | '(' num_expr ')' { $$ = $2; }
590 /********************************************************************
592 ********************************************************************/
597 SelectionTreeElementPointer sel(
598 new SelectionTreeElement(SEL_CONST));
599 _gmx_selelem_set_vtype(sel, STR_VALUE);
600 _gmx_selvalue_reserve(&sel->v, 1);
605 | pos_mod KEYWORD_STR
608 scoped_ptr_sfree posmodGuard($1);
609 set($$, _gmx_sel_init_keyword($2, SelectionParserValueListPointer(), $1, scanner));
615 /********************************************************************
616 * POSITION EXPRESSIONS
617 ********************************************************************/
619 /* Constant position expressions */
620 pos_expr: '[' number ',' number ',' number ']'
623 set($$, _gmx_sel_init_const_position($2, $4, $6));
628 /* Grouping of position expressions */
629 pos_expr: '(' pos_expr ')' { $$ = $2; }
632 /* Expressions with a position value */
633 pos_expr: METHOD_POS method_params
636 set($$, _gmx_sel_init_method($1, get($2), NULL, scanner));
642 /* Evaluation of positions using a keyword */
643 pos_expr: KEYWORD_POS OF sel_expr %prec PARAM_REDUCT
646 scoped_ptr_sfree keywordGuard($1);
647 set($$, _gmx_sel_init_position(get($3), $1, scanner));
653 /********************************************************************
655 ********************************************************************/
657 sel_expr: VARIABLE_GROUP
660 set($$, _gmx_sel_init_variable_ref(get($1)));
665 num_expr: VARIABLE_NUMERIC
668 set($$, _gmx_sel_init_variable_ref(get($1)));
673 pos_expr: VARIABLE_POS
676 set($$, _gmx_sel_init_variable_ref(get($1)));
681 /********************************************************************
683 ********************************************************************/
688 | method_param_list END_OF_METHOD
696 set($$, SelectionParserParameter::createList());
699 | method_param_list method_param
702 SelectionParserParameterListPointer list(get($1));
703 list->push_back(get($2));
713 scoped_ptr_sfree nameGuard($1);
714 set($$, SelectionParserParameter::create($1, get($2)));
719 value_list: value_list_contents { $$ = $1; }
720 | '{' value_list_contents '}' { $$ = $2; }
727 set($$, SelectionParserValue::createList());
730 | value_list_contents value_item
733 SelectionParserValueListPointer list(get($1));
734 list->push_back(get($2));
738 | value_list_contents ',' value_item
741 SelectionParserValueListPointer list(get($1));
742 list->push_back(get($3));
749 basic_value_list_contents { $$ = $1; }
750 | '{' basic_value_list_contents '}' { $$ = $2; }
753 basic_value_list_contents:
757 set($$, SelectionParserValue::createList(get($1)));
760 | basic_value_list_contents basic_value_item
763 SelectionParserValueListPointer list(get($1));
764 list->push_back(get($2));
768 | basic_value_list_contents ',' basic_value_item
771 SelectionParserValueListPointer list(get($1));
772 list->push_back(get($3));
778 value_item: sel_expr %prec PARAM_REDUCT
781 set($$, SelectionParserValue::createExpr(get($1)));
784 | pos_expr %prec PARAM_REDUCT
787 set($$, SelectionParserValue::createExpr(get($1)));
790 | num_expr %prec PARAM_REDUCT
793 set($$, SelectionParserValue::createExpr(get($1)));
796 | str_expr %prec PARAM_REDUCT
799 set($$, SelectionParserValue::createExpr(get($1)));
802 | value_item_range { $$ = $1; }
806 integer_number %prec PARAM_REDUCT
809 set($$, SelectionParserValue::createInteger($1));
812 | real_number %prec PARAM_REDUCT
815 set($$, SelectionParserValue::createReal($1));
818 | string %prec PARAM_REDUCT
821 scoped_ptr_sfree stringGuard($1);
822 set($$, SelectionParserValue::createString($1));
825 | value_item_range { $$ = $1; }
829 integer_number TO integer_number
832 set($$, SelectionParserValue::createIntegerRange($1, $3));
835 | integer_number TO real_number
838 set($$, SelectionParserValue::createRealRange($1, $3));
841 | real_number TO number
844 set($$, SelectionParserValue::createRealRange($1, $3));