3 * This file is part of the GROMACS molecular simulation package.
5 * Copyright (c) 2009,2010,2011,2012,2013,2014, 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_ptr_sfree.h"
59 #include "parser_internal.h"
61 using gmx::scoped_ptr_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"
85 struct gmx_ana_selmethod_t *meth;
87 gmx::SelectionStringMatchType smt;
89 gmx::SelectionTreeElementPointer *sel;
90 gmx::SelectionParserValue *val;
91 gmx::SelectionParserValueListPointer *vlist;
92 gmx::SelectionParserParameter *param;
93 gmx::SelectionParserParameterListPointer *plist;
96 /* Invalid token to report lexer errors */
99 /* Simple input tokens */
103 %token <str> IDENTIFIER
106 /* Simple keyword tokens */
110 /* Variable tokens */
111 %token <sel> VARIABLE_NUMERIC
112 %token <sel> VARIABLE_GROUP
113 %token <sel> VARIABLE_POS
115 /* Selection method tokens */
116 %token <meth> KEYWORD_NUMERIC
117 %token <meth> KEYWORD_STR
118 %token <str> KEYWORD_POS
119 %token <meth> KEYWORD_GROUP
120 %token <meth> METHOD_NUMERIC
121 %token <meth> METHOD_GROUP
122 %token <meth> METHOD_POS
123 %token <meth> MODIFIER
124 /* Empty token that should precede any non-position KEYWORD/METHOD token that
125 * is not preceded by KEYWORD_POS. This is used to work around reduce/reduce
126 * conflicts that appear when a lookahead token would require a reduction of
127 * a rule with empty RHS before shifting, and there is an alternative reduction
128 * available. Replacing the empty RHS with a dummy token makes these conflicts
129 * only shift/reduce conflicts. Another alternative would be to remove the
130 * pos_mod non-terminal completely and split each rule that uses it into two,
131 * but this would require duplicating six rules in the grammar. */
138 /* Comparison operators have lower precedence than parameter reduction
139 * to make it possible to parse, e.g., "mindist from resnr 1 < 2" without
141 %nonassoc <str> CMP_OP
142 /* A dummy token that determines the precedence of parameter reduction */
143 %nonassoc PARAM_REDUCT
144 /* Boolean operator tokens */
148 /* Arithmetic operator tokens */
151 %right UNARY_NEG /* Dummy token for unary negation precedence */
153 %nonassoc NUM_REDUCT /* Dummy token for numerical keyword reduction precedence */
155 /* Simple non-terminals */
156 %type <i> integer_number
157 %type <r> real_number number
160 %type <smt> str_match_type
162 /* Expression non-terminals */
163 %type <sel> commands command cmd_plain
164 %type <sel> selection
170 /* Parameter/value non-terminals */
171 %type <plist> method_params method_param_list
172 %type <param> method_param
173 %type <vlist> value_list value_list_contents basic_value_list basic_value_list_contents
174 %type <val> value_item value_item_range basic_value_item
176 %destructor { free($$); } STR IDENTIFIER KEYWORD_POS CMP_OP string
177 %destructor { if($$) free($$); } PARAM pos_mod
178 %destructor { delete $$; } commands command cmd_plain selection
179 %destructor { delete $$; } sel_expr num_expr str_expr pos_expr
180 %destructor { delete $$; } method_params method_param_list method_param
181 %destructor { delete $$; } value_list value_list_contents basic_value_list basic_value_list_contents
182 %destructor { delete $$; } value_item value_item_range basic_value_item
187 %define api.push-pull push
189 %name-prefix="_gmx_sel_yy"
190 %parse-param { void *scanner }
194 /* The start rule: allow one or more commands */
195 commands: /* empty */
204 set($$, _gmx_sel_append_selection(get($2), get($1), scanner));
205 if (_gmx_sel_parser_should_finish(scanner))
211 /* A command is formed from an actual command and a separator */
212 command: cmd_plain CMD_SEP { $$ = $1; }
216 _gmx_selparser_error(scanner, "invalid selection '%s'",
217 _gmx_sel_lexer_pselstr(scanner));
218 _gmx_sel_lexer_clear_method_stack(scanner);
219 if (_gmx_sel_is_lexer_interactive(scanner))
221 _gmx_sel_lexer_clear_pselstr(scanner);
233 /* Commands can be selections or variable assignments */
234 cmd_plain: /* empty */
243 SelectionTreeElementPointer s
244 = _gmx_sel_init_group_by_id($1, scanner);
245 SelectionTreeElementPointer p
246 = _gmx_sel_init_position(s, NULL, scanner);
248 set($$, _gmx_sel_init_selection(NULL, p, scanner));
254 scoped_ptr_sfree nameGuard($1);
255 SelectionTreeElementPointer s
256 = _gmx_sel_init_group_by_name($1, scanner);
257 SelectionTreeElementPointer p
258 = _gmx_sel_init_position(s, NULL, scanner);
260 set($$, _gmx_sel_init_selection(NULL, p, scanner));
266 set($$, _gmx_sel_init_selection(NULL, get($1), scanner));
272 scoped_ptr_sfree nameGuard($1);
273 set($$, _gmx_sel_init_selection($1, get($2), scanner));
276 | IDENTIFIER '=' sel_expr
279 scoped_ptr_sfree nameGuard($1);
280 set($$, _gmx_sel_assign_variable($1, get($3), scanner));
283 | IDENTIFIER '=' num_expr
286 scoped_ptr_sfree nameGuard($1);
287 set($$, _gmx_sel_assign_variable($1, get($3), scanner));
290 | IDENTIFIER '=' pos_expr
293 scoped_ptr_sfree nameGuard($1);
294 set($$, _gmx_sel_assign_variable($1, get($3), scanner));
299 /* Selection is made of an expression and zero or more modifiers */
300 selection: pos_expr { $$ = $1; }
304 set($$, _gmx_sel_init_position(get($1), NULL, scanner));
308 | '(' selection ')' { $$ = $2; }
309 | selection MODIFIER method_params
312 set($$, _gmx_sel_init_modifier($2, get($3), get($1), scanner));
318 /********************************************************************
319 * BASIC NON-TERMINAL SYMBOLS
320 ********************************************************************/
324 | '-' TOK_INT { $$ = -$2; }
328 TOK_REAL { $$ = $1; }
329 | '-' TOK_REAL { $$ = -$2; }
332 number: integer_number { $$ = $1; }
333 | real_number { $$ = $1; }
336 string: STR { $$ = $1; }
337 | IDENTIFIER { $$ = $1; }
340 /********************************************************************
341 * ATOM SELECTION EXPRESSIONS
342 ********************************************************************/
344 /* Boolean expressions and grouping */
345 sel_expr: NOT sel_expr
348 SelectionTreeElementPointer arg(get($2));
349 SelectionTreeElementPointer sel(
350 new SelectionTreeElement(SEL_BOOLEAN));
351 sel->u.boolt = BOOL_NOT;
356 | sel_expr AND sel_expr
359 SelectionTreeElementPointer arg1(get($1)), arg2(get($3));
360 SelectionTreeElementPointer sel(
361 new SelectionTreeElement(SEL_BOOLEAN));
362 sel->u.boolt = BOOL_AND;
363 sel->child = arg1; sel->child->next = arg2;
367 | sel_expr OR sel_expr
370 SelectionTreeElementPointer arg1(get($1)), arg2(get($3));
371 SelectionTreeElementPointer sel(
372 new SelectionTreeElement(SEL_BOOLEAN));
373 sel->u.boolt = BOOL_OR;
374 sel->child = arg1; sel->child->next = arg2;
378 | '(' sel_expr ')' { $$ = $2; }
381 /* Numeric comparisons */
382 sel_expr: num_expr CMP_OP num_expr
385 scoped_ptr_sfree opGuard($2);
386 set($$, _gmx_sel_init_comparison(get($1), get($3), $2, scanner));
392 /* External groups */
393 sel_expr: GROUP string
396 scoped_ptr_sfree nameGuard($2);
397 set($$, _gmx_sel_init_group_by_name($2, scanner));
403 set($$, _gmx_sel_init_group_by_id($2, scanner));
408 /* Position modifiers for selection methods */
409 pos_mod: EMPTY_POSMOD { $$ = NULL; }
410 | KEYWORD_POS { $$ = $1; }
413 /* Matching mode forcing for keyword matching */
415 '~' { $$ = gmx::eStringMatchType_RegularExpression; }
416 | '?' { $$ = gmx::eStringMatchType_Wildcard; }
417 | '=' { $$ = gmx::eStringMatchType_Exact; }
420 /* Keyword selections */
421 sel_expr: pos_mod KEYWORD_GROUP
424 scoped_ptr_sfree posmodGuard($1);
425 set($$, _gmx_sel_init_keyword($2, SelectionParserValueListPointer(), $1, scanner));
429 | pos_mod KEYWORD_STR basic_value_list
432 scoped_ptr_sfree posmodGuard($1);
433 set($$, _gmx_sel_init_keyword_strmatch($2, gmx::eStringMatchType_Auto, get($3), $1, scanner));
437 | pos_mod KEYWORD_STR str_match_type basic_value_list
440 scoped_ptr_sfree posmodGuard($1);
441 set($$, _gmx_sel_init_keyword_strmatch($2, $3, get($4), $1, scanner));
445 | pos_mod KEYWORD_NUMERIC basic_value_list
448 scoped_ptr_sfree posmodGuard($1);
449 set($$, _gmx_sel_init_keyword($2, get($3), $1, scanner));
455 /* Custom selection methods */
456 sel_expr: pos_mod METHOD_GROUP method_params
459 scoped_ptr_sfree posmodGuard($1);
460 set($$, _gmx_sel_init_method($2, get($3), $1, scanner));
466 /********************************************************************
467 * NUMERICAL EXPRESSIONS
468 ********************************************************************/
470 /* Basic numerical values */
474 SelectionTreeElementPointer sel(
475 new SelectionTreeElement(SEL_CONST));
476 _gmx_selelem_set_vtype(sel, INT_VALUE);
477 _gmx_selvalue_reserve(&sel->v, 1);
485 SelectionTreeElementPointer sel(
486 new SelectionTreeElement(SEL_CONST));
487 _gmx_selelem_set_vtype(sel, REAL_VALUE);
488 _gmx_selvalue_reserve(&sel->v, 1);
495 /* Numeric selection methods */
496 num_expr: pos_mod KEYWORD_NUMERIC %prec NUM_REDUCT
499 scoped_ptr_sfree posmodGuard($1);
500 set($$, _gmx_sel_init_keyword($2, SelectionParserValueListPointer(), $1, scanner));
504 | pos_mod METHOD_NUMERIC method_params
507 scoped_ptr_sfree posmodGuard($1);
508 set($$, _gmx_sel_init_method($2, get($3), $1, scanner));
514 /* Arithmetic evaluation and grouping */
515 num_expr: num_expr '+' num_expr
518 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '+', scanner));
521 | num_expr '-' num_expr
524 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '-', scanner));
527 | num_expr '*' num_expr
530 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '*', scanner));
533 | num_expr '/' num_expr
536 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '/', scanner));
539 | '-' num_expr %prec UNARY_NEG
542 set($$, _gmx_sel_init_arithmetic(get($2), SelectionTreeElementPointer(), '-', scanner));
545 | num_expr '^' num_expr
548 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '^', scanner));
551 | '(' num_expr ')' { $$ = $2; }
554 /********************************************************************
556 ********************************************************************/
561 SelectionTreeElementPointer sel(
562 new SelectionTreeElement(SEL_CONST));
563 _gmx_selelem_set_vtype(sel, STR_VALUE);
564 _gmx_selvalue_reserve(&sel->v, 1);
569 | pos_mod KEYWORD_STR
572 scoped_ptr_sfree posmodGuard($1);
573 set($$, _gmx_sel_init_keyword($2, SelectionParserValueListPointer(), $1, scanner));
579 /********************************************************************
580 * POSITION EXPRESSIONS
581 ********************************************************************/
583 /* Constant position expressions */
584 pos_expr: '[' number ',' number ',' number ']'
587 set($$, _gmx_sel_init_const_position($2, $4, $6));
592 /* Grouping of position expressions */
593 pos_expr: '(' pos_expr ')' { $$ = $2; }
596 /* Expressions with a position value */
597 pos_expr: METHOD_POS method_params
600 set($$, _gmx_sel_init_method($1, get($2), NULL, scanner));
606 /* Evaluation of positions using a keyword */
607 pos_expr: KEYWORD_POS OF sel_expr %prec PARAM_REDUCT
610 scoped_ptr_sfree keywordGuard($1);
611 set($$, _gmx_sel_init_position(get($3), $1, scanner));
617 /********************************************************************
619 ********************************************************************/
621 sel_expr: VARIABLE_GROUP
624 set($$, _gmx_sel_init_variable_ref(get($1)));
629 num_expr: VARIABLE_NUMERIC
632 set($$, _gmx_sel_init_variable_ref(get($1)));
637 pos_expr: VARIABLE_POS
640 set($$, _gmx_sel_init_variable_ref(get($1)));
645 /********************************************************************
647 ********************************************************************/
652 | method_param_list END_OF_METHOD
660 set($$, SelectionParserParameter::createList());
663 | method_param_list method_param
666 SelectionParserParameterListPointer list(get($1));
667 list->push_back(get($2));
677 scoped_ptr_sfree nameGuard($1);
678 set($$, SelectionParserParameter::create($1, get($2)));
683 value_list: value_list_contents { $$ = $1; }
684 | '{' value_list_contents '}' { $$ = $2; }
691 set($$, SelectionParserValue::createList());
694 | value_list_contents value_item
697 SelectionParserValueListPointer list(get($1));
698 list->push_back(get($2));
702 | value_list_contents ',' value_item
705 SelectionParserValueListPointer list(get($1));
706 list->push_back(get($3));
713 basic_value_list_contents { $$ = $1; }
714 | '{' basic_value_list_contents '}' { $$ = $2; }
717 basic_value_list_contents:
721 set($$, SelectionParserValue::createList(get($1)));
724 | basic_value_list_contents basic_value_item
727 SelectionParserValueListPointer list(get($1));
728 list->push_back(get($2));
732 | basic_value_list_contents ',' basic_value_item
735 SelectionParserValueListPointer list(get($1));
736 list->push_back(get($3));
742 value_item: sel_expr %prec PARAM_REDUCT
745 set($$, SelectionParserValue::createExpr(get($1)));
748 | pos_expr %prec PARAM_REDUCT
751 set($$, SelectionParserValue::createExpr(get($1)));
754 | num_expr %prec PARAM_REDUCT
757 set($$, SelectionParserValue::createExpr(get($1)));
760 | str_expr %prec PARAM_REDUCT
763 set($$, SelectionParserValue::createExpr(get($1)));
766 | value_item_range { $$ = $1; }
770 integer_number %prec PARAM_REDUCT
773 set($$, SelectionParserValue::createInteger($1));
776 | real_number %prec PARAM_REDUCT
779 set($$, SelectionParserValue::createReal($1));
782 | string %prec PARAM_REDUCT
785 scoped_ptr_sfree stringGuard($1);
786 set($$, SelectionParserValue::createString($1));
789 | value_item_range { $$ = $1; }
793 integer_number TO integer_number
796 set($$, SelectionParserValue::createIntegerRange($1, $3));
799 | integer_number TO real_number
802 set($$, SelectionParserValue::createRealRange($1, $3));
805 | real_number TO number
808 set($$, SelectionParserValue::createRealRange($1, $3));