Removed obsolete selection code.
[gromacs/qmmm-gamess-us.git] / src / gmxlib / selection / symrec.c
blob74a82dd57b5a92ca384c19cb078eca19cb48c237
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 Implementation of functions in symrec.h.
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
38 #include <macros.h>
39 #include <smalloc.h>
40 #include <string2.h>
41 #include <typedefs.h>
42 #include <gmx_fatal.h>
44 #include <poscalc.h>
46 #include "selelem.h"
47 #include "symrec.h"
49 /*! \internal \brief
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;
58 /*! \internal \brief
59 * Single symbol for the selection parser.
61 struct gmx_sel_symrec_t
63 /** Name of the symbol. */
64 char *name;
65 /** Type of the symbol. */
66 e_symbol_t type;
67 /** Value of the symbol. */
68 union {
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;
73 } u;
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[] = {
80 "group",
81 "to",
82 "not",
83 "and",
84 "or",
85 "xor",
86 "yes",
87 "no",
88 "on",
89 "off",
90 "help",
93 /*!
94 * \param[in] sym Symbol to query.
95 * \returns The name of \p sym.
97 * The returned pointer should not be free'd.
99 char *
100 _gmx_sel_sym_name(gmx_sel_symrec_t *sym)
102 return sym->name;
106 * \param[in] sym Symbol to query.
107 * \returns The type of \p sym.
109 e_symbol_t
110 _gmx_sel_sym_type(gmx_sel_symrec_t *sym)
112 return sym->type;
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");
126 return NULL;
128 return sym->u.meth;
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.
136 struct t_selelem *
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");
142 return NULL;
144 return sym->u.var;
147 /*! \brief
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.
154 static void
155 add_reserved_symbols(gmx_sel_symtab_t *tab)
157 gmx_sel_symrec_t *sym;
158 gmx_sel_symrec_t *last;
159 size_t i;
161 last = NULL;
162 for (i = 0; i < asize(sym_reserved); ++i)
164 snew(sym, 1);
165 sym->name = strdup(sym_reserved[i]);
166 sym->type = SYMBOL_RESERVED;
167 sym->next = NULL;
168 if (last)
170 last->next = sym;
172 else
174 tab->first = sym;
176 last = sym;
180 /*! \brief
181 * Adds the position symbols to the symbol list.
183 * \param[in,out] tab Symbol table to which the symbols are added.
185 static void
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;
191 int i;
193 postypes = gmx_ana_poscalc_create_type_enum(TRUE);
194 last = tab->first;
195 while (last && last->next)
197 last = last->next;
199 for (i = 1; postypes[i] != NULL; ++i)
201 snew(sym, 1);
202 sym->name = strdup(postypes[i]);
203 sym->type = SYMBOL_POS;
204 sym->next = NULL;
205 if (last)
207 last->next = sym;
209 else
211 tab->first = sym;
213 last = sym;
215 sfree(postypes);
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;
228 snew(tab, 1);
229 add_reserved_symbols(tab);
230 add_position_symbols(tab);
231 *tabp = tab;
232 return 0;
236 * \param[in] tab Symbol table to free.
238 * The pointer \p tab is invalid after the call.
240 void
241 _gmx_sel_symtab_free(gmx_sel_symtab_t *tab)
243 gmx_sel_symrec_t *sym;
245 while (tab->first)
247 sym = tab->first;
248 tab->first = sym->next;
249 if (sym->type == SYMBOL_VARIABLE)
251 _gmx_selelem_free(sym->u.var);
253 sfree(sym->name);
254 sfree(sym);
256 sfree(tab);
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
263 * considered.
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.
269 gmx_sel_symrec_t *
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
280 * considered.
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.
289 gmx_sel_symrec_t *
290 _gmx_sel_find_symbol_len(gmx_sel_symtab_t *tab, const char *name, size_t len,
291 bool bExact)
293 gmx_sel_symrec_t *sym;
294 gmx_sel_symrec_t *match;
295 bool bUnique;
296 bool bMatch;
298 match = NULL;
299 bUnique = TRUE;
300 bMatch = FALSE;
301 sym = tab->first;
302 while (sym)
304 if (!strncmp(sym->name, name, len))
306 if (strlen(sym->name) == len)
308 return sym;
310 if (bMatch)
312 bUnique = FALSE;
314 bMatch = TRUE;
315 if (sym->type == SYMBOL_METHOD)
317 match = sym;
320 sym = sym->next;
322 if (bExact)
324 return NULL;
327 if (!bUnique)
329 fprintf(stderr, "parse error: ambiguous symbol\n");
330 return NULL;
332 return match;
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.
341 gmx_sel_symrec_t *
342 _gmx_sel_first_symbol(gmx_sel_symtab_t *tab, e_symbol_t type)
344 gmx_sel_symrec_t *sym;
346 sym = tab->first;
347 while (sym)
349 if (sym->type == type)
351 return sym;
353 sym = sym->next;
355 return NULL;
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.
364 gmx_sel_symrec_t *
365 _gmx_sel_next_symbol(gmx_sel_symrec_t *after, e_symbol_t type)
367 gmx_sel_symrec_t *sym;
369 sym = after->next;
370 while (sym)
372 if (sym->type == type)
374 return sym;
376 sym = sym->next;
378 return NULL;
381 /*! \brief
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;
395 int len;
397 /* Check if there is a conflicting symbol */
398 psym = NULL;
399 sym = tab->first;
400 while (sym)
402 if (!strcasecmp(sym->name, name))
404 *ctype = sym->type;
405 return NULL;
407 psym = sym;
408 sym = sym->next;
411 /* Create a new symbol record */
412 if (psym == NULL)
414 snew(tab->first, 1);
415 sym = tab->first;
417 else
419 snew(psym->next, 1);
420 sym = psym->next;
422 sym->name = strdup(name);
423 return sym;
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.
433 gmx_sel_symrec_t *
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;
438 e_symbol_t ctype;
440 sym = add_symbol(tab, name, &ctype);
441 if (!sym)
443 fprintf(stderr, "parse error: ");
444 switch (ctype)
446 case SYMBOL_RESERVED:
447 case SYMBOL_POS:
448 fprintf(stderr, "variable name (%s) conflicts with a reserved keyword\n",
449 name);
450 break;
451 case SYMBOL_VARIABLE:
452 fprintf(stderr, "duplicate variable name (%s)\n", name);
453 break;
454 case SYMBOL_METHOD:
455 fprintf(stderr, "variable name (%s) conflicts with a selection keyword\n",
456 name);
457 break;
459 return NULL;
462 sym->type = SYMBOL_VARIABLE;
463 sym->u.var = sel;
464 sel->refcount++;
465 return sym;
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.
475 gmx_sel_symrec_t *
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;
480 e_symbol_t ctype;
482 sym = add_symbol(tab, name, &ctype);
483 if (!sym)
485 fprintf(stderr, "parse error: ");
486 switch (ctype)
488 case SYMBOL_RESERVED:
489 case SYMBOL_POS:
490 fprintf(stderr, "method name (%s) conflicts with a reserved keyword\n",
491 name);
492 break;
493 case SYMBOL_VARIABLE:
494 fprintf(stderr, "method name (%s) conflicts with a variable name\n",
495 name);
496 break;
497 case SYMBOL_METHOD:
498 fprintf(stderr, "duplicate method name (%s)\n", name);
499 break;
501 return NULL;
504 sym->type = SYMBOL_METHOD;
505 sym->u.meth = method;
506 return sym;