Update my e-mail address on author lines.
[alexxy/gromacs.git] / src / gromacs / selection / params.cpp
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
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.
13
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.
18  *
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.
25  *
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.
28  *
29  * For more info, check our website at http://www.gromacs.org
30  */
31 /*! \internal \file
32  * \brief
33  * Implements functions in selparam.h.
34  *
35  * \author Teemu Murtola <teemu.murtola@gmail.com>
36  * \ingroup module_selection
37  */
38 #include <algorithm>
39 #include <string>
40
41 #include "gromacs/legacyheaders/smalloc.h"
42 #include "gromacs/legacyheaders/string2.h"
43 #include "gromacs/legacyheaders/vec.h"
44
45 #include "gromacs/selection/position.h"
46 #include "gromacs/selection/selmethod.h"
47 #include "gromacs/selection/selparam.h"
48 #include "gromacs/utility/exceptions.h"
49 #include "gromacs/utility/gmxassert.h"
50 #include "gromacs/utility/messagestringcollector.h"
51 #include "gromacs/utility/stringutil.h"
52
53 #include "parsetree.h"
54 #include "position.h"
55 #include "scanner.h"
56 #include "selelem.h"
57
58 using gmx::SelectionParserValue;
59 using gmx::SelectionParserValueList;
60 using gmx::SelectionParserParameter;
61 using gmx::SelectionParserParameterList;
62 using gmx::SelectionTreeElement;
63 using gmx::SelectionTreeElementPointer;
64
65 /*!
66  * \param[in] name   Name of the parameter to search.
67  * \param[in] nparam Number of parameters in the \p param array.
68  * \param[in] param  Parameter array to search.
69  * \returns   Pointer to the parameter in the \p param
70  *   or NULL if no parameter with name \p name was found.
71  *
72  * The comparison is case-sensitive.
73  */
74 gmx_ana_selparam_t *
75 gmx_ana_selparam_find(const char *name, int nparam, gmx_ana_selparam_t *param)
76 {
77     int                i;
78
79     if (nparam == 0)
80     {
81         return NULL;
82     }
83     /* Find the first non-null parameter */
84     i = 0;
85     while (i < nparam && param[i].name == NULL)
86     {
87         ++i;
88     }
89     /* Process the special case of a NULL parameter */
90     if (name == NULL)
91     {
92         return (i == 0) ? NULL : &param[i-1];
93     }
94     for (; i < nparam; ++i)
95     {
96         if (!strcmp(param[i].name, name))
97         {
98             return &param[i];
99         }
100         /* Check for 'no' prefix on boolean parameters */
101         if (param[i].val.type == NO_VALUE
102             && strlen(name) > 2 && name[0] == 'n' && name[1] == 'o'
103             && !strcmp(param[i].name, name+2))
104         {
105             return &param[i];
106         }
107     }
108     return NULL;
109 }
110
111 /*! \brief
112  * Does a type conversion on a SelectionParserValue.
113  *
114  * \param[in,out] value    Value to convert.
115  * \param[in]     type     Type to convert to.
116  * \param[in]     scanner  Scanner data structure.
117  * \returns       0 on success, a non-zero value on error.
118  */
119 static int
120 convert_value(SelectionParserValue *value, e_selvalue_t type, void *scanner)
121 {
122     if (value->type == type || type == NO_VALUE)
123     {
124         return 0;
125     }
126     if (value->hasExpressionValue())
127     {
128         /* Conversion from atom selection to position using default
129          * reference positions. */
130         if (value->type == GROUP_VALUE && type == POS_VALUE)
131         {
132             SelectionTreeElementPointer expr =
133                 _gmx_sel_init_position(value->expr, NULL, scanner);
134             // FIXME: Use exceptions
135             if (!expr)
136             {
137                 return -1;
138             }
139             *value = SelectionParserValue::createExpr(expr);
140             return 0;
141         }
142         return -1;
143     }
144     else
145     {
146         /* Integers to floating point are easy */
147         if (value->type == INT_VALUE && type == REAL_VALUE)
148         {
149             *value = SelectionParserValue::createRealRange(value->u.i.i1,
150                                                            value->u.i.i2);
151             return 0;
152         }
153         /* Reals that are integer-valued can also be converted */
154         if (value->type == REAL_VALUE && type == INT_VALUE)
155         {
156             int i1 = static_cast<int>(value->u.r.r1);
157             int i2 = static_cast<int>(value->u.r.r2);
158             if (gmx_within_tol(value->u.r.r1, i1, GMX_REAL_EPS)
159                 && gmx_within_tol(value->u.r.r2, i2, GMX_REAL_EPS))
160             {
161                 *value = SelectionParserValue::createIntegerRange(i1, i2);
162                 return 0;
163             }
164         }
165     }
166     return -1;
167 }
168
169 /*! \brief
170  * Does a type conversion on a list of values.
171  *
172  * \param[in,out] values   Values to convert.
173  * \param[in]     type     Type to convert to.
174  * \param[in]     scanner  Scanner data structure.
175  * \returns       0 on success, a non-zero value on error.
176  */
177 static int
178 convert_values(SelectionParserValueList *values, e_selvalue_t type, void *scanner)
179 {
180     int rc = 0;
181     SelectionParserValueList::iterator value;
182     for (value = values->begin(); value != values->end(); ++value)
183     {
184         int rc1 = convert_value(&*value, type, scanner);
185         if (rc1 != 0 && rc == 0)
186         {
187             rc = rc1;
188         }
189     }
190     /* FIXME: More informative error messages */
191     return rc;
192 }
193
194 /*! \brief
195  * Adds a child element for a parameter, keeping the parameter order.
196  *
197  * \param[in,out] root  Root element to which the child is added.
198  * \param[in]     child Child to add.
199  * \param[in]     param Parameter for which this child is a value.
200  *
201  * Puts \p child in the child list of \p root such that the list remains
202  * in the same order as the corresponding parameters.
203  */
204 static void
205 place_child(const SelectionTreeElementPointer &root,
206             const SelectionTreeElementPointer &child,
207             gmx_ana_selparam_t                *param)
208 {
209     gmx_ana_selparam_t *ps;
210     int                 n;
211
212     ps = root->u.expr.method->param;
213     n  = param - ps;
214     /* Put the child element in the correct place */
215     if (!root->child || n < root->child->u.param - ps)
216     {
217         child->next = root->child;
218         root->child = child;
219     }
220     else
221     {
222         SelectionTreeElementPointer prev = root->child;
223         while (prev->next && prev->next->u.param - ps >= n)
224         {
225             prev = prev->next;
226         }
227         child->next = prev->next;
228         prev->next  = child;
229     }
230 }
231
232 /*! \brief
233  * Comparison function for sorting integer ranges.
234  *
235  * \param[in] a Pointer to the first range.
236  * \param[in] b Pointer to the second range.
237  * \returns   -1, 0, or 1 depending on the relative order of \p a and \p b.
238  *
239  * The ranges are primarily sorted based on their starting point, and
240  * secondarily based on length (longer ranges come first).
241  */
242 static int
243 cmp_int_range(const void *a, const void *b)
244 {
245     if (((int *)a)[0] < ((int *)b)[0])
246     {
247         return -1;
248     }
249     if (((int *)a)[0] > ((int *)b)[0])
250     {
251         return 1;
252     }
253     if (((int *)a)[1] > ((int *)b)[1])
254     {
255         return -1;
256     }
257     return 0;
258 }
259
260 /*! \brief
261  * Comparison function for sorting real ranges.
262  *
263  * \param[in] a Pointer to the first range.
264  * \param[in] b Pointer to the second range.
265  * \returns   -1, 0, or 1 depending on the relative order of \p a and \p b.
266  *
267  * The ranges are primarily sorted based on their starting point, and
268  * secondarily based on length (longer ranges come first).
269  */
270 static int
271 cmp_real_range(const void *a, const void *b)
272 {
273     if (((real *)a)[0] < ((real *)b)[0])
274     {
275         return -1;
276     }
277     if (((real *)a)[0] > ((real *)b)[0])
278     {
279         return 1;
280     }
281     if (((real *)a)[1] > ((real *)b)[1])
282     {
283         return -1;
284     }
285     return 0;
286 }
287
288 /*! \brief
289  * Parses the values for a parameter that takes integer or real ranges.
290  *
291  * \param[in] values List of values.
292  * \param     param  Parameter to parse.
293  * \param[in] scanner Scanner data structure.
294  * \returns   true if the values were parsed successfully, false otherwise.
295  */
296 static bool
297 parse_values_range(const SelectionParserValueList &values,
298                    gmx_ana_selparam_t *param, void *scanner)
299 {
300     int                *idata;
301     real               *rdata;
302     int                 i, j, n;
303
304     param->flags &= ~SPAR_DYNAMIC;
305     GMX_RELEASE_ASSERT(param->val.type == INT_VALUE || param->val.type == REAL_VALUE,
306                        "Invalid range parameter type");
307     idata = NULL;
308     rdata = NULL;
309     if (param->val.type == INT_VALUE)
310     {
311         snew(idata, values.size()*2);
312     }
313     else
314     {
315         snew(rdata, values.size()*2);
316     }
317     i = 0;
318     SelectionParserValueList::const_iterator value;
319     for (value = values.begin(); value != values.end(); ++value)
320     {
321         if (value->hasExpressionValue())
322         {
323             _gmx_selparser_error(scanner, "expressions not supported within range parameters");
324             return false;
325         }
326         GMX_RELEASE_ASSERT(value->type == param->val.type,
327                            "Invalid range value type (should have been caught earlier)");
328         if (param->val.type == INT_VALUE)
329         {
330             int i1 = std::min(value->u.i.i1, value->u.i.i2);
331             int i2 = std::max(value->u.i.i1, value->u.i.i2);
332             /* Check if the new range overlaps or extends the previous one */
333             if (i > 0 && i1 <= idata[i-1]+1 && i2 >= idata[i-2]-1)
334             {
335                 idata[i-2] = std::min(idata[i-2], i1);
336                 idata[i-1] = std::max(idata[i-1], i2);
337             }
338             else
339             {
340                 idata[i++] = i1;
341                 idata[i++] = i2;
342             }
343         }
344         else
345         {
346             real r1 = std::min(value->u.r.r1, value->u.r.r2);
347             real r2 = std::max(value->u.r.r1, value->u.r.r2);
348             /* Check if the new range overlaps or extends the previous one */
349             if (i > 0 && r1 <= rdata[i-1] && r2 >= rdata[i-2])
350             {
351                 rdata[i-2] = std::min(rdata[i-2], r1);
352                 rdata[i-1] = std::max(rdata[i-1], r2);
353             }
354             else
355             {
356                 rdata[i++] = r1;
357                 rdata[i++] = r2;
358             }
359         }
360     }
361     n = i/2;
362     /* Sort the ranges and merge consequent ones */
363     if (param->val.type == INT_VALUE)
364     {
365         qsort(idata, n, 2*sizeof(int), &cmp_int_range);
366         for (i = j = 2; i < 2*n; i += 2)
367         {
368             if (idata[j-1]+1 >= idata[i])
369             {
370                 if (idata[i+1] > idata[j-1])
371                 {
372                     idata[j-1] = idata[i+1];
373                 }
374             }
375             else
376             {
377                 idata[j]   = idata[i];
378                 idata[j+1] = idata[i+1];
379                 j         += 2;
380             }
381         }
382     }
383     else
384     {
385         qsort(rdata, n, 2*sizeof(real), &cmp_real_range);
386         for (i = j = 2; i < 2*n; i += 2)
387         {
388             if (rdata[j-1]+1 >= rdata[i])
389             {
390                 if (rdata[i+1] > rdata[j-1])
391                 {
392                     rdata[j-1] = rdata[i+1];
393                 }
394             }
395             else
396             {
397                 rdata[j]   = rdata[i];
398                 rdata[j+1] = rdata[i+1];
399                 j         += 2;
400             }
401         }
402     }
403     n = j/2;
404     /* Store the values */
405     if (param->flags & SPAR_VARNUM)
406     {
407         param->val.nr  = n;
408         if (param->val.type == INT_VALUE)
409         {
410             srenew(idata, j);
411             _gmx_selvalue_setstore_alloc(&param->val, idata, j);
412         }
413         else
414         {
415             srenew(rdata, j);
416             _gmx_selvalue_setstore_alloc(&param->val, rdata, j);
417         }
418     }
419     else
420     {
421         if (n != param->val.nr)
422         {
423             _gmx_selparser_error(scanner, "the value should consist of exactly one range");
424             sfree(idata);
425             sfree(rdata);
426             return false;
427         }
428         if (param->val.type == INT_VALUE)
429         {
430             memcpy(param->val.u.i, idata, 2*n*sizeof(int));
431             sfree(idata);
432         }
433         else
434         {
435             memcpy(param->val.u.r, rdata, 2*n*sizeof(real));
436             sfree(rdata);
437         }
438     }
439     if (param->nvalptr)
440     {
441         *param->nvalptr = param->val.nr;
442     }
443     param->nvalptr = NULL;
444
445     return true;
446 }
447
448 /*! \brief
449  * Parses the values for a parameter that takes a variable number of values.
450  *
451  * \param[in] values List of values.
452  * \param     param  Parameter to parse.
453  * \param     root   Selection element to which child expressions are added.
454  * \param[in] scanner Scanner data structure.
455  * \returns   true if the values were parsed successfully, false otherwise.
456  *
457  * For integer ranges, the sequence of numbers from the first to second value
458  * is stored, each as a separate value.
459  */
460 static bool
461 parse_values_varnum(const SelectionParserValueList    &values,
462                     gmx_ana_selparam_t                *param,
463                     const SelectionTreeElementPointer &root,
464                     void                              *scanner)
465 {
466     int                 i, j;
467
468     param->flags &= ~SPAR_DYNAMIC;
469     /* Compute number of values, considering also integer ranges. */
470     size_t valueCount = values.size();
471     if (param->val.type == INT_VALUE)
472     {
473         SelectionParserValueList::const_iterator value;
474         for (value = values.begin(); value != values.end(); ++value)
475         {
476             if (value->type == INT_VALUE && !value->hasExpressionValue())
477             {
478                 valueCount += abs(value->u.i.i2 - value->u.i.i1);
479             }
480         }
481     }
482
483     /* Check that the value type is actually implemented */
484     if (param->val.type != INT_VALUE && param->val.type != REAL_VALUE
485         && param->val.type != STR_VALUE && param->val.type != POS_VALUE)
486     {
487         GMX_THROW(gmx::InternalError("Variable-count value type not implemented"));
488     }
489
490     /* Reserve appropriate amount of memory */
491     if (param->val.type == POS_VALUE)
492     {
493         gmx_ana_pos_reserve(param->val.u.p, valueCount, 0);
494         gmx_ana_pos_set_nr(param->val.u.p, valueCount);
495         gmx_ana_indexmap_init(&param->val.u.p->m, NULL, NULL, INDEX_UNKNOWN);
496     }
497     else
498     {
499         _gmx_selvalue_reserve(&param->val, valueCount);
500     }
501
502     i     = 0;
503     SelectionParserValueList::const_iterator value;
504     for (value = values.begin(); value != values.end(); ++value)
505     {
506         if (value->hasExpressionValue())
507         {
508             _gmx_selparser_error(scanner, "expressions not supported within value lists");
509             return false;
510         }
511         GMX_RELEASE_ASSERT(value->type == param->val.type,
512                            "Invalid value type (should have been caught earlier)");
513         switch (param->val.type)
514         {
515             case INT_VALUE:
516                 if (value->u.i.i1 <= value->u.i.i2)
517                 {
518                     for (j = value->u.i.i1; j <= value->u.i.i2; ++j)
519                     {
520                         param->val.u.i[i++] = j;
521                     }
522                 }
523                 else
524                 {
525                     for (j = value->u.i.i1; j >= value->u.i.i2; --j)
526                     {
527                         param->val.u.i[i++] = j;
528                     }
529                 }
530                 break;
531             case REAL_VALUE:
532                 if (value->u.r.r1 != value->u.r.r2)
533                 {
534                     _gmx_selparser_error(scanner, "real ranges not supported");
535                     return false;
536                 }
537                 param->val.u.r[i++] = value->u.r.r1;
538                 break;
539             case STR_VALUE:
540                 param->val.u.s[i++] = strdup(value->stringValue().c_str());
541                 break;
542             case POS_VALUE:  copy_rvec(value->u.x, param->val.u.p->x[i++]); break;
543             default: /* Should not be reached */
544                 GMX_THROW(gmx::InternalError("Variable-count value type not implemented"));
545         }
546     }
547     param->val.nr = i;
548     if (param->nvalptr)
549     {
550         *param->nvalptr = param->val.nr;
551     }
552     param->nvalptr = NULL;
553     /* Create a dummy child element to store the string values.
554      * This element is responsible for freeing the values, but carries no
555      * other function. */
556     if (param->val.type == STR_VALUE)
557     {
558         SelectionTreeElementPointer child(new SelectionTreeElement(SEL_CONST));
559         _gmx_selelem_set_vtype(child, STR_VALUE);
560         child->setName(param->name);
561         child->flags &= ~SEL_ALLOCVAL;
562         child->flags |= SEL_FLAGSSET | SEL_VARNUMVAL | SEL_ALLOCDATA;
563         child->v.nr   = param->val.nr;
564         _gmx_selvalue_setstore(&child->v, param->val.u.s);
565         /* Because the child is not group-valued, the u union is not used
566          * for anything, so we can abuse it by storing the parameter value
567          * as place_child() expects, but this is really ugly... */
568         child->u.param = param;
569         place_child(root, child, param);
570     }
571
572     return true;
573 }
574
575 /*! \brief
576  * Adds a new subexpression reference to a selection element.
577  *
578  * \param[in,out] root  Root element to which the subexpression is added.
579  * \param[in]     param Parameter for which this expression is a value.
580  * \param[in]     expr  Expression to add.
581  * \param[in]     scanner Scanner data structure.
582  * \returns       The created child element.
583  *
584  * Creates a new \ref SEL_SUBEXPRREF element and adds it into the child
585  * list of \p root.
586  * If \p expr is already a \ref SEL_SUBEXPRREF, it is used as it is.
587  * \ref SEL_ALLOCVAL is cleared for the returned element.
588  */
589 static SelectionTreeElementPointer
590 add_child(const SelectionTreeElementPointer &root, gmx_ana_selparam_t *param,
591           const SelectionTreeElementPointer &expr, void *scanner)
592 {
593     GMX_RELEASE_ASSERT(root->type == SEL_EXPRESSION || root->type == SEL_MODIFIER,
594                        "Unsupported root element for selection parameter parser");
595     SelectionTreeElementPointer child;
596     /* Create a subexpression reference element if necessary */
597     if (expr->type == SEL_SUBEXPRREF)
598     {
599         child = expr;
600     }
601     else
602     {
603         child.reset(new SelectionTreeElement(SEL_SUBEXPRREF));
604         _gmx_selelem_set_vtype(child, expr->v.type);
605         child->child  = expr;
606     }
607     /* Setup the child element */
608     child->flags  &= ~SEL_ALLOCVAL;
609     child->u.param = param;
610     if (child->v.type != param->val.type)
611     {
612         _gmx_selparser_error(scanner, "invalid expression value");
613         // FIXME: Use exceptions.
614         return SelectionTreeElementPointer();
615     }
616     _gmx_selelem_update_flags(child, scanner);
617     if ((child->flags & SEL_DYNAMIC) && !(param->flags & SPAR_DYNAMIC))
618     {
619         _gmx_selparser_error(scanner, "dynamic values not supported");
620         // FIXME: Use exceptions.
621         return SelectionTreeElementPointer();
622     }
623     if (!(child->flags & SEL_DYNAMIC))
624     {
625         param->flags &= ~SPAR_DYNAMIC;
626     }
627     /* Put the child element in the correct place */
628     place_child(root, child, param);
629     return child;
630 }
631
632 /*! \brief
633  * Parses an expression value for a parameter that takes a variable number of values.
634  *
635  * \param[in] values List of values.
636  * \param     param  Parameter to parse.
637  * \param     root   Selection element to which child expressions are added.
638  * \param[in] scanner Scanner data structure.
639  * \returns   true if the values were parsed successfully, false otherwise.
640  */
641 static bool
642 parse_values_varnum_expr(const SelectionParserValueList    &values,
643                          gmx_ana_selparam_t                *param,
644                          const SelectionTreeElementPointer &root,
645                          void                              *scanner)
646 {
647     GMX_RELEASE_ASSERT(values.size() == 1 && values.front().hasExpressionValue(),
648                        "Called with an invalid type of value");
649
650     SelectionTreeElementPointer child
651         = add_child(root, param, values.front().expr, scanner);
652     if (!child)
653     {
654         return false;
655     }
656
657     /* Process single-valued expressions */
658     /* TODO: We should also handle SEL_SINGLEVAL expressions here */
659     if (child->v.type == POS_VALUE || child->v.type == GROUP_VALUE)
660     {
661         /* Set the value storage */
662         _gmx_selvalue_setstore(&child->v, param->val.u.ptr);
663         param->val.nr = 1;
664         if (param->nvalptr)
665         {
666             *param->nvalptr = param->val.nr;
667         }
668         param->nvalptr = NULL;
669         return true;
670     }
671
672     if (!(child->flags & SEL_VARNUMVAL))
673     {
674         _gmx_selparser_error(scanner, "invalid expression value");
675         return false;
676     }
677
678     child->flags   |= SEL_ALLOCVAL;
679     param->val.nr   = -1;
680     *param->nvalptr = param->val.nr;
681     /* Rest of the initialization is done during compilation in
682      * init_method(). */
683
684     return true;
685 }
686
687 /*! \brief
688  * Initializes the storage of an expression value.
689  *
690  * \param[in,out] sel   Selection element that evaluates the value.
691  * \param[in]     param Parameter to receive the value.
692  * \param[in]     i     The value of \p sel evaluates the value \p i for
693  *   \p param.
694  * \param[in]     scanner Scanner data structure.
695  *
696  * Initializes the data pointer of \p sel such that the result is stored
697  * as the value \p i of \p param.
698  * This function is used internally by parse_values_std().
699  */
700 static bool
701 set_expr_value_store(const SelectionTreeElementPointer &sel,
702                      gmx_ana_selparam_t *param, int i, void *scanner)
703 {
704     if (sel->v.type != GROUP_VALUE && !(sel->flags & SEL_SINGLEVAL))
705     {
706         _gmx_selparser_error(scanner, "invalid expression value");
707         return false;
708     }
709     switch (sel->v.type)
710     {
711         case INT_VALUE:   sel->v.u.i = &param->val.u.i[i]; break;
712         case REAL_VALUE:  sel->v.u.r = &param->val.u.r[i]; break;
713         case STR_VALUE:   sel->v.u.s = &param->val.u.s[i]; break;
714         case POS_VALUE:   sel->v.u.p = &param->val.u.p[i]; break;
715         case GROUP_VALUE: sel->v.u.g = &param->val.u.g[i]; break;
716         default: /* Error */
717             GMX_THROW(gmx::InternalError("Invalid value type"));
718     }
719     sel->v.nr     = 1;
720     sel->v.nalloc = -1;
721     return true;
722 }
723
724 /*! \brief
725  * Parses the values for a parameter that takes a constant number of values.
726  *
727  * \param[in] values List of values.
728  * \param     param  Parameter to parse.
729  * \param     root   Selection element to which child expressions are added.
730  * \param[in] scanner Scanner data structure.
731  * \returns   true if the values were parsed successfully, false otherwise.
732  *
733  * For integer ranges, the sequence of numbers from the first to second value
734  * is stored, each as a separate value.
735  */
736 static bool
737 parse_values_std(const SelectionParserValueList &values,
738                  gmx_ana_selparam_t *param,
739                  const SelectionTreeElementPointer &root, void *scanner)
740 {
741     int                i, j;
742     bool               bDynamic;
743
744     /* Handle atom-valued parameters */
745     if (param->flags & SPAR_ATOMVAL)
746     {
747         if (values.size() > 1)
748         {
749             _gmx_selparser_error(scanner, "more than one value not supported");
750             return false;
751         }
752         if (values.front().hasExpressionValue())
753         {
754             SelectionTreeElementPointer child
755                 = add_child(root, param, values.front().expr, scanner);
756             if (!child)
757             {
758                 return false;
759             }
760             child->flags |= SEL_ALLOCVAL;
761             if (child->v.type != GROUP_VALUE && (child->flags & SEL_ATOMVAL))
762             {
763                 /* Rest of the initialization is done during compilation in
764                  * init_method(). */
765                 /* TODO: Positions are not correctly handled */
766                 param->val.nr = -1;
767                 if (param->nvalptr)
768                 {
769                     *param->nvalptr = -1;
770                 }
771                 return true;
772             }
773             param->flags  &= ~SPAR_ATOMVAL;
774             param->val.nr  = 1;
775             if (param->nvalptr)
776             {
777                 *param->nvalptr = 1;
778             }
779             param->nvalptr = NULL;
780             if (param->val.type == INT_VALUE || param->val.type == REAL_VALUE
781                 || param->val.type == STR_VALUE)
782             {
783                 _gmx_selvalue_reserve(&param->val, 1);
784             }
785             return set_expr_value_store(child, param, 0, scanner);
786         }
787         /* If we reach here, proceed with normal parameter handling */
788         param->val.nr = 1;
789         if (param->val.type == INT_VALUE || param->val.type == REAL_VALUE
790             || param->val.type == STR_VALUE)
791         {
792             _gmx_selvalue_reserve(&param->val, 1);
793         }
794         param->flags &= ~SPAR_ATOMVAL;
795         param->flags &= ~SPAR_DYNAMIC;
796     }
797
798     i        = 0;
799     bDynamic = false;
800     SelectionParserValueList::const_iterator value;
801     for (value = values.begin(); value != values.end() && i < param->val.nr; ++value)
802     {
803         if (value->type != param->val.type)
804         {
805             _gmx_selparser_error(scanner, "incorrect value skipped");
806             continue;
807         }
808         if (value->hasExpressionValue())
809         {
810             SelectionTreeElementPointer child
811                 = add_child(root, param, value->expr, scanner);
812             /* Check that the expression is valid */
813             if (!child)
814             {
815                 return false;
816             }
817             if (!set_expr_value_store(child, param, i, scanner))
818             {
819                 return false;
820             }
821             if (child->flags & SEL_DYNAMIC)
822             {
823                 bDynamic = true;
824             }
825         }
826         else
827         {
828             /* Value is not an expression */
829             switch (value->type)
830             {
831                 case INT_VALUE:
832                     if (value->u.i.i1 <= value->u.i.i2)
833                     {
834                         for (j = value->u.i.i1; j <= value->u.i.i2 && i < param->val.nr; ++j)
835                         {
836                             param->val.u.i[i++] = j;
837                         }
838                         if (j != value->u.i.i2 + 1)
839                         {
840                             _gmx_selparser_error(scanner, "extra values skipped");
841                         }
842                     }
843                     else
844                     {
845                         for (j = value->u.i.i1; j >= value->u.i.i2 && i < param->val.nr; --j)
846                         {
847                             param->val.u.i[i++] = j;
848                         }
849                         if (j != value->u.i.i2 - 1)
850                         {
851                             _gmx_selparser_error(scanner, "extra values skipped");
852                         }
853                     }
854                     --i;
855                     break;
856                 case REAL_VALUE:
857                     if (value->u.r.r1 != value->u.r.r2)
858                     {
859                         _gmx_selparser_error(scanner, "real ranges not supported");
860                         return false;
861                     }
862                     param->val.u.r[i] = value->u.r.r1;
863                     break;
864                 case STR_VALUE:
865                     param->val.u.s[i] = strdup(value->stringValue().c_str());
866                     break;
867                 case POS_VALUE:
868                     gmx_ana_pos_init_const(&param->val.u.p[i], value->u.x);
869                     break;
870                 case NO_VALUE:
871                 case GROUP_VALUE:
872                     GMX_THROW(gmx::InternalError("Invalid non-expression value type"));
873             }
874         }
875         ++i;
876     }
877     if (value != values.end())
878     {
879         _gmx_selparser_error(scanner, "extra values");
880         return false;
881     }
882     if (i < param->val.nr)
883     {
884         _gmx_selparser_error(scanner, "not enough values");
885         return false;
886     }
887     if (!bDynamic)
888     {
889         param->flags &= ~SPAR_DYNAMIC;
890     }
891     if (param->nvalptr)
892     {
893         *param->nvalptr = param->val.nr;
894     }
895     param->nvalptr = NULL;
896
897     return true;
898 }
899
900 /*! \brief
901  * Parses the values for a boolean parameter.
902  *
903  * \param[in] name   Name by which the parameter was given.
904  * \param[in] values List of values.
905  * \param     param  Parameter to parse.
906  * \param[in] scanner Scanner data structure.
907  * \returns   true if the values were parsed successfully, false otherwise.
908  */
909 static bool
910 parse_values_bool(const std::string &name,
911                   const SelectionParserValueList &values,
912                   gmx_ana_selparam_t *param, void *scanner)
913 {
914     GMX_ASSERT(param->val.type == NO_VALUE,
915                "Boolean parser called for non-boolean parameter");
916     if (values.size() > 1 || (!values.empty() && values.front().type != INT_VALUE))
917     {
918         _gmx_selparser_error(scanner, "parameter takes only a yes/no/on/off/0/1 value");
919         return false;
920     }
921
922     bool bSetNo = false;
923     /* Check if the parameter name is given with a 'no' prefix */
924     if (name.length() > 2 && name[0] == 'n' && name[1] == 'o'
925         && name.compare(2, name.length() - 2, param->name) == 0)
926     {
927         bSetNo = true;
928     }
929     if (bSetNo && !values.empty())
930     {
931         _gmx_selparser_error(scanner, "parameter 'no%s' should not have a value",
932                              param->name);
933         return false;
934     }
935     if (!values.empty() && values.front().u.i.i1 == 0)
936     {
937         bSetNo = true;
938     }
939
940     *param->val.u.b = bSetNo ? false : true;
941     return true;
942 }
943
944 /*! \brief
945  * Parses the values for an enumeration parameter.
946  *
947  * \param[in] values List of values.
948  * \param     param  Parameter to parse.
949  * \param[in] scanner Scanner data structure.
950  * \returns   true if the values were parsed successfully, false otherwise.
951  */
952 static bool
953 parse_values_enum(const SelectionParserValueList &values,
954                   gmx_ana_selparam_t             *param,
955                   void                           *scanner)
956 {
957     GMX_ASSERT(param->val.type == STR_VALUE,
958                "Enum parser called for non-string parameter");
959     if (values.size() != 1)
960     {
961         _gmx_selparser_error(scanner, "a single value is required");
962         return false;
963     }
964     const SelectionParserValue &value = values.front();
965     GMX_RELEASE_ASSERT(value.type == param->val.type,
966                        "Invalid value type (should have been caught earlier)");
967     if (value.hasExpressionValue())
968     {
969         _gmx_selparser_error(scanner, "expression value for enumerated parameter not supported");
970         return false;
971     }
972
973     const std::string &svalue = value.stringValue();
974     int                i      = 1;
975     int                match  = 0;
976     while (param->val.u.s[i] != NULL)
977     {
978         if (gmx::startsWith(param->val.u.s[i], svalue))
979         {
980             /* Check if there is a duplicate match */
981             if (match > 0)
982             {
983                 _gmx_selparser_error(scanner, "ambiguous value");
984                 return false;
985             }
986             match = i;
987         }
988         ++i;
989     }
990     if (match == 0)
991     {
992         _gmx_selparser_error(scanner, "invalid value");
993         return false;
994     }
995     param->val.u.s[0] = param->val.u.s[match];
996     return true;
997 }
998
999 /*! \brief
1000  * Replaces constant expressions with their values.
1001  *
1002  * \param[in,out] values First element in the value list to process.
1003  */
1004 static void
1005 convert_const_values(SelectionParserValueList *values)
1006 {
1007     SelectionParserValueList::iterator value;
1008     for (value = values->begin(); value != values->end(); ++value)
1009     {
1010         if (value->hasExpressionValue() && value->expr->v.type != GROUP_VALUE &&
1011             value->expr->type == SEL_CONST)
1012         {
1013             SelectionTreeElementPointer expr = value->expr;
1014             switch (expr->v.type)
1015             {
1016                 case INT_VALUE:
1017                     *value = SelectionParserValue::createInteger(expr->v.u.i[0]);
1018                     break;
1019                 case REAL_VALUE:
1020                     *value = SelectionParserValue::createReal(expr->v.u.r[0]);
1021                     break;
1022                 case STR_VALUE:
1023                     *value = SelectionParserValue::createString(expr->v.u.s[0]);
1024                     break;
1025                 case POS_VALUE:
1026                     *value = SelectionParserValue::createPosition(expr->v.u.p->x[0]);
1027                     break;
1028                 default:
1029                     GMX_THROW(gmx::InternalError(
1030                                       "Unsupported constant expression value type"));
1031             }
1032         }
1033     }
1034 }
1035
1036 /*!
1037  * \param     pparams List of parameters from the selection parser.
1038  * \param[in] nparam  Number of parameters in \p params.
1039  * \param     params  Array of parameters to parse.
1040  * \param     root    Selection element to which child expressions are added.
1041  * \param[in] scanner Scanner data structure.
1042  * \returns   true if the parameters were parsed successfully, false otherwise.
1043  *
1044  * Initializes the \p params array based on the parameters in \p pparams.
1045  * See the documentation of \c gmx_ana_selparam_t for different options
1046  * available for parsing.
1047  *
1048  * The list \p pparams and any associated values are freed after the parameters
1049  * have been processed, no matter is there was an error or not.
1050  */
1051 bool
1052 _gmx_sel_parse_params(const SelectionParserParameterList &pparams,
1053                       int nparam, gmx_ana_selparam_t *params,
1054                       const SelectionTreeElementPointer &root, void *scanner)
1055 {
1056     gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
1057     gmx_ana_selparam_t          *oparam;
1058     bool                         bOk, rc;
1059     int                          i;
1060
1061     /* Check that the value pointers of SPAR_VARNUM parameters are NULL and
1062      * that they are not NULL for other parameters */
1063     bOk = true;
1064     for (i = 0; i < nparam; ++i)
1065     {
1066         std::string                contextStr = gmx::formatString("In parameter '%s'", params[i].name);
1067         gmx::MessageStringContext  context(errors, contextStr);
1068         if (params[i].val.type != POS_VALUE && (params[i].flags & (SPAR_VARNUM | SPAR_ATOMVAL)))
1069         {
1070             if (params[i].val.u.ptr != NULL)
1071             {
1072                 _gmx_selparser_error(scanner, "value pointer is not NULL "
1073                                      "although it should be for SPAR_VARNUM "
1074                                      "and SPAR_ATOMVAL parameters");
1075             }
1076             if ((params[i].flags & SPAR_VARNUM)
1077                 && (params[i].flags & SPAR_DYNAMIC) && !params[i].nvalptr)
1078             {
1079                 _gmx_selparser_error(scanner, "nvalptr is NULL but both "
1080                                      "SPAR_VARNUM and SPAR_DYNAMIC are specified");
1081                 bOk = false;
1082             }
1083         }
1084         else
1085         {
1086             if (params[i].val.u.ptr == NULL)
1087             {
1088                 _gmx_selparser_error(scanner, "value pointer is NULL");
1089                 bOk = false;
1090             }
1091         }
1092     }
1093     if (!bOk)
1094     {
1095         return false;
1096     }
1097     /* Parse the parameters */
1098     i = 0;
1099     SelectionParserParameterList::const_iterator pparam;
1100     for (pparam = pparams.begin(); pparam != pparams.end(); ++pparam)
1101     {
1102         std::string contextStr;
1103         /* Find the parameter and make some checks */
1104         if (!pparam->name().empty())
1105         {
1106             contextStr = gmx::formatString("In parameter '%s'", pparam->name().c_str());
1107             i          = -1;
1108             oparam     = gmx_ana_selparam_find(pparam->name().c_str(), nparam, params);
1109         }
1110         else if (i >= 0)
1111         {
1112             contextStr = gmx::formatString("In value %d", i + 1);
1113             oparam     = &params[i];
1114             if (oparam->name != NULL)
1115             {
1116                 oparam = NULL;
1117                 _gmx_selparser_error(scanner, "too many NULL parameters provided");
1118                 bOk = false;
1119                 continue;
1120             }
1121             ++i;
1122         }
1123         else
1124         {
1125             _gmx_selparser_error(scanner, "all NULL parameters should appear in the beginning of the list");
1126             bOk = false;
1127             continue;
1128         }
1129         gmx::MessageStringContext  context(errors, contextStr);
1130         if (!oparam)
1131         {
1132             _gmx_selparser_error(scanner, "unknown parameter skipped");
1133             bOk = false;
1134             continue;
1135         }
1136         if (oparam->val.type != NO_VALUE && pparam->values().empty())
1137         {
1138             _gmx_selparser_error(scanner, "no value provided");
1139             bOk = false;
1140             continue;
1141         }
1142         if (oparam->flags & SPAR_SET)
1143         {
1144             _gmx_selparser_error(scanner, "parameter set multiple times, extra values skipped");
1145             bOk = false;
1146             continue;
1147         }
1148         oparam->flags |= SPAR_SET;
1149         /* Process the values for the parameter */
1150         convert_const_values(pparam->values_.get());
1151         if (convert_values(pparam->values_.get(), oparam->val.type, scanner) != 0)
1152         {
1153             _gmx_selparser_error(scanner, "invalid value");
1154             bOk = false;
1155             continue;
1156         }
1157         if (oparam->val.type == NO_VALUE)
1158         {
1159             rc = parse_values_bool(pparam->name(), pparam->values(), oparam, scanner);
1160         }
1161         else if (oparam->flags & SPAR_RANGES)
1162         {
1163             rc = parse_values_range(pparam->values(), oparam, scanner);
1164         }
1165         else if (oparam->flags & SPAR_VARNUM)
1166         {
1167             if (pparam->values().size() == 1
1168                 && pparam->values().front().hasExpressionValue())
1169             {
1170                 rc = parse_values_varnum_expr(pparam->values(), oparam, root, scanner);
1171             }
1172             else
1173             {
1174                 rc = parse_values_varnum(pparam->values(), oparam, root, scanner);
1175             }
1176         }
1177         else if (oparam->flags & SPAR_ENUMVAL)
1178         {
1179             rc = parse_values_enum(pparam->values(), oparam, scanner);
1180         }
1181         else
1182         {
1183             rc = parse_values_std(pparam->values(), oparam, root, scanner);
1184         }
1185         if (!rc)
1186         {
1187             bOk = false;
1188         }
1189     }
1190     /* Check that all required parameters are present */
1191     for (i = 0; i < nparam; ++i)
1192     {
1193         if (!(params[i].flags & SPAR_OPTIONAL) && !(params[i].flags & SPAR_SET))
1194         {
1195             _gmx_selparser_error(scanner, "required parameter '%s' not specified", params[i].name);
1196             bOk = false;
1197         }
1198     }
1199
1200     return bOk;
1201 }