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 Implementation of functions in symrec.h.
42 #include <gmx_fatal.h>
50 * Symbol table for the selection parser.
52 struct gmx_sel_symtab_t
54 /** Pointer to the first symbol in the linked list of symbols. */
55 gmx_sel_symrec_t
*first
;
59 * Single symbol for the selection parser.
61 struct gmx_sel_symrec_t
63 /** Name of the symbol. */
65 /** Type of the symbol. */
67 /** Value of the symbol. */
69 /** Pointer to the method structure (\ref SYMBOL_METHOD). */
70 struct gmx_ana_selmethod_t
*meth
;
71 /** Pointer to the variable value (\ref SYMBOL_VARIABLE). */
72 struct t_selelem
*var
;
74 /** Pointer to the next symbol. */
75 struct gmx_sel_symrec_t
*next
;
78 /** List of reserved symbols to register in add_reserved_symbols(). */
79 static const char *const sym_reserved
[] = {
94 * \param[in] sym Symbol to query.
95 * \returns The name of \p sym.
97 * The returned pointer should not be free'd.
100 _gmx_sel_sym_name(gmx_sel_symrec_t
*sym
)
106 * \param[in] sym Symbol to query.
107 * \returns The type of \p sym.
110 _gmx_sel_sym_type(gmx_sel_symrec_t
*sym
)
116 * \param[in] sym Symbol to query.
117 * \returns The method associated with \p sym, or NULL if \p sym is not a
118 * \ref SYMBOL_METHOD symbol.
120 struct gmx_ana_selmethod_t
*
121 _gmx_sel_sym_value_method(gmx_sel_symrec_t
*sym
)
123 if (sym
->type
!= SYMBOL_METHOD
)
125 gmx_call("symbol is not a method symbol");
132 * \param[in] sym Symbol to query.
133 * \returns The variable expression associated with \p sym, or NULL if
134 * \p sym is not a \ref SYMBOL_VARIABLE symbol.
137 _gmx_sel_sym_value_var(gmx_sel_symrec_t
*sym
)
139 if (sym
->type
!= SYMBOL_VARIABLE
)
141 gmx_call("symbol is not a variable symbol");
148 * Adds the reserved symbols to a symbol table.
150 * \param[in,out] tab Symbol table to which the symbols are added.
152 * Assumes that the symbol table is empty.
155 add_reserved_symbols(gmx_sel_symtab_t
*tab
)
157 gmx_sel_symrec_t
*sym
;
158 gmx_sel_symrec_t
*last
;
162 for (i
= 0; i
< asize(sym_reserved
); ++i
)
165 sym
->name
= strdup(sym_reserved
[i
]);
166 sym
->type
= SYMBOL_RESERVED
;
181 * Adds the position symbols to the symbol list.
183 * \param[in,out] tab Symbol table to which the symbols are added.
186 add_position_symbols(gmx_sel_symtab_t
*tab
)
188 const char **postypes
;
189 gmx_sel_symrec_t
*sym
;
190 gmx_sel_symrec_t
*last
;
193 postypes
= gmx_ana_poscalc_create_type_enum(TRUE
);
195 while (last
&& last
->next
)
199 for (i
= 1; postypes
[i
] != NULL
; ++i
)
202 sym
->name
= strdup(postypes
[i
]);
203 sym
->type
= SYMBOL_POS
;
219 * \param[out] tabp Symbol table pointer to initialize.
221 * Reserved and position symbols are added to the created table.
224 _gmx_sel_symtab_create(gmx_sel_symtab_t
**tabp
)
226 gmx_sel_symtab_t
*tab
;
229 add_reserved_symbols(tab
);
230 add_position_symbols(tab
);
236 * \param[in] tab Symbol table to free.
238 * The pointer \p tab is invalid after the call.
241 _gmx_sel_symtab_free(gmx_sel_symtab_t
*tab
)
243 gmx_sel_symrec_t
*sym
;
248 tab
->first
= sym
->next
;
249 if (sym
->type
== SYMBOL_VARIABLE
)
251 _gmx_selelem_free(sym
->u
.var
);
260 * \param[in] tab Symbol table to search.
261 * \param[in] name Symbol name to find.
262 * \param[in] bExact If FALSE, symbols that begin with \p name are also
264 * \returns Pointer to the symbol with name \p name, or NULL if not found.
266 * If no exact match is found and \p bExact is FALSE, returns a symbol that
267 * begins with \p name if a unique matching symbol is found.
270 _gmx_sel_find_symbol(gmx_sel_symtab_t
*tab
, const char *name
, bool bExact
)
272 return _gmx_sel_find_symbol_len(tab
, name
, strlen(name
), bExact
);
276 * \param[in] tab Symbol table to search.
277 * \param[in] name Symbol name to find.
278 * \param[in] len Only consider the first \p len characters of \p name.
279 * \param[in] bExact If FALSE, symbols that begin with \p name are also
281 * \returns Pointer to the symbol with name \p name, or NULL if not found.
283 * If no exact match is found and \p bExact is FALSE, returns a symbol that
284 * begins with \p name if a unique matching symbol is found.
286 * The parameter \p len is there to allow using this function from scanner.l
287 * without modifying the text to be scanned or copying it.
290 _gmx_sel_find_symbol_len(gmx_sel_symtab_t
*tab
, const char *name
, size_t len
,
293 gmx_sel_symrec_t
*sym
;
294 gmx_sel_symrec_t
*match
;
304 if (!strncmp(sym
->name
, name
, len
))
306 if (strlen(sym
->name
) == len
)
315 if (sym
->type
== SYMBOL_METHOD
)
329 fprintf(stderr
, "parse error: ambiguous symbol\n");
336 * \param[in] tab Symbol table to search.
337 * \param[in] type Type of symbol to find.
338 * \returns The first symbol in \p tab with type \p type,
339 * or NULL if there are no such symbols.
342 _gmx_sel_first_symbol(gmx_sel_symtab_t
*tab
, e_symbol_t type
)
344 gmx_sel_symrec_t
*sym
;
349 if (sym
->type
== type
)
359 * \param[in] after Start the search after this symbol.
360 * \param[in] type Type of symbol to find.
361 * \returns The next symbol after \p after with type \p type,
362 * or NULL if there are no more symbols.
365 _gmx_sel_next_symbol(gmx_sel_symrec_t
*after
, e_symbol_t type
)
367 gmx_sel_symrec_t
*sym
;
372 if (sym
->type
== type
)
382 * Internal utility function used in adding symbols to a symbol table.
384 * \param[in,out] tab Symbol table to add the symbol to.
385 * \param[in] name Name of the symbol to add.
386 * \param[out] ctype On error, the type of the conflicting symbol is
387 * written to \p *ctype.
388 * \returns Pointer to the new symbol record, or NULL if \p name
389 * conflicts with an existing symbol.
391 static gmx_sel_symrec_t
*
392 add_symbol(gmx_sel_symtab_t
*tab
, const char *name
, e_symbol_t
*ctype
)
394 gmx_sel_symrec_t
*sym
, *psym
;
397 /* Check if there is a conflicting symbol */
402 if (!strcasecmp(sym
->name
, name
))
411 /* Create a new symbol record */
422 sym
->name
= strdup(name
);
427 * \param[in,out] tab Symbol table to add the symbol to.
428 * \param[in] name Name of the new symbol.
429 * \param[in] sel Value of the variable.
430 * \returns Pointer to the created symbol record, or NULL if there was a
431 * symbol with the same name.
434 _gmx_sel_add_var_symbol(gmx_sel_symtab_t
*tab
, const char *name
,
435 struct t_selelem
*sel
)
437 gmx_sel_symrec_t
*sym
;
440 sym
= add_symbol(tab
, name
, &ctype
);
443 fprintf(stderr
, "parse error: ");
446 case SYMBOL_RESERVED
:
448 fprintf(stderr
, "variable name (%s) conflicts with a reserved keyword\n",
451 case SYMBOL_VARIABLE
:
452 fprintf(stderr
, "duplicate variable name (%s)\n", name
);
455 fprintf(stderr
, "variable name (%s) conflicts with a selection keyword\n",
462 sym
->type
= SYMBOL_VARIABLE
;
469 * \param[in,out] tab Symbol table to add the symbol to.
470 * \param[in] name Name of the new symbol.
471 * \param[in] method Method that this symbol represents.
472 * \returns Pointer to the created symbol record, or NULL if there was a
473 * symbol with the same name.
476 _gmx_sel_add_method_symbol(gmx_sel_symtab_t
*tab
, const char *name
,
477 struct gmx_ana_selmethod_t
*method
)
479 gmx_sel_symrec_t
*sym
;
482 sym
= add_symbol(tab
, name
, &ctype
);
485 fprintf(stderr
, "parse error: ");
488 case SYMBOL_RESERVED
:
490 fprintf(stderr
, "method name (%s) conflicts with a reserved keyword\n",
493 case SYMBOL_VARIABLE
:
494 fprintf(stderr
, "method name (%s) conflicts with a variable name\n",
498 fprintf(stderr
, "duplicate method name (%s)\n", name
);
504 sym
->type
= SYMBOL_METHOD
;
505 sym
->u
.meth
= method
;