A bit more modular selection position handling.
[gromacs/qmmm-gamess-us.git] / src / gmxlib / selection / parser.y
blob5bc9629961d8793711494383413abee9bc68be1b
1 /*
3 * This source code is part of
5 * G R O M A C S
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
31 /*! \internal \file
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.
41 #ifdef HAVE_CONFIG_H
42 #include <config.h>
43 #endif
45 #include <string2.h>
47 #include "parsetree.h"
48 #include "selelem.h"
50 #include "scanner.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);
57 static void
58 yyerror(yyscan_t, char const *s);
61 %union{
62 int i;
63 real r;
64 char *str;
65 struct gmx_ana_selmethod_t *meth;
67 struct t_selelem *sel;
69 struct t_selexpr_value *val;
70 struct t_selexpr_param *param;
73 /* Invalid token to report lexer errors */
74 %token INVALID
76 /* Tokens for help requests */
77 %token HELP
78 %token <str> HELP_TOPIC
80 /* Simple input tokens */
81 %token <i> INTEGER
82 %token <r> REAL
83 %token <str> STR
84 %token <str> IDENTIFIER
85 %token CMD_SEP
87 /* Simple keyword tokens */
88 %token GROUP
89 %token TO
91 /* Variable tokens */
92 %token <sel> VARIABLE_NUMERIC
93 %token <sel> VARIABLE_GROUP
94 %token <sel> VARIABLE_POS
96 /* Selection method tokens */
97 %token <meth> KEYWORD_NUMERIC
98 %token <meth> KEYWORD_STR
99 %token <str> KEYWORD_POS
100 %token <meth> KEYWORD_GROUP
101 %token <meth> METHOD_NUMERIC
102 %token <meth> METHOD_GROUP
103 %token <meth> METHOD_POS
104 %token <meth> MODIFIER
106 %token <str> PARAM_BASIC
107 %token <str> PARAM_EXPR
108 %token END_OF_METHOD
110 /* Simple tokens with precedence */
111 %nonassoc OF
112 /* A dummy token that determines the precedence of parameter reduction */
113 %nonassoc PARAM_REDUCT
115 /* Operator tokens */
116 %left AND OR XOR
117 %left NOT
118 %nonassoc <str> CMP_OP
120 /* Simple non-terminals */
121 %type <r> number
122 %type <str> string
123 %type <str> pos_mod
125 /* Expression non-terminals */
126 %type <sel> commands command cmd_plain
127 %type <sel> selection
128 %type <sel> sel_expr
129 %type <sel> num_expr
130 %type <sel> pos_expr
132 /* Parameter/value non-terminals */
133 %type <param> method_params method_param_list method_param
134 %type <val> value_list value_list_nonempty value_item
136 %destructor { free($$); } HELP_TOPIC STR IDENTIFIER string
137 %destructor { if($$) free($$); } PARAM_BASIC PARAM_EXPR
138 %destructor { if($$) _gmx_selelem_free($$); } command cmd_plain
139 %destructor { _gmx_selelem_free_chain($$); } selection
140 %destructor { _gmx_selelem_free($$); } sel_expr num_expr
141 %destructor { _gmx_selelem_free($$); } pos_expr
142 %destructor { _gmx_selexpr_free_params($$); } method_params method_param_list method_param
143 %destructor { _gmx_selexpr_free_values($$); } value_list value_list_nonempty value_item
145 %expect 5
146 %debug
147 %pure-parser
149 /* If you change these, you also need to update the prototype in parsetree.c. */
150 %name-prefix="_gmx_sel_yy"
151 %parse-param { yyscan_t scanner }
152 %lex-param { yyscan_t scanner }
156 /* The start rule: allow one or more commands */
157 commands: /* empty */ { $$ = NULL }
158 | commands command
160 $$ = _gmx_sel_append_selection($2, $1, scanner);
161 if (_gmx_sel_parser_should_finish(scanner))
162 YYACCEPT;
166 /* A command is formed from an actual command and a separator */
167 command: cmd_plain CMD_SEP { $$ = $1; }
168 | error CMD_SEP
170 $$ = NULL;
171 _gmx_selparser_error("invalid selection '%s'",
172 _gmx_sel_lexer_pselstr(scanner));
173 if (_gmx_sel_is_lexer_interactive(scanner))
175 _gmx_sel_lexer_clear_pselstr(scanner);
176 yyerrok;
178 else
180 YYABORT;
185 /* Commands can be selections or variable assignments */
186 cmd_plain: /* empty */
188 $$ = NULL;
189 _gmx_sel_handle_empty_cmd(scanner);
191 | help_request { $$ = NULL; }
192 | INTEGER
194 t_selelem *s, *p;
195 s = _gmx_sel_init_group_by_id($1, scanner);
196 if (s == NULL) YYERROR;
197 p = _gmx_sel_init_position(s, NULL, scanner);
198 if (p == NULL) YYERROR;
199 $$ = _gmx_sel_init_selection(strdup(s->name), p, scanner);
201 | string
203 t_selelem *s, *p;
204 s = _gmx_sel_init_group_by_name($1, scanner);
205 free($1);
206 if (s == NULL) YYERROR;
207 p = _gmx_sel_init_position(s, NULL, scanner);
208 if (p == NULL) YYERROR;
209 $$ = _gmx_sel_init_selection(strdup(s->name), p, scanner);
211 | selection
212 { $$ = _gmx_sel_init_selection(NULL, $1, scanner); }
213 | string selection
214 { $$ = _gmx_sel_init_selection($1, $2, scanner); }
215 | IDENTIFIER '=' sel_expr
216 { $$ = _gmx_sel_assign_variable($1, $3, scanner); }
217 | IDENTIFIER '=' num_expr
218 { $$ = _gmx_sel_assign_variable($1, $3, scanner); }
219 | IDENTIFIER '=' pos_expr
220 { $$ = _gmx_sel_assign_variable($1, $3, scanner); }
223 /* Help requests */
224 help_request:
225 HELP { _gmx_sel_handle_help_cmd(NULL, scanner); }
226 | help_topic
229 help_topic: HELP HELP_TOPIC { _gmx_sel_handle_help_cmd($2, scanner); }
230 | help_topic HELP_TOPIC { _gmx_sel_handle_help_cmd($2, scanner); }
233 /* Selection is made of an expression and zero or more modifiers */
234 selection: pos_expr { $$ = $1; }
235 | sel_expr
237 $$ = _gmx_sel_init_position($1, NULL, scanner);
238 if ($$ == NULL) YYERROR;
240 | '(' selection ')' { $$ = $2; }
241 | selection MODIFIER method_params
243 $$ = _gmx_sel_init_modifier($2, process_param_list($3), $1, scanner);
244 _gmx_sel_finish_method(scanner);
248 /********************************************************************
249 * BASIC NON-TERMINAL SYMBOLS
250 ********************************************************************/
252 number: INTEGER { $$ = $1; }
253 | REAL { $$ = $1; }
256 string: STR { $$ = $1; }
257 | IDENTIFIER { $$ = $1; }
260 /********************************************************************
261 * ATOM SELECTION EXPRESSIONS
262 ********************************************************************/
264 /* Boolean expressions and grouping */
265 sel_expr: NOT sel_expr
267 $$ = _gmx_selelem_create(SEL_BOOLEAN);
268 $$->u.boolt = BOOL_NOT;
269 $$->child = $2;
271 | sel_expr AND sel_expr
273 $$ = _gmx_selelem_create(SEL_BOOLEAN);
274 $$->u.boolt = BOOL_AND;
275 $$->child = $1; $$->child->next = $3;
277 | sel_expr OR sel_expr
279 $$ = _gmx_selelem_create(SEL_BOOLEAN);
280 $$->u.boolt = BOOL_OR;
281 $$->child = $1; $$->child->next = $3;
283 /* | sel_expr XOR sel_expr
285 $$ = _gmx_selelem_create(SEL_BOOLEAN);
286 $$->u.boolt = BOOL_XOR;
287 $$->child = $1; $$->child->next = $3;
289 | '(' sel_expr ')' { $$ = $2; }
292 /* Numeric comparisons */
293 sel_expr: num_expr CMP_OP num_expr
295 $$ = _gmx_sel_init_comparison($1, $3, $2, scanner);
296 if ($$ == NULL) YYERROR;
300 /* External groups */
301 sel_expr: GROUP string
303 $$ = _gmx_sel_init_group_by_name($2, scanner);
304 free($2);
305 if ($$ == NULL) YYERROR;
307 | GROUP INTEGER
309 $$ = _gmx_sel_init_group_by_id($2, scanner);
310 if ($$ == NULL) YYERROR;
314 /* Position modifiers for selection methods */
315 pos_mod: /* empty */ { $$ = NULL; }
316 | KEYWORD_POS { $$ = $1; }
319 /* Keyword selections */
320 sel_expr: pos_mod KEYWORD_GROUP
322 $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
323 if ($$ == NULL) YYERROR;
325 | pos_mod KEYWORD_STR value_list_nonempty
327 $$ = _gmx_sel_init_keyword($2, process_value_list($3, NULL), $1, scanner);
328 if ($$ == NULL) YYERROR;
330 | pos_mod KEYWORD_NUMERIC value_list_nonempty
332 $$ = _gmx_sel_init_keyword($2, process_value_list($3, NULL), $1, scanner);
333 if ($$ == NULL) YYERROR;
337 /* Custom selection methods */
338 sel_expr: pos_mod METHOD_GROUP method_params
340 $$ = _gmx_sel_init_method($2, process_param_list($3), $1, scanner);
341 if ($$ == NULL) YYERROR;
342 _gmx_sel_finish_method(scanner);
346 /********************************************************************
347 * NUMERICAL EXPRESSIONS
348 ********************************************************************/
350 /* Basic numerical values */
351 num_expr: INTEGER
353 $$ = _gmx_selelem_create(SEL_CONST);
354 _gmx_selelem_set_vtype($$, INT_VALUE);
355 _gmx_selvalue_reserve(&$$->v, 1);
356 $$->v.u.i[0] = $1;
358 | REAL
360 $$ = _gmx_selelem_create(SEL_CONST);
361 _gmx_selelem_set_vtype($$, REAL_VALUE);
362 _gmx_selvalue_reserve(&$$->v, 1);
363 $$->v.u.r[0] = $1;
367 /* Numeric selection methods */
368 num_expr: pos_mod KEYWORD_NUMERIC
370 $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
371 if ($$ == NULL) YYERROR;
373 | pos_mod METHOD_NUMERIC method_params
375 $$ = _gmx_sel_init_method($2, process_param_list($3), $1, scanner);
376 if ($$ == NULL) YYERROR;
377 _gmx_sel_finish_method(scanner);
381 /* Grouping of numeric expressions */
382 num_expr: '(' num_expr ')' { $$ = $2; }
385 /********************************************************************
386 * POSITION EXPRESSIONS
387 ********************************************************************/
389 /* Constant position expressions */
390 pos_expr: '(' number ',' number ',' number ')'
391 { $$ = _gmx_sel_init_const_position($2, $4, $6); }
394 /* Grouping of position expressions */
395 pos_expr: '(' pos_expr ')' { $$ = $2; }
398 /* Expressions with a position value */
399 pos_expr: METHOD_POS method_params
401 $$ = _gmx_sel_init_method($1, process_param_list($2), NULL, scanner);
402 if ($$ == NULL) YYERROR;
403 _gmx_sel_finish_method(scanner);
407 /* Evaluation of positions using a keyword */
408 pos_expr: KEYWORD_POS OF sel_expr
410 $$ = _gmx_sel_init_position($3, $1, scanner);
411 if ($$ == NULL) YYERROR;
415 /********************************************************************
416 * VARIABLES
417 ********************************************************************/
419 sel_expr: VARIABLE_GROUP
420 { $$ = _gmx_sel_init_variable_ref($1); }
423 num_expr: VARIABLE_NUMERIC
424 { $$ = _gmx_sel_init_variable_ref($1); }
427 pos_expr: VARIABLE_POS
428 { $$ = _gmx_sel_init_variable_ref($1); }
431 /********************************************************************
432 * METHOD PARAMETERS
433 ********************************************************************/
435 method_params:
436 method_param_list { $$ = $1; }
437 | method_param_list END_OF_METHOD { $$ = $1; }
440 method_param_list:
441 /* empty */ { $$ = NULL; }
442 | method_param_list method_param
443 { $2->next = $1; $$ = $2; }
446 method_param:
447 PARAM_BASIC value_list
449 $$ = _gmx_selexpr_create_param($1);
450 $$->value = process_value_list($2, &$$->nval);
452 | PARAM_EXPR pos_expr %prec PARAM_REDUCT
454 $$ = _gmx_selexpr_create_param($1);
455 $$->nval = 1;
456 $$->value = _gmx_selexpr_create_value_expr($2);
458 | PARAM_EXPR sel_expr %prec PARAM_REDUCT
460 $$ = _gmx_selexpr_create_param($1);
461 $$->nval = 1;
462 $$->value = _gmx_selexpr_create_value_expr($2);
466 value_list: /* empty */ { $$ = NULL; }
467 | value_list_nonempty { $$ = $1; }
470 value_list_nonempty:
471 value_item { $$ = $1; }
472 | value_list_nonempty value_item { $2->next = $1; $$ = $2; }
475 value_item: INTEGER
477 $$ = _gmx_selexpr_create_value(INT_VALUE);
478 $$->u.i.i1 = $$->u.i.i2 = $1;
480 | REAL
482 $$ = _gmx_selexpr_create_value(REAL_VALUE);
483 $$->u.r.r1 = $$->u.r.r2 = $1;
485 | INTEGER TO INTEGER
487 $$ = _gmx_selexpr_create_value(INT_VALUE);
488 $$->u.i.i1 = $1; $$->u.i.i2 = $3;
490 | INTEGER TO REAL
492 $$ = _gmx_selexpr_create_value(REAL_VALUE);
493 $$->u.r.r1 = $1; $$->u.r.r2 = $3;
495 | REAL TO number
497 $$ = _gmx_selexpr_create_value(REAL_VALUE);
498 $$->u.r.r1 = $1; $$->u.r.r2 = $3;
500 | string
502 $$ = _gmx_selexpr_create_value(STR_VALUE);
503 $$->u.s = $1;
509 static t_selexpr_value *
510 process_value_list(t_selexpr_value *values, int *nr)
512 t_selexpr_value *val, *pval, *nval;
514 /* Count values (if needed) and reverse list */
515 if (nr)
517 *nr = 0;
519 pval = NULL;
520 val = values;
521 while (val)
523 if (nr)
525 ++*nr;
527 nval = val->next;
528 val->next = pval;
529 pval = val;
530 val = nval;
532 values = pval;
534 return values;
537 static t_selexpr_param *
538 process_param_list(t_selexpr_param *params)
540 t_selexpr_param *par, *ppar, *npar;
542 /* Reverse list */
543 ppar = NULL;
544 par = params;
545 while (par)
547 npar = par->next;
548 par->next = ppar;
549 ppar = par;
550 par = npar;
552 params = ppar;
554 return params;
557 static void
558 yyerror(yyscan_t scanner, char const *s)
560 _gmx_selparser_error("%s", s);