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
33 * Implements functions in symrec.h.
35 * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36 * \ingroup module_selection
46 #include <gmx_fatal.h>
48 #include "gromacs/selection/poscalc.h"
54 * Symbol table for the selection parser.
56 struct gmx_sel_symtab_t
58 /** Pointer to the first symbol in the linked list of symbols. */
59 gmx_sel_symrec_t *first;
63 * Single symbol for the selection parser.
65 struct gmx_sel_symrec_t
67 /** Name of the symbol. */
69 /** Type of the symbol. */
71 /** Value of the symbol. */
73 /** Pointer to the method structure (\ref SYMBOL_METHOD). */
74 struct gmx_ana_selmethod_t *meth;
75 /** Pointer to the variable value (\ref SYMBOL_VARIABLE). */
76 struct t_selelem *var;
78 /** Pointer to the next symbol. */
79 struct gmx_sel_symrec_t *next;
82 /** List of reserved symbols to register in add_reserved_symbols(). */
83 static const char *const sym_reserved[] = {
98 * \param[in] sym Symbol to query.
99 * \returns The name of \p sym.
101 * The returned pointer should not be free'd.
104 _gmx_sel_sym_name(gmx_sel_symrec_t *sym)
110 * \param[in] sym Symbol to query.
111 * \returns The type of \p sym.
114 _gmx_sel_sym_type(gmx_sel_symrec_t *sym)
120 * \param[in] sym Symbol to query.
121 * \returns The method associated with \p sym, or NULL if \p sym is not a
122 * \ref SYMBOL_METHOD symbol.
124 struct gmx_ana_selmethod_t *
125 _gmx_sel_sym_value_method(gmx_sel_symrec_t *sym)
127 if (sym->type != SYMBOL_METHOD)
129 gmx_call("symbol is not a method symbol");
136 * \param[in] sym Symbol to query.
137 * \returns The variable expression associated with \p sym, or NULL if
138 * \p sym is not a \ref SYMBOL_VARIABLE symbol.
141 _gmx_sel_sym_value_var(gmx_sel_symrec_t *sym)
143 if (sym->type != SYMBOL_VARIABLE)
145 gmx_call("symbol is not a variable symbol");
152 * Adds the reserved symbols to a symbol table.
154 * \param[in,out] tab Symbol table to which the symbols are added.
156 * Assumes that the symbol table is empty.
159 add_reserved_symbols(gmx_sel_symtab_t *tab)
161 gmx_sel_symrec_t *sym;
162 gmx_sel_symrec_t *last;
166 for (i = 0; i < asize(sym_reserved); ++i)
169 sym->name = strdup(sym_reserved[i]);
170 sym->type = SYMBOL_RESERVED;
185 * Adds the position symbols to the symbol list.
187 * \param[in,out] tab Symbol table to which the symbols are added.
190 add_position_symbols(gmx_sel_symtab_t *tab)
192 const char **postypes;
193 gmx_sel_symrec_t *sym;
194 gmx_sel_symrec_t *last;
197 postypes = gmx_ana_poscalc_create_type_enum(TRUE);
199 while (last && last->next)
203 for (i = 1; postypes[i] != NULL; ++i)
206 sym->name = strdup(postypes[i]);
207 sym->type = SYMBOL_POS;
223 * \param[out] tabp Symbol table pointer to initialize.
225 * Reserved and position symbols are added to the created table.
228 _gmx_sel_symtab_create(gmx_sel_symtab_t **tabp)
230 gmx_sel_symtab_t *tab;
233 add_reserved_symbols(tab);
234 add_position_symbols(tab);
240 * \param[in] tab Symbol table to free.
242 * The pointer \p tab is invalid after the call.
245 _gmx_sel_symtab_free(gmx_sel_symtab_t *tab)
247 gmx_sel_symrec_t *sym;
252 tab->first = sym->next;
253 if (sym->type == SYMBOL_VARIABLE)
255 _gmx_selelem_free(sym->u.var);
264 * \param[in] tab Symbol table to search.
265 * \param[in] name Symbol name to find.
266 * \param[in] bExact If FALSE, symbols that begin with \p name are also
268 * \returns Pointer to the symbol with name \p name, or NULL if not found.
270 * If no exact match is found and \p bExact is FALSE, returns a symbol that
271 * begins with \p name if a unique matching symbol is found.
274 _gmx_sel_find_symbol(gmx_sel_symtab_t *tab, const char *name, gmx_bool bExact)
276 return _gmx_sel_find_symbol_len(tab, name, strlen(name), bExact);
280 * \param[in] tab Symbol table to search.
281 * \param[in] name Symbol name to find.
282 * \param[in] len Only consider the first \p len characters of \p name.
283 * \param[in] bExact If FALSE, symbols that begin with \p name are also
285 * \returns Pointer to the symbol with name \p name, or NULL if not found.
287 * If no exact match is found and \p bExact is FALSE, returns a symbol that
288 * begins with \p name if a unique matching symbol is found.
290 * The parameter \p len is there to allow using this function from scanner.l
291 * without modifying the text to be scanned or copying it.
294 _gmx_sel_find_symbol_len(gmx_sel_symtab_t *tab, const char *name, size_t len,
297 gmx_sel_symrec_t *sym;
298 gmx_sel_symrec_t *match;
308 if (!strncmp(sym->name, name, len))
310 if (strlen(sym->name) == len)
319 if (sym->type == SYMBOL_METHOD)
333 fprintf(stderr, "parse error: ambiguous symbol\n");
340 * \param[in] tab Symbol table to search.
341 * \param[in] type Type of symbol to find.
342 * \returns The first symbol in \p tab with type \p type,
343 * or NULL if there are no such symbols.
346 _gmx_sel_first_symbol(gmx_sel_symtab_t *tab, e_symbol_t type)
348 gmx_sel_symrec_t *sym;
353 if (sym->type == type)
363 * \param[in] after Start the search after this symbol.
364 * \param[in] type Type of symbol to find.
365 * \returns The next symbol after \p after with type \p type,
366 * or NULL if there are no more symbols.
369 _gmx_sel_next_symbol(gmx_sel_symrec_t *after, e_symbol_t type)
371 gmx_sel_symrec_t *sym;
376 if (sym->type == type)
386 * Internal utility function used in adding symbols to a symbol table.
388 * \param[in,out] tab Symbol table to add the symbol to.
389 * \param[in] name Name of the symbol to add.
390 * \param[out] ctype On error, the type of the conflicting symbol is
391 * written to \p *ctype.
392 * \returns Pointer to the new symbol record, or NULL if \p name
393 * conflicts with an existing symbol.
395 static gmx_sel_symrec_t *
396 add_symbol(gmx_sel_symtab_t *tab, const char *name, e_symbol_t *ctype)
398 gmx_sel_symrec_t *sym, *psym;
401 /* Check if there is a conflicting symbol */
406 if (!gmx_strcasecmp(sym->name, name))
415 /* Create a new symbol record */
426 sym->name = strdup(name);
431 * \param[in,out] tab Symbol table to add the symbol to.
432 * \param[in] name Name of the new symbol.
433 * \param[in] sel Value of the variable.
434 * \returns Pointer to the created symbol record, or NULL if there was a
435 * symbol with the same name.
438 _gmx_sel_add_var_symbol(gmx_sel_symtab_t *tab, const char *name,
439 struct t_selelem *sel)
441 gmx_sel_symrec_t *sym;
444 sym = add_symbol(tab, name, &ctype);
447 fprintf(stderr, "parse error: ");
450 case SYMBOL_RESERVED:
452 fprintf(stderr, "variable name (%s) conflicts with a reserved keyword\n",
455 case SYMBOL_VARIABLE:
456 fprintf(stderr, "duplicate variable name (%s)\n", name);
459 fprintf(stderr, "variable name (%s) conflicts with a selection keyword\n",
466 sym->type = SYMBOL_VARIABLE;
473 * \param[in,out] tab Symbol table to add the symbol to.
474 * \param[in] name Name of the new symbol.
475 * \param[in] method Method that this symbol represents.
476 * \returns Pointer to the created symbol record, or NULL if there was a
477 * symbol with the same name.
480 _gmx_sel_add_method_symbol(gmx_sel_symtab_t *tab, const char *name,
481 struct gmx_ana_selmethod_t *method)
483 gmx_sel_symrec_t *sym;
486 sym = add_symbol(tab, name, &ctype);
489 fprintf(stderr, "parse error: ");
492 case SYMBOL_RESERVED:
494 fprintf(stderr, "method name (%s) conflicts with a reserved keyword\n",
497 case SYMBOL_VARIABLE:
498 fprintf(stderr, "method name (%s) conflicts with a variable name\n",
502 fprintf(stderr, "duplicate method name (%s)\n", name);
508 sym->type = SYMBOL_METHOD;
509 sym->u.meth = method;