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.
48 #include "parsetree.h"
53 static t_selexpr_value
*
54 process_value_list
(t_selexpr_value
*values
, int *nr
);
55 static t_selexpr_param
*
56 process_param_list
(t_selexpr_param
*params
);
59 yyerror(yyscan_t
, char const *s
);
66 struct gmx_ana_selmethod_t
*meth
;
68 struct t_selelem
*sel
;
70 struct t_selexpr_value
*val
;
71 struct t_selexpr_param
*param
;
74 /* Invalid token to report lexer errors */
77 /* Tokens for help requests */
79 %token
<str
> HELP_TOPIC
81 /* Simple input tokens */
85 %token
<str
> IDENTIFIER
88 /* Simple keyword tokens */
93 %token
<sel
> VARIABLE_NUMERIC
94 %token
<sel
> VARIABLE_GROUP
95 %token
<sel
> VARIABLE_POS
97 /* Selection method tokens */
98 %token
<meth
> KEYWORD_NUMERIC
99 %token
<meth
> KEYWORD_STR
100 %token
<str
> KEYWORD_POS
101 %token
<meth
> KEYWORD_GROUP
102 %token
<meth
> METHOD_NUMERIC
103 %token
<meth
> METHOD_GROUP
104 %token
<meth
> METHOD_POS
105 %token
<meth
> MODIFIER
106 /* Empty token that should precede any non-position KEYWORD/METHOD token that
107 * is not preceded by KEYWORD_POS. This is used to work around reduce/reduce
108 * conflicts that appear when a lookahead token would require a reduction of
109 * a rule with empty RHS before shifting, and there is an alternative reduction
110 * available. Replacing the empty RHS with a dummy token makes these conflicts
111 * only shift/reduce conflicts. Another alternative would be to remove the
112 * pos_mod non-terminal completely and split each rule that uses it into two,
113 * but this would require duplicating six rules in the grammar. */
120 /* Comparison operators have lower precedence than parameter reduction
121 * to make it possible to parse, e.g., "mindist from resnr 1 < 2" without
123 %nonassoc
<str
> CMP_OP
124 /* A dummy token that determines the precedence of parameter reduction */
125 %nonassoc PARAM_REDUCT
126 /* Boolean operator tokens */
129 /* Arithmetic operator tokens */
132 %left UNARY_NEG
/* Dummy token for unary negation precedence */
135 /* Simple non-terminals */
140 /* Expression non-terminals */
141 %type
<sel
> commands command cmd_plain
142 %type
<sel
> selection
148 /* Parameter/value non-terminals */
149 %type
<param
> method_params method_param_list method_param
150 %type
<val
> value_list value_list_nonempty value_item
152 %destructor
{ free
($$
); } HELP_TOPIC STR IDENTIFIER CMP_OP
string
153 %destructor
{ if
($$
) free
($$
); } PARAM
154 %destructor
{ if
($$
) _gmx_selelem_free
($$
); } command cmd_plain
155 %destructor
{ _gmx_selelem_free_chain
($$
); } selection
156 %destructor
{ _gmx_selelem_free
($$
); } sel_expr num_expr str_expr pos_expr
157 %destructor
{ _gmx_selexpr_free_params
($$
); } method_params method_param_list method_param
158 %destructor
{ _gmx_selexpr_free_values
($$
); } value_list value_list_nonempty value_item
164 /* If you change these, you also need to update the prototype in parsetree.c. */
165 %name
-prefix
="_gmx_sel_yyb"
166 %parse
-param
{ yyscan_t scanner
}
167 %lex
-param
{ yyscan_t scanner
}
171 /* The start rule: allow one or more commands */
172 commands: /* empty */ { $$
= NULL
}
175 $$
= _gmx_sel_append_selection
($2, $1, scanner
);
176 if
(_gmx_sel_parser_should_finish
(scanner
))
181 /* A command is formed from an actual command and a separator */
182 command: cmd_plain CMD_SEP
{ $$
= $1; }
186 _gmx_selparser_error
("invalid selection '%s'",
187 _gmx_sel_lexer_pselstr
(scanner
));
188 _gmx_sel_lexer_clear_method_stack
(scanner
);
189 if
(_gmx_sel_is_lexer_interactive
(scanner
))
191 _gmx_sel_lexer_clear_pselstr
(scanner
);
201 /* Commands can be selections or variable assignments */
202 cmd_plain: /* empty */
205 _gmx_sel_handle_empty_cmd
(scanner
);
207 | help_request
{ $$
= NULL
; }
211 s
= _gmx_sel_init_group_by_id
($1, scanner
);
212 if
(s
== NULL
) YYERROR;
213 p
= _gmx_sel_init_position
(s
, NULL
, scanner
);
214 if
(p
== NULL
) YYERROR;
215 $$
= _gmx_sel_init_selection
(strdup
(s
->name
), p
, scanner
);
220 s
= _gmx_sel_init_group_by_name
($1, scanner
);
222 if
(s
== NULL
) YYERROR;
223 p
= _gmx_sel_init_position
(s
, NULL
, scanner
);
224 if
(p
== NULL
) YYERROR;
225 $$
= _gmx_sel_init_selection
(strdup
(s
->name
), p
, scanner
);
228 { $$
= _gmx_sel_init_selection
(NULL
, $1, scanner
); }
230 { $$
= _gmx_sel_init_selection
($1, $2, scanner
); }
231 | IDENTIFIER
'=' sel_expr
232 { $$
= _gmx_sel_assign_variable
($1, $3, scanner
); }
233 | IDENTIFIER
'=' num_expr
234 { $$
= _gmx_sel_assign_variable
($1, $3, scanner
); }
235 | IDENTIFIER
'=' pos_expr
236 { $$
= _gmx_sel_assign_variable
($1, $3, scanner
); }
241 HELP
{ _gmx_sel_handle_help_cmd
(NULL
, scanner
); }
245 help_topic: HELP HELP_TOPIC
{ _gmx_sel_handle_help_cmd
($2, scanner
); }
246 | help_topic HELP_TOPIC
{ _gmx_sel_handle_help_cmd
($2, scanner
); }
249 /* Selection is made of an expression and zero or more modifiers */
250 selection: pos_expr
{ $$
= $1; }
253 $$
= _gmx_sel_init_position
($1, NULL
, scanner
);
254 if
($$
== NULL
) YYERROR;
256 |
'(' selection
')' { $$
= $2; }
257 | selection MODIFIER method_params
259 $$
= _gmx_sel_init_modifier
($2, $3, $1, scanner
);
260 if
($$
== NULL
) YYERROR;
264 /********************************************************************
265 * BASIC NON-TERMINAL SYMBOLS
266 ********************************************************************/
268 number: TOK_INT
{ $$
= $1; }
269 | TOK_REAL
{ $$
= $1; }
272 string: STR
{ $$
= $1; }
273 | IDENTIFIER
{ $$
= $1; }
276 /********************************************************************
277 * ATOM SELECTION EXPRESSIONS
278 ********************************************************************/
280 /* Boolean expressions and grouping */
281 sel_expr: NOT sel_expr
283 $$
= _gmx_selelem_create
(SEL_BOOLEAN
);
284 $$
->u.boolt
= BOOL_NOT
;
287 | sel_expr AND sel_expr
289 $$
= _gmx_selelem_create
(SEL_BOOLEAN
);
290 $$
->u.boolt
= BOOL_AND
;
291 $$
->child
= $1; $$
->child
->next
= $3;
293 | sel_expr OR sel_expr
295 $$
= _gmx_selelem_create
(SEL_BOOLEAN
);
296 $$
->u.boolt
= BOOL_OR
;
297 $$
->child
= $1; $$
->child
->next
= $3;
299 /* | sel_expr XOR sel_expr
301 $$ = _gmx_selelem_create(SEL_BOOLEAN);
302 $$->u.boolt = BOOL_XOR;
303 $$->child = $1; $$->child->next = $3;
305 |
'(' sel_expr
')' { $$
= $2; }
308 /* Numeric comparisons */
309 sel_expr: num_expr CMP_OP num_expr
311 $$
= _gmx_sel_init_comparison
($1, $3, $2, scanner
);
312 if
($$
== NULL
) YYERROR;
316 /* External groups */
317 sel_expr: GROUP
string
319 $$
= _gmx_sel_init_group_by_name
($2, scanner
);
321 if
($$
== NULL
) YYERROR;
325 $$
= _gmx_sel_init_group_by_id
($2, scanner
);
326 if
($$
== NULL
) YYERROR;
330 /* Position modifiers for selection methods */
331 pos_mod: EMPTY_POSMOD
{ $$
= NULL
; }
332 | KEYWORD_POS
{ $$
= $1; }
335 /* Keyword selections */
336 sel_expr: pos_mod KEYWORD_GROUP
338 $$
= _gmx_sel_init_keyword
($2, NULL
, $1, scanner
);
339 if
($$
== NULL
) YYERROR;
341 | pos_mod KEYWORD_STR value_list_nonempty
343 $$
= _gmx_sel_init_keyword
($2, process_value_list
($3, NULL
), $1, scanner
);
344 if
($$
== NULL
) YYERROR;
346 | pos_mod KEYWORD_NUMERIC value_list_nonempty
348 $$
= _gmx_sel_init_keyword
($2, process_value_list
($3, NULL
), $1, scanner
);
349 if
($$
== NULL
) YYERROR;
353 /* Custom selection methods */
354 sel_expr: pos_mod METHOD_GROUP method_params
356 $$
= _gmx_sel_init_method
($2, $3, $1, scanner
);
357 if
($$
== NULL
) YYERROR;
361 /********************************************************************
362 * NUMERICAL EXPRESSIONS
363 ********************************************************************/
365 /* Basic numerical values */
368 $$
= _gmx_selelem_create
(SEL_CONST
);
369 _gmx_selelem_set_vtype
($$
, INT_VALUE
);
370 _gmx_selvalue_reserve
(&$$
->v
, 1);
375 $$
= _gmx_selelem_create
(SEL_CONST
);
376 _gmx_selelem_set_vtype
($$
, REAL_VALUE
);
377 _gmx_selvalue_reserve
(&$$
->v
, 1);
382 /* Numeric selection methods */
383 num_expr: pos_mod KEYWORD_NUMERIC
385 $$
= _gmx_sel_init_keyword
($2, NULL
, $1, scanner
);
386 if
($$
== NULL
) YYERROR;
388 | pos_mod METHOD_NUMERIC method_params
390 $$
= _gmx_sel_init_method
($2, $3, $1, scanner
);
391 if
($$
== NULL
) YYERROR;
395 /* Arithmetic evaluation and grouping */
396 num_expr: num_expr
'+' num_expr
397 { $$
= _gmx_sel_init_arithmetic
($1, $3, '+', scanner
); }
398 | num_expr
'-' num_expr
399 { $$
= _gmx_sel_init_arithmetic
($1, $3, '-', scanner
); }
400 | num_expr
'*' num_expr
401 { $$
= _gmx_sel_init_arithmetic
($1, $3, '*', scanner
); }
402 | num_expr
'/' num_expr
403 { $$
= _gmx_sel_init_arithmetic
($1, $3, '/', scanner
); }
404 |
'-' num_expr %prec UNARY_NEG
405 { $$
= _gmx_sel_init_arithmetic
($2, NULL
, '-', scanner
); }
406 | num_expr
'^' num_expr
407 { $$
= _gmx_sel_init_arithmetic
($1, $3, '^', scanner
); }
408 |
'(' num_expr
')' { $$
= $2; }
411 /********************************************************************
413 ********************************************************************/
417 $$
= _gmx_selelem_create
(SEL_CONST
);
418 _gmx_selelem_set_vtype
($$
, STR_VALUE
);
419 _gmx_selvalue_reserve
(&$$
->v
, 1);
422 | pos_mod KEYWORD_STR
424 $$
= _gmx_sel_init_keyword
($2, NULL
, $1, scanner
);
425 if
($$
== NULL
) YYERROR;
429 /********************************************************************
430 * POSITION EXPRESSIONS
431 ********************************************************************/
433 /* Constant position expressions */
434 pos_expr: '(' number
',' number
',' number
')'
435 { $$
= _gmx_sel_init_const_position
($2, $4, $6); }
438 /* Grouping of position expressions */
439 pos_expr: '(' pos_expr
')' { $$
= $2; }
442 /* Expressions with a position value */
443 pos_expr: METHOD_POS method_params
445 $$
= _gmx_sel_init_method
($1, $2, NULL
, scanner
);
446 if
($$
== NULL
) YYERROR;
450 /* Evaluation of positions using a keyword */
451 pos_expr: KEYWORD_POS OF sel_expr %prec PARAM_REDUCT
453 $$
= _gmx_sel_init_position
($3, $1, scanner
);
454 if
($$
== NULL
) YYERROR;
458 /********************************************************************
460 ********************************************************************/
462 sel_expr: VARIABLE_GROUP
463 { $$
= _gmx_sel_init_variable_ref
($1); }
466 num_expr: VARIABLE_NUMERIC
467 { $$
= _gmx_sel_init_variable_ref
($1); }
470 pos_expr: VARIABLE_POS
471 { $$
= _gmx_sel_init_variable_ref
($1); }
474 /********************************************************************
476 ********************************************************************/
480 { $$
= process_param_list
($1); }
481 | method_param_list END_OF_METHOD
482 { $$
= process_param_list
($1); }
486 /* empty */ { $$
= NULL
; }
487 | method_param_list method_param
488 { $2->next
= $1; $$
= $2; }
494 $$
= _gmx_selexpr_create_param
($1);
495 $$
->value
= process_value_list
($2, &$$
->nval
);
499 value_list: /* empty */ { $$
= NULL
; }
500 | value_list_nonempty
{ $$
= $1; }
504 value_item
{ $$
= $1; }
505 | value_list_nonempty value_item
506 { $2->next
= $1; $$
= $2; }
507 | value_list_nonempty
',' value_item
508 { $3->next
= $1; $$
= $3; }
511 value_item: sel_expr %prec PARAM_REDUCT
512 { $$
= _gmx_selexpr_create_value_expr
($1); }
513 | pos_expr %prec PARAM_REDUCT
514 { $$
= _gmx_selexpr_create_value_expr
($1); }
515 | num_expr %prec PARAM_REDUCT
516 { $$
= _gmx_selexpr_create_value_expr
($1); }
517 | str_expr %prec PARAM_REDUCT
518 { $$
= _gmx_selexpr_create_value_expr
($1); }
521 $$
= _gmx_selexpr_create_value
(INT_VALUE
);
522 $$
->u.i.i1
= $1; $$
->u.i.i2
= $3;
524 | TOK_INT TO TOK_REAL
526 $$
= _gmx_selexpr_create_value
(REAL_VALUE
);
527 $$
->u.r.r1
= $1; $$
->u.r.r2
= $3;
531 $$
= _gmx_selexpr_create_value
(REAL_VALUE
);
532 $$
->u.r.r1
= $1; $$
->u.r.r2
= $3;
538 static t_selexpr_value
*
539 process_value_list
(t_selexpr_value
*values
, int *nr
)
541 t_selexpr_value
*val
, *pval
, *nval
;
543 /* Count values (if needed) and reverse list */
566 static t_selexpr_param
*
567 process_param_list
(t_selexpr_param
*params
)
569 t_selexpr_param
*par
, *ppar
, *npar
;
587 yyerror(yyscan_t scanner
, char const *s
)
589 _gmx_selparser_error
("%s", s
);