2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2009, The GROMACS development team,
6 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012,2013, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
39 * \brief Implementation of functions in symrec.h.
49 #include <gmx_fatal.h>
57 * Symbol table for the selection parser.
59 struct gmx_sel_symtab_t
61 /** Pointer to the first symbol in the linked list of symbols. */
62 gmx_sel_symrec_t *first;
66 * Single symbol for the selection parser.
68 struct gmx_sel_symrec_t
70 /** Name of the symbol. */
72 /** Type of the symbol. */
74 /** Value of the symbol. */
76 /** Pointer to the method structure (\ref SYMBOL_METHOD). */
77 struct gmx_ana_selmethod_t *meth;
78 /** Pointer to the variable value (\ref SYMBOL_VARIABLE). */
79 struct t_selelem *var;
81 /** Pointer to the next symbol. */
82 struct gmx_sel_symrec_t *next;
85 /** List of reserved symbols to register in add_reserved_symbols(). */
86 static const char *const sym_reserved[] = {
101 * \param[in] sym Symbol to query.
102 * \returns The name of \p sym.
104 * The returned pointer should not be free'd.
107 _gmx_sel_sym_name(gmx_sel_symrec_t *sym)
113 * \param[in] sym Symbol to query.
114 * \returns The type of \p sym.
117 _gmx_sel_sym_type(gmx_sel_symrec_t *sym)
123 * \param[in] sym Symbol to query.
124 * \returns The method associated with \p sym, or NULL if \p sym is not a
125 * \ref SYMBOL_METHOD symbol.
127 struct gmx_ana_selmethod_t *
128 _gmx_sel_sym_value_method(gmx_sel_symrec_t *sym)
130 if (sym->type != SYMBOL_METHOD)
132 gmx_call("symbol is not a method symbol");
139 * \param[in] sym Symbol to query.
140 * \returns The variable expression associated with \p sym, or NULL if
141 * \p sym is not a \ref SYMBOL_VARIABLE symbol.
144 _gmx_sel_sym_value_var(gmx_sel_symrec_t *sym)
146 if (sym->type != SYMBOL_VARIABLE)
148 gmx_call("symbol is not a variable symbol");
155 * Adds the reserved symbols to a symbol table.
157 * \param[in,out] tab Symbol table to which the symbols are added.
159 * Assumes that the symbol table is empty.
162 add_reserved_symbols(gmx_sel_symtab_t *tab)
164 gmx_sel_symrec_t *sym;
165 gmx_sel_symrec_t *last;
169 for (i = 0; i < asize(sym_reserved); ++i)
172 sym->name = strdup(sym_reserved[i]);
173 sym->type = SYMBOL_RESERVED;
188 * Adds the position symbols to the symbol list.
190 * \param[in,out] tab Symbol table to which the symbols are added.
193 add_position_symbols(gmx_sel_symtab_t *tab)
195 const char **postypes;
196 gmx_sel_symrec_t *sym;
197 gmx_sel_symrec_t *last;
200 postypes = gmx_ana_poscalc_create_type_enum(TRUE);
202 while (last && last->next)
206 for (i = 1; postypes[i] != NULL; ++i)
209 sym->name = strdup(postypes[i]);
210 sym->type = SYMBOL_POS;
226 * \param[out] tabp Symbol table pointer to initialize.
228 * Reserved and position symbols are added to the created table.
231 _gmx_sel_symtab_create(gmx_sel_symtab_t **tabp)
233 gmx_sel_symtab_t *tab;
236 add_reserved_symbols(tab);
237 add_position_symbols(tab);
243 * \param[in] tab Symbol table to free.
245 * The pointer \p tab is invalid after the call.
248 _gmx_sel_symtab_free(gmx_sel_symtab_t *tab)
250 gmx_sel_symrec_t *sym;
255 tab->first = sym->next;
256 if (sym->type == SYMBOL_VARIABLE)
258 _gmx_selelem_free(sym->u.var);
267 * \param[in] tab Symbol table to search.
268 * \param[in] name Symbol name to find.
269 * \param[in] bExact If FALSE, symbols that begin with \p name are also
271 * \returns Pointer to the symbol with name \p name, or NULL if not found.
273 * If no exact match is found and \p bExact is FALSE, returns a symbol that
274 * begins with \p name if a unique matching symbol is found.
277 _gmx_sel_find_symbol(gmx_sel_symtab_t *tab, const char *name, gmx_bool bExact)
279 return _gmx_sel_find_symbol_len(tab, name, strlen(name), bExact);
283 * \param[in] tab Symbol table to search.
284 * \param[in] name Symbol name to find.
285 * \param[in] len Only consider the first \p len characters of \p name.
286 * \param[in] bExact If FALSE, symbols that begin with \p name are also
288 * \returns Pointer to the symbol with name \p name, or NULL if not found.
290 * If no exact match is found and \p bExact is FALSE, returns a symbol that
291 * begins with \p name if a unique matching symbol is found.
293 * The parameter \p len is there to allow using this function from scanner.l
294 * without modifying the text to be scanned or copying it.
297 _gmx_sel_find_symbol_len(gmx_sel_symtab_t *tab, const char *name, size_t len,
300 gmx_sel_symrec_t *sym;
301 gmx_sel_symrec_t *match;
311 if (!strncmp(sym->name, name, len))
313 if (strlen(sym->name) == len)
322 if (sym->type == SYMBOL_METHOD)
336 fprintf(stderr, "parse error: ambiguous symbol\n");
343 * \param[in] tab Symbol table to search.
344 * \param[in] type Type of symbol to find.
345 * \returns The first symbol in \p tab with type \p type,
346 * or NULL if there are no such symbols.
349 _gmx_sel_first_symbol(gmx_sel_symtab_t *tab, e_symbol_t type)
351 gmx_sel_symrec_t *sym;
356 if (sym->type == type)
366 * \param[in] after Start the search after this symbol.
367 * \param[in] type Type of symbol to find.
368 * \returns The next symbol after \p after with type \p type,
369 * or NULL if there are no more symbols.
372 _gmx_sel_next_symbol(gmx_sel_symrec_t *after, e_symbol_t type)
374 gmx_sel_symrec_t *sym;
379 if (sym->type == type)
389 * Internal utility function used in adding symbols to a symbol table.
391 * \param[in,out] tab Symbol table to add the symbol to.
392 * \param[in] name Name of the symbol to add.
393 * \param[out] ctype On error, the type of the conflicting symbol is
394 * written to \p *ctype.
395 * \returns Pointer to the new symbol record, or NULL if \p name
396 * conflicts with an existing symbol.
398 static gmx_sel_symrec_t *
399 add_symbol(gmx_sel_symtab_t *tab, const char *name, e_symbol_t *ctype)
401 gmx_sel_symrec_t *sym, *psym;
404 /* Check if there is a conflicting symbol */
409 if (!gmx_strcasecmp(sym->name, name))
418 /* Create a new symbol record */
429 sym->name = strdup(name);
434 * \param[in,out] tab Symbol table to add the symbol to.
435 * \param[in] name Name of the new symbol.
436 * \param[in] sel Value of the variable.
437 * \returns Pointer to the created symbol record, or NULL if there was a
438 * symbol with the same name.
441 _gmx_sel_add_var_symbol(gmx_sel_symtab_t *tab, const char *name,
442 struct t_selelem *sel)
444 gmx_sel_symrec_t *sym;
447 sym = add_symbol(tab, name, &ctype);
450 fprintf(stderr, "parse error: ");
453 case SYMBOL_RESERVED:
455 fprintf(stderr, "variable name (%s) conflicts with a reserved keyword\n",
458 case SYMBOL_VARIABLE:
459 fprintf(stderr, "duplicate variable name (%s)\n", name);
462 fprintf(stderr, "variable name (%s) conflicts with a selection keyword\n",
469 sym->type = SYMBOL_VARIABLE;
476 * \param[in,out] tab Symbol table to add the symbol to.
477 * \param[in] name Name of the new symbol.
478 * \param[in] method Method that this symbol represents.
479 * \returns Pointer to the created symbol record, or NULL if there was a
480 * symbol with the same name.
483 _gmx_sel_add_method_symbol(gmx_sel_symtab_t *tab, const char *name,
484 struct gmx_ana_selmethod_t *method)
486 gmx_sel_symrec_t *sym;
489 sym = add_symbol(tab, name, &ctype);
492 fprintf(stderr, "parse error: ");
495 case SYMBOL_RESERVED:
497 fprintf(stderr, "method name (%s) conflicts with a reserved keyword\n",
500 case SYMBOL_VARIABLE:
501 fprintf(stderr, "method name (%s) conflicts with a variable name\n",
505 fprintf(stderr, "duplicate method name (%s)\n", name);
511 sym->type = SYMBOL_METHOD;
512 sym->u.meth = method;