3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
9 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11 * Copyright (c) 2001-2009, The GROMACS development team,
12 * check out http://www.gromacs.org for more information.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * If you want to redistribute modifications, please consider that
20 * scientific software is very special. Version control is crucial -
21 * bugs must be traceable. We will be happy to consider code for
22 * inclusion in the official distribution, but derived work must not
23 * be called official GROMACS. Details are found in the README & COPYING
24 * files - if they are missing, get the official version at www.gromacs.org.
26 * To help us fund GROMACS development, we humbly ask that you cite
27 * the papers on the package - you can find them in the top README file.
29 * For more info, check our website at http://www.gromacs.org
32 * \brief Grammar description and parser for the selection language.
35 /*! \internal \file parser.c
36 * \brief Generated (from parser.y by Bison) parser for the selection language.
38 /*! \internal \file parser.h
39 * \brief Generated (from parser.y by Bison) parser include file.
47 #include "parsetree.h"
52 static t_selexpr_value *
53 process_value_list(t_selexpr_value *values, int *nr);
54 static t_selexpr_param *
55 process_param_list(t_selexpr_param *params);
58 yyerror(yyscan_t, char const *s);
60 // Work around compiler warnings that result from bison not correctly
61 // dealing with stdlib.h with ICC on Windows.
62 #if (defined __INTEL_COMPILER && defined _WIN32)
63 #define YYMALLOC malloc
72 struct gmx_ana_selmethod_t *meth;
74 struct t_selelem *sel;
76 struct t_selexpr_value *val;
77 struct t_selexpr_param *param;
79 /* NOTE: The Intel compiler seems to report warnings for the above line about
80 * "definition at end of file not followed by a semicolon or a declarator".
81 * This is due to the compiler misinterpreting #line directives in the
82 * generated files parser.c/.h, and changing them would be more trouble than
85 /* Invalid token to report lexer errors */
88 /* Tokens for help requests */
90 %token <str> HELP_TOPIC
92 /* Simple input tokens */
96 %token <str> IDENTIFIER
99 /* Simple keyword tokens */
103 /* Variable tokens */
104 %token <sel> VARIABLE_NUMERIC
105 %token <sel> VARIABLE_GROUP
106 %token <sel> VARIABLE_POS
108 /* Selection method tokens */
109 %token <meth> KEYWORD_NUMERIC
110 %token <meth> KEYWORD_STR
111 %token <str> KEYWORD_POS
112 %token <meth> KEYWORD_GROUP
113 %token <meth> METHOD_NUMERIC
114 %token <meth> METHOD_GROUP
115 %token <meth> METHOD_POS
116 %token <meth> MODIFIER
117 /* Empty token that should precede any non-position KEYWORD/METHOD token that
118 * is not preceded by KEYWORD_POS. This is used to work around reduce/reduce
119 * conflicts that appear when a lookahead token would require a reduction of
120 * a rule with empty RHS before shifting, and there is an alternative reduction
121 * available. Replacing the empty RHS with a dummy token makes these conflicts
122 * only shift/reduce conflicts. Another alternative would be to remove the
123 * pos_mod non-terminal completely and split each rule that uses it into two,
124 * but this would require duplicating six rules in the grammar. */
131 /* Comparison operators have lower precedence than parameter reduction
132 * to make it possible to parse, e.g., "mindist from resnr 1 < 2" without
134 %nonassoc <str> CMP_OP
135 /* A dummy token that determines the precedence of parameter reduction */
136 %nonassoc PARAM_REDUCT
137 /* Boolean operator tokens */
141 /* Arithmetic operator tokens */
144 %right UNARY_NEG /* Dummy token for unary negation precedence */
146 %nonassoc NUM_REDUCT /* Dummy token for numerical keyword reduction precedence */
148 /* Simple non-terminals */
149 %type <r> integer_number
150 %type <r> real_number number
154 /* Expression non-terminals */
155 %type <sel> commands command cmd_plain
156 %type <sel> selection
162 /* Parameter/value non-terminals */
163 %type <param> method_params method_param_list method_param
164 %type <val> value_list value_list_contents value_item value_item_range
165 %type <val> basic_value_list basic_value_list_contents basic_value_item
167 %destructor { free($$); } HELP_TOPIC STR IDENTIFIER CMP_OP string
168 %destructor { if($$) free($$); } PARAM
169 %destructor { if($$) _gmx_selelem_free($$); } command cmd_plain
170 %destructor { _gmx_selelem_free_chain($$); } selection
171 %destructor { _gmx_selelem_free($$); } sel_expr num_expr str_expr pos_expr
172 %destructor { _gmx_selexpr_free_params($$); } method_params method_param_list method_param
173 %destructor { _gmx_selexpr_free_values($$); } value_list value_list_contents value_item value_item_range
174 %destructor { _gmx_selexpr_free_values($$); } basic_value_list basic_value_list_contents basic_value_item
180 /* If you change these, you also need to update the prototype in parsetree.c. */
181 %name-prefix="_gmx_sel_yyb"
182 %parse-param { yyscan_t scanner }
183 %lex-param { yyscan_t scanner }
187 /* The start rule: allow one or more commands */
188 commands: /* empty */ { $$ = NULL }
191 $$ = _gmx_sel_append_selection($2, $1, scanner);
192 if (_gmx_sel_parser_should_finish(scanner))
197 /* A command is formed from an actual command and a separator */
198 command: cmd_plain CMD_SEP { $$ = $1; }
202 _gmx_selparser_error("invalid selection '%s'",
203 _gmx_sel_lexer_pselstr(scanner));
204 _gmx_sel_lexer_clear_method_stack(scanner);
205 if (_gmx_sel_is_lexer_interactive(scanner))
207 _gmx_sel_lexer_clear_pselstr(scanner);
217 /* Commands can be selections or variable assignments */
218 cmd_plain: /* empty */
221 _gmx_sel_handle_empty_cmd(scanner);
223 | help_request { $$ = NULL; }
227 s = _gmx_sel_init_group_by_id($1, scanner);
228 if (s == NULL) YYERROR;
229 p = _gmx_sel_init_position(s, NULL, scanner);
230 if (p == NULL) YYERROR;
231 $$ = _gmx_sel_init_selection(strdup(s->name), p, scanner);
236 s = _gmx_sel_init_group_by_name($1, scanner);
238 if (s == NULL) YYERROR;
239 p = _gmx_sel_init_position(s, NULL, scanner);
240 if (p == NULL) YYERROR;
241 $$ = _gmx_sel_init_selection(strdup(s->name), p, scanner);
244 { $$ = _gmx_sel_init_selection(NULL, $1, scanner); }
246 { $$ = _gmx_sel_init_selection($1, $2, scanner); }
247 | IDENTIFIER '=' sel_expr
248 { $$ = _gmx_sel_assign_variable($1, $3, scanner); }
249 | IDENTIFIER '=' num_expr
250 { $$ = _gmx_sel_assign_variable($1, $3, scanner); }
251 | IDENTIFIER '=' pos_expr
252 { $$ = _gmx_sel_assign_variable($1, $3, scanner); }
257 HELP { _gmx_sel_handle_help_cmd(NULL, scanner); }
261 help_topic: HELP HELP_TOPIC { _gmx_sel_handle_help_cmd($2, scanner); }
262 | help_topic HELP_TOPIC { _gmx_sel_handle_help_cmd($2, scanner); }
265 /* Selection is made of an expression and zero or more modifiers */
266 selection: pos_expr { $$ = $1; }
269 $$ = _gmx_sel_init_position($1, NULL, scanner);
270 if ($$ == NULL) YYERROR;
272 | '(' selection ')' { $$ = $2; }
273 | selection MODIFIER method_params
275 $$ = _gmx_sel_init_modifier($2, $3, $1, scanner);
276 if ($$ == NULL) YYERROR;
280 /********************************************************************
281 * BASIC NON-TERMINAL SYMBOLS
282 ********************************************************************/
286 | '-' TOK_INT { $$ = -$2; }
290 TOK_REAL { $$ = $1; }
291 | '-' TOK_REAL { $$ = -$2; }
294 number: integer_number { $$ = $1; }
295 | real_number { $$ = $1; }
298 string: STR { $$ = $1; }
299 | IDENTIFIER { $$ = $1; }
302 /********************************************************************
303 * ATOM SELECTION EXPRESSIONS
304 ********************************************************************/
306 /* Boolean expressions and grouping */
307 sel_expr: NOT sel_expr
309 $$ = _gmx_selelem_create(SEL_BOOLEAN);
310 $$->u.boolt = BOOL_NOT;
313 | sel_expr AND sel_expr
315 $$ = _gmx_selelem_create(SEL_BOOLEAN);
316 $$->u.boolt = BOOL_AND;
317 $$->child = $1; $$->child->next = $3;
319 | sel_expr OR sel_expr
321 $$ = _gmx_selelem_create(SEL_BOOLEAN);
322 $$->u.boolt = BOOL_OR;
323 $$->child = $1; $$->child->next = $3;
325 /* | sel_expr XOR sel_expr
327 $$ = _gmx_selelem_create(SEL_BOOLEAN);
328 $$->u.boolt = BOOL_XOR;
329 $$->child = $1; $$->child->next = $3;
331 | '(' sel_expr ')' { $$ = $2; }
334 /* Numeric comparisons */
335 sel_expr: num_expr CMP_OP num_expr
337 $$ = _gmx_sel_init_comparison($1, $3, $2, scanner);
338 if ($$ == NULL) YYERROR;
342 /* External groups */
343 sel_expr: GROUP string
345 $$ = _gmx_sel_init_group_by_name($2, scanner);
347 if ($$ == NULL) YYERROR;
351 $$ = _gmx_sel_init_group_by_id($2, scanner);
352 if ($$ == NULL) YYERROR;
356 /* Position modifiers for selection methods */
357 pos_mod: EMPTY_POSMOD { $$ = NULL; }
358 | KEYWORD_POS { $$ = $1; }
361 /* Keyword selections */
362 sel_expr: pos_mod KEYWORD_GROUP
364 $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
365 if ($$ == NULL) YYERROR;
367 | pos_mod KEYWORD_STR basic_value_list
369 $$ = _gmx_sel_init_keyword($2, process_value_list($3, NULL), $1, scanner);
370 if ($$ == NULL) YYERROR;
372 | pos_mod KEYWORD_NUMERIC basic_value_list
374 $$ = _gmx_sel_init_keyword($2, process_value_list($3, NULL), $1, scanner);
375 if ($$ == NULL) YYERROR;
379 /* Custom selection methods */
380 sel_expr: pos_mod METHOD_GROUP method_params
382 $$ = _gmx_sel_init_method($2, $3, $1, scanner);
383 if ($$ == NULL) YYERROR;
387 /********************************************************************
388 * NUMERICAL EXPRESSIONS
389 ********************************************************************/
391 /* Basic numerical values */
394 $$ = _gmx_selelem_create(SEL_CONST);
395 _gmx_selelem_set_vtype($$, INT_VALUE);
396 _gmx_selvalue_reserve(&$$->v, 1);
401 $$ = _gmx_selelem_create(SEL_CONST);
402 _gmx_selelem_set_vtype($$, REAL_VALUE);
403 _gmx_selvalue_reserve(&$$->v, 1);
408 /* Numeric selection methods */
409 num_expr: pos_mod KEYWORD_NUMERIC %prec NUM_REDUCT
411 $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
412 if ($$ == NULL) YYERROR;
414 | pos_mod METHOD_NUMERIC method_params
416 $$ = _gmx_sel_init_method($2, $3, $1, scanner);
417 if ($$ == NULL) YYERROR;
421 /* Arithmetic evaluation and grouping */
422 num_expr: num_expr '+' num_expr
423 { $$ = _gmx_sel_init_arithmetic($1, $3, '+', scanner); }
424 | num_expr '-' num_expr
425 { $$ = _gmx_sel_init_arithmetic($1, $3, '-', scanner); }
426 | num_expr '*' num_expr
427 { $$ = _gmx_sel_init_arithmetic($1, $3, '*', scanner); }
428 | num_expr '/' num_expr
429 { $$ = _gmx_sel_init_arithmetic($1, $3, '/', scanner); }
430 | '-' num_expr %prec UNARY_NEG
431 { $$ = _gmx_sel_init_arithmetic($2, NULL, '-', scanner); }
432 | num_expr '^' num_expr
433 { $$ = _gmx_sel_init_arithmetic($1, $3, '^', scanner); }
434 | '(' num_expr ')' { $$ = $2; }
437 /********************************************************************
439 ********************************************************************/
443 $$ = _gmx_selelem_create(SEL_CONST);
444 _gmx_selelem_set_vtype($$, STR_VALUE);
445 _gmx_selvalue_reserve(&$$->v, 1);
448 | pos_mod KEYWORD_STR
450 $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
451 if ($$ == NULL) YYERROR;
455 /********************************************************************
456 * POSITION EXPRESSIONS
457 ********************************************************************/
459 /* Constant position expressions */
460 pos_expr: '[' number ',' number ',' number ']'
461 { $$ = _gmx_sel_init_const_position($2, $4, $6); }
464 /* Grouping of position expressions */
465 pos_expr: '(' pos_expr ')' { $$ = $2; }
468 /* Expressions with a position value */
469 pos_expr: METHOD_POS method_params
471 $$ = _gmx_sel_init_method($1, $2, NULL, scanner);
472 if ($$ == NULL) YYERROR;
476 /* Evaluation of positions using a keyword */
477 pos_expr: KEYWORD_POS OF sel_expr %prec PARAM_REDUCT
479 $$ = _gmx_sel_init_position($3, $1, scanner);
480 if ($$ == NULL) YYERROR;
484 /********************************************************************
486 ********************************************************************/
488 sel_expr: VARIABLE_GROUP
489 { $$ = _gmx_sel_init_variable_ref($1); }
492 num_expr: VARIABLE_NUMERIC
493 { $$ = _gmx_sel_init_variable_ref($1); }
496 pos_expr: VARIABLE_POS
497 { $$ = _gmx_sel_init_variable_ref($1); }
500 /********************************************************************
502 ********************************************************************/
506 { $$ = process_param_list($1); }
507 | method_param_list END_OF_METHOD
508 { $$ = process_param_list($1); }
512 /* empty */ { $$ = NULL; }
513 | method_param_list method_param
514 { $2->next = $1; $$ = $2; }
520 $$ = _gmx_selexpr_create_param($1);
521 $$->value = process_value_list($2, &$$->nval);
525 value_list: /* empty */ { $$ = NULL; }
526 | value_list_contents { $$ = $1; }
527 | '{' value_list_contents '}' { $$ = $2; }
531 value_item { $$ = $1; }
532 | value_list_contents value_item
533 { $2->next = $1; $$ = $2; }
534 | value_list_contents ',' value_item
535 { $3->next = $1; $$ = $3; }
539 basic_value_list_contents { $$ = $1; }
540 | '{' basic_value_list_contents '}' { $$ = $2; }
543 basic_value_list_contents:
544 basic_value_item { $$ = $1; }
545 | basic_value_list_contents basic_value_item
546 { $2->next = $1; $$ = $2; }
547 | basic_value_list_contents ',' basic_value_item
548 { $3->next = $1; $$ = $3; }
551 value_item: sel_expr %prec PARAM_REDUCT
552 { $$ = _gmx_selexpr_create_value_expr($1); }
553 | pos_expr %prec PARAM_REDUCT
554 { $$ = _gmx_selexpr_create_value_expr($1); }
555 | num_expr %prec PARAM_REDUCT
556 { $$ = _gmx_selexpr_create_value_expr($1); }
557 | str_expr %prec PARAM_REDUCT
558 { $$ = _gmx_selexpr_create_value_expr($1); }
559 | value_item_range { $$ = $1; }
563 integer_number %prec PARAM_REDUCT
565 $$ = _gmx_selexpr_create_value(INT_VALUE);
566 $$->u.i.i1 = $$->u.i.i2 = $1;
568 | real_number %prec PARAM_REDUCT
570 $$ = _gmx_selexpr_create_value(REAL_VALUE);
571 $$->u.r.r1 = $$->u.r.r2 = $1;
573 | string %prec PARAM_REDUCT
575 $$ = _gmx_selexpr_create_value(STR_VALUE);
578 | value_item_range { $$ = $1; }
582 integer_number TO integer_number
584 $$ = _gmx_selexpr_create_value(INT_VALUE);
585 $$->u.i.i1 = $1; $$->u.i.i2 = $3;
587 | integer_number TO real_number
589 $$ = _gmx_selexpr_create_value(REAL_VALUE);
590 $$->u.r.r1 = $1; $$->u.r.r2 = $3;
592 | real_number TO number
594 $$ = _gmx_selexpr_create_value(REAL_VALUE);
595 $$->u.r.r1 = $1; $$->u.r.r2 = $3;
601 static t_selexpr_value *
602 process_value_list(t_selexpr_value *values, int *nr)
604 t_selexpr_value *val, *pval, *nval;
606 /* Count values (if needed) and reverse list */
629 static t_selexpr_param *
630 process_param_list(t_selexpr_param *params)
632 t_selexpr_param *par, *ppar, *npar;
650 yyerror(yyscan_t scanner, char const *s)
652 _gmx_selparser_error("%s", s);