* Hence, all the selections should be parsed before the compiler can be
* called.
*
- * The compiler initializes all fields in \c t_selelem not initialized by
- * the parser: \c t_selelem::v (some fields have already been initialized by
- * the parser), \c t_selelem::evaluate, and \c t_selelem::u (again, some
- * elements have been initialized in the parser).
- * The \c t_selelem::cdata field is used during the compilation to store
+ * The compiler initializes all fields in gmx::SelectionTreeElement not
+ * initialized by the parser: gmx::SelectionTreeElement::v (some fields have
+ * already been initialized by the parser),
+ * gmx::SelectionTreeElement::evaluate, and gmx::SelectionTreeElement::u
+ * (again, some elements have been initialized in the parser).
+ * The gmx::SelectionTreeElement::cdata field is used during the compilation to store
* internal data, but the data is freed when the compiler returns.
*
* In addition to initializing the elements, the compiler reorganizes the tree
*
* The compiler is invoked using gmx::SelectionCompiler.
* The gmx::SelectionCompiler::compile() method does the compilation in several
- * passes over the \c t_selelem tree.
+ * passes over the gmx::SelectionTreeElement tree.
* -# Defaults are set for the position type and flags of position calculation
* methods that were not explicitly specified in the user input.
* -# Subexpressions are extracted: a separate root is created for each
* passes, because some flags are set recursively based on which elements
* refer to an element, and these flags need to be set to initialize
* other fields.
- * -# The \c t_selelem::evaluate field is set to the correct evaluation
- * function from evaluate.h.
+ * -# The gmx::SelectionTreeElement::evaluate field is set to the correct
+ * evaluation function from evaluate.h.
* .
* -# The evaluation function of all elements is replaced with the
* analyze_static() function to be able to initialize the element before
*
* After the compilation, the selection element tree is suitable for
* gmx_ana_selcollection_evaluate().
- * Enough memory has been allocated for \ref t_selelem::v
- * (and \ref t_selelem::cgrp for \ref SEL_SUBEXPR elements) to allow the
- * selection to be evaluated without allocating any memory.
+ * Enough memory has been allocated for gmx::SelectionTreeElement::v
+ * (and gmx::SelectionTreeElement::cgrp for \ref SEL_SUBEXPR elements) to allow
+ * the selection to be evaluated without allocating any memory.
*
*
* \subsection selcompiler_tree_root Root elements
* These are used for two purposes:
* -# A selection that should be evaluated.
* These elements appear in the same order as the selections in the input.
- * For these elements, \ref t_selelem::v has been set to the maximum
- * possible group that the selection can evaluate to (only for dynamic
- * selections), and \ref t_selelem::cgrp has been set to use a NULL group
- * for evaluation.
+ * For these elements, gmx::SelectionTreeElement::v has been set to the
+ * maximum possible group that the selection can evaluate to (only for
+ * dynamic selections), and gmx::SelectionTreeElement::cgrp has been set to
+ * use a NULL group for evaluation.
* -# A subexpression that appears in one or more selections.
* Each selection that gives a value for a method parameter is a
* potential subexpression, as is any variable value.
* Only subexpressions that require evaluation for each frame are left
* after the selection is compiled.
* Each subexpression appears in the chain before any references to it.
- * For these elements, \c t_selelem::cgrp has been set to the group
- * that should be used to evaluate the subexpression.
- * If \c t_selelem::cgrp is empty, the total evaluation group is not known
- * in advance or it is more efficient to evaluate the subexpression only
- * when it is referenced. If this is the case, \c t_selelem::evaluate is
- * also NULL.
+ * For these elements, gmx::SelectionTreeElement::cgrp has been set to the
+ * group that should be used to evaluate the subexpression.
+ * If gmx::SelectionTreeElement::cgrp is empty, the total evaluation group
+ * is not known in advance or it is more efficient to evaluate the
+ * subexpression only when it is referenced. If this is the case,
+ * gmx::SelectionTreeElement::evaluate is also NULL.
*
* The children of the \ref SEL_ROOT elements can be used to distinguish
* the two types of root elements from each other; the rules are the same
* replaced with \ref SEL_CONST elements.
* Constant elements from the parser are also retained if present in
* dynamic parts of the selections.
- * Several constant elements with a NULL \c t_selelem::evaluate are left for
- * debugging purposes; of these, only the ones for \ref BOOL_OR expressions are
- * used during evaluation.
+ * Several constant elements with a NULL gmx::SelectionTreeElement::evaluate
+ * are left for debugging purposes; of these, only the ones for \ref BOOL_OR
+ * expressions are used during evaluation.
*
- * The value is stored in \c t_selelem::v, and for group values with an
- * evaluation function set, also in \c t_selelem::cgrp.
+ * The value is stored in gmx::SelectionTreeElement::v, and for group values
+ * with an evaluation function set, also in gmx::SelectionTreeElement::cgrp.
* For \ref GROUP_VALUE elements, unnecessary atoms (i.e., atoms that
* could never be selected) have been removed from the value.
*
* \subsection selcompiler_tree_method Method evaluation elements
*
* All selection methods that need to be evaluated dynamically are described
- * by a \ref SEL_EXPRESSION element. The \c t_selelem::method and
- * \c t_selelem::mdata fields have already been initialized by the parser,
+ * by a \ref SEL_EXPRESSION element. The gmx::SelectionTreeElement::method and
+ * gmx::SelectionTreeElement::mdata fields have already been initialized by the parser,
* and the compiler only calls the initialization functions in the method
* data structure to do some additional initialization of these fields at
- * appropriate points. If the \c t_selelem::pc data field has been created by
- * the parser, the compiler initializes the data structure properly once the
- * required positions are known. If the \c t_selelem::pc field is NULL after
- * the parser, but the method provides only sel_updatefunc_pos(), an
- * appropriate position calculation data structure is created.
- * If \c t_selelem::pc is not NULL, \c t_selelem::pos is also initialized
- * to hold the positions calculated.
+ * appropriate points. If the gmx::SelectionTreeElement::pc data field has been
+ * created by the parser, the compiler initializes the data structure properly
+ * once the required positions are known. If the gmx::SelectionTreeElement::pc
+ * field is NULL after the parser, but the method provides only
+ * sel_updatefunc_pos(), an appropriate position calculation data structure is
+ * created. If gmx::SelectionTreeElement::pc is not NULL,
+ * gmx::SelectionTreeElement::pos is also initialized to hold the positions
+ * calculated.
*
* Children of these elements are of type \ref SEL_SUBEXPRREF, and describe
* parameter values that need to be evaluated for each frame. See the next
* help in debugging.
*
* For \ref SEL_SUBEXPR elements, memory has been allocated for
- * \c t_selelem::cgrp to store the group for which the expression has been
- * evaluated during the current frame. This is only done if full subexpression
- * evaluation by _gmx_sel_evaluate_subexpr() is needed; the other evaluation
- * functions do not require this memory.
+ * gmx::SelectionTreeElement::cgrp to store the group for which the expression
+ * has been evaluated during the current frame. This is only done if full
+ * subexpression evaluation by _gmx_sel_evaluate_subexpr() is needed; the other
+ * evaluation functions do not require this memory.
*
* \ref SEL_SUBEXPRREF elements are used to describe references to
* subexpressions. They have always a single child, which is the
#include "selelem.h"
using std::min;
+using gmx::SelectionTreeElement;
+using gmx::SelectionTreeElementPointer;
/*! \internal \brief
* Compiler flags.
typedef struct t_compiler_data
{
/** The real evaluation method. */
- sel_evalfunc evaluate;
+ gmx::sel_evalfunc evaluate;
/** Number of references to a \ref SEL_SUBEXPR element. */
int refcount;
/** Flags for specifying how to treat this element during compilation. */
* Helper method for printing out debug information about a min/max group.
*/
static void
-print_group_info(FILE *fp, const char *name, t_selelem *sel, gmx_ana_index_t *g)
+print_group_info(FILE *fp, const char *name,
+ const SelectionTreeElement &sel,
+ gmx_ana_index_t *g)
{
fprintf(fp, " %s=", name);
if (!g)
{
fprintf(fp, "(null)");
}
- else if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
+ else if (sel.cdata->flags & SEL_CDATA_MINMAXALLOC)
{
fprintf(fp, "(%d atoms, %p)", g->isize, (void*)g);
}
- else if (sel->v.type == GROUP_VALUE && g == sel->v.u.g)
+ else if (sel.v.type == GROUP_VALUE && g == sel.v.u.g)
{
fprintf(fp, "(static, %p)", (void*)g);
}
* \param[in] level Indentation level, starting from zero.
*/
void
-_gmx_selelem_print_compiler_info(FILE *fp, t_selelem *sel, int level)
+_gmx_selelem_print_compiler_info(FILE *fp, const SelectionTreeElement &sel,
+ int level)
{
- if (!sel->cdata)
+ if (!sel.cdata)
{
return;
}
fprintf(fp, "%*c cdata: flg=", level*2+1, ' ');
- if (sel->cdata->flags & SEL_CDATA_FULLEVAL)
+ if (sel.cdata->flags & SEL_CDATA_FULLEVAL)
{
fprintf(fp, "F");
}
- if (!(sel->cdata->flags & SEL_CDATA_STATIC))
+ if (!(sel.cdata->flags & SEL_CDATA_STATIC))
{
fprintf(fp, "D");
}
- if (sel->cdata->flags & SEL_CDATA_STATICEVAL)
+ if (sel.cdata->flags & SEL_CDATA_STATICEVAL)
{
fprintf(fp, "S");
}
- if (sel->cdata->flags & SEL_CDATA_EVALMAX)
+ if (sel.cdata->flags & SEL_CDATA_EVALMAX)
{
fprintf(fp, "M");
}
- if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
+ if (sel.cdata->flags & SEL_CDATA_MINMAXALLOC)
{
fprintf(fp, "A");
}
- if (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
+ if (sel.cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
{
fprintf(fp, "Ss");
}
- if (sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
+ if (sel.cdata->flags & SEL_CDATA_COMMONSUBEXPR)
{
fprintf(fp, "Sc");
}
- if (!sel->cdata->flags)
+ if (!sel.cdata->flags)
{
fprintf(fp, "0");
}
- if (sel->cdata->refcount > 0)
+ if (sel.cdata->refcount > 0)
{
- fprintf(fp, " refc=%d", sel->cdata->refcount);
+ fprintf(fp, " refc=%d", sel.cdata->refcount);
}
fprintf(fp, " eval=");
- _gmx_sel_print_evalfunc_name(fp, sel->cdata->evaluate);
- print_group_info(fp, "gmin", sel, sel->cdata->gmin);
- print_group_info(fp, "gmax", sel, sel->cdata->gmax);
+ _gmx_sel_print_evalfunc_name(fp, sel.cdata->evaluate);
+ print_group_info(fp, "gmin", sel, sel.cdata->gmin);
+ print_group_info(fp, "gmax", sel, sel.cdata->gmax);
fprintf(fp, "\n");
}
-/*!
- * \param sel Selection to free.
- *
- * This function only frees the data for the given selection, not its children.
- * It is safe to call the function when compiler data has not been allocated
- * or has already been freed; in such a case, nothing is done.
- */
-void
-_gmx_selelem_free_compiler_data(t_selelem *sel)
+namespace gmx
+{
+
+void SelectionTreeElement::freeCompilerData()
{
- if (sel->cdata)
+ if (cdata)
{
- sel->evaluate = sel->cdata->evaluate;
- if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
+ evaluate = cdata->evaluate;
+ if (cdata->flags & SEL_CDATA_MINMAXALLOC)
{
- sel->cdata->gmin->name = NULL;
- sel->cdata->gmax->name = NULL;
- gmx_ana_index_deinit(sel->cdata->gmin);
- gmx_ana_index_deinit(sel->cdata->gmax);
- sfree(sel->cdata->gmin);
- sfree(sel->cdata->gmax);
+ cdata->gmin->name = NULL;
+ cdata->gmax->name = NULL;
+ gmx_ana_index_deinit(cdata->gmin);
+ gmx_ana_index_deinit(cdata->gmax);
+ sfree(cdata->gmin);
+ sfree(cdata->gmax);
}
- sfree(sel->cdata);
+ sfree(cdata);
}
- sel->cdata = NULL;
+ cdata = NULL;
}
+} // namespace gmx
+
/*! \brief
* Allocates memory for storing the evaluated value of a selection element.
*
* maximum of the \p isize values can be stored.
*/
static void
-alloc_selection_data(t_selelem *sel, int isize, bool bChildEval)
+alloc_selection_data(const SelectionTreeElementPointer &sel,
+ int isize, bool bChildEval)
{
int nalloc;
}
else /* sel->flags should contain SEL_VARNUMVAL */
{
- t_selelem *child;
-
if (!bChildEval)
{
return;
}
- child = sel;
+ SelectionTreeElementPointer child = sel;
if (sel->type == SEL_SUBEXPRREF)
{
GMX_RELEASE_ASSERT(sel->child && sel->child->type == SEL_SUBEXPR,
* \param[in] eval The new evaluation function.
*/
static void
-set_evaluation_function(t_selelem *sel, sel_evalfunc eval)
+set_evaluation_function(const SelectionTreeElementPointer &sel,
+ gmx::sel_evalfunc eval)
{
sel->evaluate = eval;
if (sel->type != SEL_SUBEXPRREF)
{
- t_selelem *child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
set_evaluation_function(child, eval);
* for, or NULL if the element is an internal element.
*/
static void
-init_pos_keyword_defaults(t_selelem *root, const char *spost, const char *rpost,
+init_pos_keyword_defaults(SelectionTreeElement *root,
+ const char *spost, const char *rpost,
const gmx::internal::SelectionData *sel)
{
/* Selections use largest static group by default, while
sel = NULL;
}
/* Recurse into children */
- t_selelem *child = root->child;
+ SelectionTreeElementPointer child = root->child;
while (child)
{
- init_pos_keyword_defaults(child, spost, rpost, sel);
+ init_pos_keyword_defaults(child.get(), spost, rpost, sel);
child = child->next;
}
}
* \param root First selection in the whole selection chain.
* \returns The new first element for the chain.
*/
-static t_selelem *
-reverse_selelem_chain(t_selelem *root)
+static SelectionTreeElementPointer
+reverse_selelem_chain(const SelectionTreeElementPointer &root)
{
- t_selelem *item;
- t_selelem *prev;
- t_selelem *next;
-
- prev = NULL;
- item = root;
+ SelectionTreeElementPointer prev;
+ SelectionTreeElementPointer item = root;
while (item)
{
- next = item->next;
+ SelectionTreeElementPointer next = item->next;
item->next = prev;
prev = item;
item = next;
* The elements are processed in reverse order to correctly detect
* subexpressions only referred to by other subexpressions.
*/
-static t_selelem *
-remove_unused_subexpressions(t_selelem *root)
+static SelectionTreeElementPointer
+remove_unused_subexpressions(SelectionTreeElementPointer root)
{
- t_selelem *item;
- t_selelem *prev;
- t_selelem *next;
-
- if (root == NULL)
+ if (!root)
{
- return NULL;
+ return SelectionTreeElementPointer();
}
root = reverse_selelem_chain(root);
- while (root->child->type == SEL_SUBEXPR && root->child->refcount == 1)
+ while (root->child->type == SEL_SUBEXPR && root->child.unique())
{
- next = root->next;
- _gmx_selelem_free(root);
- root = next;
+ // Frees the root element.
+ root = root->next;
}
- prev = root;
- item = root->next;
+ SelectionTreeElementPointer prev = root;
+ SelectionTreeElementPointer item = root->next;
while (item)
{
- next = item->next;
- if (item->child->type == SEL_SUBEXPR && item->child->refcount == 1)
+ SelectionTreeElementPointer next = item->next;
+ if (item->child->type == SEL_SUBEXPR && item->child.unique())
{
+ // Frees the current item when it goes out of scope.
prev->next = next;
- _gmx_selelem_free(item);
}
else
{
*
* The name of the selection becomes "SubExpr N", where N is \p i;
* Memory is allocated for the name and the name is stored both in
- * \c t_selelem::name and \c t_selelem::u::cgrp::name; the latter
+ * gmx::SelectionTreeElement::name and gmx::SelectionTreeElement::u::cgrp::name; the latter
* is freed by _gmx_selelem_free().
*/
static void
-create_subexpression_name(t_selelem *sel, int i)
+create_subexpression_name(const SelectionTreeElementPointer &sel, int i)
{
char *name = strdup(gmx::formatString("SubExpr %d", i).c_str());
* that contain the subexpression as their children and returns the first
* of these root elements.
*/
-static t_selelem *
-extract_item_subselections(t_selelem *sel, int *subexprn)
+static SelectionTreeElementPointer
+extract_item_subselections(const SelectionTreeElementPointer &sel,
+ int *subexprn)
{
- t_selelem *root;
- t_selelem *subexpr;
- t_selelem *child;
+ SelectionTreeElementPointer root;
+ SelectionTreeElementPointer subexpr;
+ SelectionTreeElementPointer child = sel->child;
- root = subexpr = NULL;
- child = sel->child;
while (child)
{
if (!root)
/* Create the root element for the subexpression */
if (!root)
{
- root = subexpr = _gmx_selelem_create(SEL_ROOT);
+ root.reset(new SelectionTreeElement(SEL_ROOT));
+ subexpr = root;
}
else
{
- subexpr->next = _gmx_selelem_create(SEL_ROOT);
- subexpr = subexpr->next;
+ subexpr->next.reset(new SelectionTreeElement(SEL_ROOT));
+ subexpr = subexpr->next;
}
/* Create the subexpression element and/or
* move the actual subexpression under the created element. */
if (child->child->type != SEL_SUBEXPR)
{
- subexpr->child = _gmx_selelem_create(SEL_SUBEXPR);
+ subexpr->child.reset(new SelectionTreeElement(SEL_SUBEXPR));
_gmx_selelem_set_vtype(subexpr->child, child->v.type);
subexpr->child->child = child->child;
child->child = subexpr->child;
subexpr->child = child->child;
}
create_subexpression_name(subexpr->child, ++*subexprn);
- subexpr->child->refcount++;
/* Set the flags for the created elements */
subexpr->flags |= (child->flags & SEL_VALFLAGMASK);
subexpr->child->flags |= (child->flags & SEL_VALFLAGMASK);
* and inserted into the selection chain before the expressions that
* refer to them.
*/
-static t_selelem *
-extract_subexpressions(t_selelem *sel)
+static SelectionTreeElementPointer
+extract_subexpressions(SelectionTreeElementPointer sel)
{
- t_selelem *root, *item, *next;
- int subexprn;
-
- subexprn = 0;
- root = NULL;
- next = sel;
+ SelectionTreeElementPointer root;
+ SelectionTreeElementPointer next = sel;
+ int subexprn = 0;
while (next)
{
- item = extract_item_subselections(next, &subexprn);
+ SelectionTreeElementPointer item
+ = extract_item_subselections(next, &subexprn);
if (item)
{
if (!root)
* a single OR operation with three operands).
*/
static void
-optimize_boolean_expressions(t_selelem *sel)
+optimize_boolean_expressions(const SelectionTreeElementPointer &sel)
{
- t_selelem *child, *prev;
-
/* Do recursively for children */
if (sel->type != SEL_SUBEXPRREF)
{
- prev = NULL;
- child = sel->child;
+ SelectionTreeElementPointer prev;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
optimize_boolean_expressions(child);
prev = prev->next;
}
child->child->child->next = child->next;
- /* Remove the two negations */
- child->child->child = NULL;
- child->next = NULL;
- _gmx_selelem_free(child);
+ // Discards the two negations.
child = prev;
}
prev = child;
return;
}
/* Merge subsequent binary operations */
- prev = NULL;
- child = sel->child;
+ SelectionTreeElementPointer prev;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
if (child->type == SEL_BOOLEAN && child->u.boolt == sel->u.boolt)
prev = prev->next;
}
prev->next = child->next;
- sfree(child->v.u.g);
- sfree(child);
+ // Discards the old child.
child = prev->next;
}
else
* The same is true for the dynamic expressions.
*/
static void
-reorder_boolean_static_children(t_selelem *sel)
+reorder_boolean_static_children(const SelectionTreeElementPointer &sel)
{
- t_selelem *child, *prev, *next;
-
/* Do recursively for children */
if (sel->type != SEL_SUBEXPRREF)
{
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
reorder_boolean_static_children(child);
/* Reorder boolean expressions such that static selections come first */
if (sel->type == SEL_BOOLEAN && (sel->flags & SEL_DYNAMIC))
{
- t_selelem start;
-
- start.next = sel->child;
- prev = &start;
- child = &start;
+ // Add a dummy head element that precedes the first child.
+ SelectionTreeElementPointer dummy(
+ new SelectionTreeElement(SEL_BOOLEAN));
+ dummy->next = sel->child;
+ SelectionTreeElementPointer prev = dummy;
+ SelectionTreeElementPointer child = dummy;
while (child->next)
{
/* child is the last handled static expression */
/* prev is the last handled non-static expression */
- next = prev->next;
+ SelectionTreeElementPointer next = prev->next;
while (next && (next->flags & SEL_DYNAMIC))
{
prev = next;
child = next;
}
- sel->child = start.next;
+ sel->child = dummy->next;
}
}
* within arithmetic expressions.
*/
static void
-optimize_arithmetic_expressions(t_selelem *sel)
+optimize_arithmetic_expressions(const SelectionTreeElementPointer &sel)
{
- t_selelem *child;
-
/* Do recursively for children. */
if (sel->type != SEL_SUBEXPRREF)
{
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
optimize_arithmetic_expressions(child);
}
/* Convert integer constants to reals. */
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
if (child->v.type == INT_VALUE)
*
* \param[in,out] sel Root of the selection subtree to process.
*
- * This function sets the evaluation function (\c t_selelem::evaluate)
- * for the selection elements.
+ * This function sets the evaluation function
+ * (gmx::SelectionTreeElement::evaluate) for the selection elements.
*/
static void
-init_item_evalfunc(t_selelem *sel)
+init_item_evalfunc(const SelectionTreeElementPointer &sel)
{
/* Process children. */
if (sel->type != SEL_SUBEXPRREF)
{
- t_selelem *child;
-
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
init_item_evalfunc(child);
* \param[in] mempool Memory pool to use.
*/
static void
-setup_memory_pooling(t_selelem *sel, gmx_sel_mempool_t *mempool)
+setup_memory_pooling(const SelectionTreeElementPointer &sel,
+ gmx_sel_mempool_t *mempool)
{
if (sel->type != SEL_SUBEXPRREF)
{
- t_selelem *child;
-
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
if ((sel->type == SEL_BOOLEAN && (child->flags & SEL_DYNAMIC))
* structure if required.
*/
static void
-init_item_evaloutput(t_selelem *sel)
+init_item_evaloutput(const SelectionTreeElementPointer &sel)
{
GMX_ASSERT(!(sel->child == NULL &&
(sel->type == SEL_SUBEXPRREF || sel->type == SEL_SUBEXPR)),
/* Process children. */
if (sel->type != SEL_SUBEXPRREF)
{
- t_selelem *child;
-
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
init_item_evaloutput(child);
if (sel->v.u.ptr)
{
_gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
- _gmx_selelem_free_values(sel->child->child);
+ sel->child->child->freeValues();
sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
sel->child->child->flags |= (sel->flags & SEL_ALLOCDATA);
_gmx_selvalue_setstore(&sel->child->child->v, sel->v.u.ptr);
* \param sel Root of the selection subtree to process.
*/
static void
-init_item_compilerdata(t_selelem *sel)
+init_item_compilerdata(const SelectionTreeElementPointer &sel)
{
- t_selelem *child;
-
/* Allocate the compiler data structure */
snew(sel->cdata, 1);
* access its compilation flags.*/
if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
{
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
if (!(child->flags & SEL_ATOMVAL) && child->child)
/* Initialize children */
if (sel->type != SEL_SUBEXPRREF)
{
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
init_item_compilerdata(child);
bool bEvalMax;
bEvalMax = (sel->u.boolt == BOOL_AND);
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
if (bEvalMax)
else if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER
|| sel->type == SEL_SUBEXPR)
{
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
child->cdata->flags |= SEL_CDATA_EVALMAX;
* reorder_boolean_static_children() should have been called.
*/
static void
-init_item_staticeval(t_selelem *sel)
+init_item_staticeval(const SelectionTreeElementPointer &sel)
{
- t_selelem *child;
-
/* Subexpressions with full evaluation should always have bStaticEval,
* so don't do anything if a reference to them is encountered. */
if (sel->type == SEL_SUBEXPRREF
/* Propagate the bStaticEval flag to children if it is not set */
if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
{
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
if ((sel->type != SEL_EXPRESSION && sel->type != SEL_MODIFIER)
* expression should not have bStaticEval. */
if (sel->type == SEL_BOOLEAN)
{
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child && !(child->flags & SEL_DYNAMIC))
{
child = child->next;
}
/* Process the children */
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
init_item_staticeval(child);
* \param sel Root of the selection subtree to process.
*/
static void
-init_item_subexpr_refcount(t_selelem *sel)
+init_item_subexpr_refcount(const SelectionTreeElementPointer &sel)
{
// Reset the counter when the subexpression is first encountered.
if (sel->type == SEL_ROOT && sel->child->type == SEL_SUBEXPR
}
else
{
- t_selelem *child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
init_item_subexpr_refcount(child);
* \param sel Root of the selection subtree to process.
*/
static void
-init_item_subexpr_flags(t_selelem *sel)
+init_item_subexpr_flags(const SelectionTreeElementPointer &sel)
{
if (sel->type == SEL_SUBEXPR)
{
|| ((sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
&& !(sel->child->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)))
{
- t_selelem *child = sel->child;
-
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
if (!(child->cdata->flags & SEL_CDATA_COMMONSUBEXPR))
* \param sel Root of the selection subtree to process.
*/
static void
-init_item_minmax_groups(t_selelem *sel)
+init_item_minmax_groups(const SelectionTreeElementPointer &sel)
{
/* Process children. */
if (sel->type != SEL_SUBEXPRREF)
{
- t_selelem *child;
-
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
init_item_minmax_groups(child);
static void
initialize_evalgrps(gmx_ana_selcollection_t *sc)
{
- t_selelem *root;
-
- root = sc->root;
+ SelectionTreeElementPointer root = sc->root;
while (root)
{
- GMX_RELEASE_ASSERT(root->child != NULL,
+ GMX_RELEASE_ASSERT(root->child,
"Root elements should always have a child");
if (root->child->type != SEL_SUBEXPR
|| (root->child->cdata->flags & SEL_CDATA_FULLEVAL))
* are evaluated for each atom.
*/
static void
-mark_subexpr_dynamic(t_selelem *sel, bool bDynamic)
+mark_subexpr_dynamic(const SelectionTreeElementPointer &sel,
+ bool bDynamic)
{
- t_selelem *child;
-
if (!bDynamic && !(sel->flags & SEL_DYNAMIC))
{
sel->cdata->flags |= SEL_CDATA_STATIC;
{
sel->cdata->flags &= ~SEL_CDATA_STATIC;
}
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
if (sel->type != SEL_EXPRESSION || child->type != SEL_SUBEXPRREF
* function. Later compilation passes remove the stub elements.
*/
static void
-release_subexpr_memory(t_selelem *sel)
+release_subexpr_memory(const SelectionTreeElementPointer &sel)
{
- if (sel->type == SEL_SUBEXPR)
+ if (sel->type == SEL_SUBEXPRREF)
{
- if (sel->refcount == 2)
+ const SelectionTreeElementPointer &subexpr = sel->child;
+ if (subexpr.use_count() == 2)
{
- release_subexpr_memory(sel->child);
- sel->name = NULL;
- _gmx_selelem_free_chain(sel->child);
- _gmx_selelem_free_values(sel);
- _gmx_selelem_free_exprdata(sel);
- _gmx_selelem_free_compiler_data(sel);
- sel->child = NULL;
+ release_subexpr_memory(subexpr);
+ subexpr->name = NULL;
+ // Free children.
+ subexpr->child.reset();
+ subexpr->freeValues();
+ subexpr->freeExpressionData();
+ subexpr->freeCompilerData();
}
}
else
{
- t_selelem *child;
-
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
release_subexpr_memory(child);
* deleted.
*/
static void
-make_static(t_selelem *sel)
+make_static(const SelectionTreeElementPointer &sel)
{
/* If this is a subexpression reference and the data is stored in the
* child, we transfer data ownership before doing anything else. */
}
/* Free the children. */
release_subexpr_memory(sel);
- _gmx_selelem_free_chain(sel->child);
- sel->child = NULL;
+ sel->child.reset();
/* Free the expression data as it is no longer needed */
- _gmx_selelem_free_exprdata(sel);
+ sel->freeExpressionData();
/* Make the item static */
sel->name = NULL;
sel->type = SEL_CONST;
sel->evaluate = NULL;
sel->cdata->evaluate = NULL;
/* Set the group value.
- * free_exprdata above frees the cgrp group, so we can just override it. */
+ * freeExpressionData() frees the cgrp group, so we can just override it.
+ * */
if (sel->v.type == GROUP_VALUE)
{
gmx_ana_index_set(&sel->u.cgrp, sel->v.u.g->isize, sel->v.u.g->index, NULL, 0);
* \returns 0 on success, a non-zero error code on error.
*/
static void
-process_const(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+process_const(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g)
{
if (sel->v.type == GROUP_VALUE)
{
* \ref SPAR_ATOMVAL, the function returns immediately.
*/
static void
-store_param_val(t_selelem *sel)
+store_param_val(const SelectionTreeElementPointer &sel)
{
/* Return immediately if there is no parameter. */
if (sel->type != SEL_SUBEXPRREF || !sel->u.param)
* is prevented by using \ref SEL_METHODINIT and \ref SEL_OUTINIT flags.
*/
static void
-init_method(t_selelem *sel, t_topology *top, int isize)
+init_method(const SelectionTreeElementPointer &sel, t_topology *top, int isize)
{
- t_selelem *child;
- bool bAtomVal;
-
/* Find out whether there are any atom-valued parameters */
- bAtomVal = false;
- child = sel->child;
+ bool bAtomVal = false;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
if (child->flags & SEL_ATOMVAL)
* reorder_item_static_children() should have been called.
*/
static void
-evaluate_boolean_static_part(gmx_sel_evaluate_t *data, t_selelem *sel,
+evaluate_boolean_static_part(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
gmx_ana_index_t *g)
{
- t_selelem *child, *next;
-
/* Find the last static subexpression */
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child->next && (child->next->cdata->flags & SEL_CDATA_STATIC))
{
child = child->next;
/* Evalute the static part if there is more than one expression */
if (child != sel->child)
{
- next = child->next;
- child->next = NULL;
+ SelectionTreeElementPointer next = child->next;
+ child->next.reset();
sel->cdata->evaluate(data, sel, g);
/* Replace the subexpressions with the result */
- _gmx_selelem_free_chain(sel->child);
- snew(child, 1);
- child->type = SEL_CONST;
+ child.reset(new SelectionTreeElement(SEL_CONST));
child->flags = SEL_FLAGSSET | SEL_SINGLEVAL | SEL_ALLOCVAL | SEL_ALLOCDATA;
_gmx_selelem_set_vtype(child, GROUP_VALUE);
child->evaluate = NULL;
child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
child->cdata->flags |= sel->cdata->flags & SEL_CDATA_STATICEVAL;
child->next = next;
+ // Frees the old static subexpressions.
sel->child = child;
}
else if (child->evaluate)
* problem.
*/
static void
-evaluate_boolean_minmax_grps(t_selelem *sel, gmx_ana_index_t *g,
+evaluate_boolean_minmax_grps(const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g,
gmx_ana_index_t *gmin, gmx_ana_index_t *gmax)
{
- t_selelem *child;
+ SelectionTreeElementPointer child;
switch (sel->u.boolt)
{
* \param[in] g Group for which \p sel should be evaluated.
* \returns 0 on success, a non-zero error code on error.
*
- * This function is used as the replacement for the \c t_selelem::evaluate
- * function pointer.
+ * This function is used as the replacement for the
+ * gmx::SelectionTreeElement::evaluate function pointer.
* It does the single most complex task in the compiler: after all elements
* have been processed, the \p gmin and \p gmax fields of \p t_compiler_data
* have been properly initialized, enough memory has been allocated for
* once and whose evaluation group is not known in advance.
*/
static void
-analyze_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+analyze_static(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g)
{
bool bDoMinMax;
* evaluation group.
*/
static void
-init_root_item(t_selelem *root, gmx_ana_index_t *gall)
+init_root_item(const SelectionTreeElementPointer &root,
+ gmx_ana_index_t *gall)
{
- t_selelem *expr;
- char *name;
-
- expr = root->child;
+ const SelectionTreeElementPointer &expr = root->child;
/* Subexpressions with non-static evaluation group should not be
* evaluated by the root, and neither should be single-reference
* subexpressions that don't evaluate for all atoms. */
}
/* Set the evaluation group */
- name = root->u.cgrp.name;
+ char *name = root->u.cgrp.name;
if (root->evaluate)
{
/* Non-atom-valued non-group expressions don't care about the group, so
* element (unused otherwise). */
if (expr->type != SEL_SUBEXPR && expr->v.u.p->g)
{
- t_selelem *child = expr;
+ SelectionTreeElementPointer child = expr;
/* TODO: This code is copied from parsetree.c; it would be better
* to have this hardcoded only in one place. */
* referenced once.
*/
static void
-postprocess_item_subexpressions(t_selelem *sel)
+postprocess_item_subexpressions(const SelectionTreeElementPointer &sel)
{
GMX_ASSERT(!(sel->child == NULL &&
(sel->type == SEL_SUBEXPRREF || sel->type == SEL_SUBEXPR)),
/* Process children. */
if (sel->type != SEL_SUBEXPRREF)
{
- t_selelem *child;
-
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
postprocess_item_subexpressions(child);
sel->evaluate = &_gmx_sel_evaluate_subexpr_staticeval;
sel->cdata->evaluate = sel->evaluate;
- _gmx_selelem_free_values(sel->child);
+ sel->child->freeValues();
sel->child->mempool = NULL;
_gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
* the method also defines the \c gmx_ana_selmethod_t::update method.
*/
static void
-init_item_comg(t_selelem *sel, gmx::PositionCalculationCollection *pcc,
+init_item_comg(const SelectionTreeElementPointer &sel,
+ gmx::PositionCalculationCollection *pcc,
e_poscalc_t type, int flags)
{
- t_selelem *child;
-
/* Initialize COM calculation for dynamic selections now that we know the maximal evaluation group */
if (sel->type == SEL_EXPRESSION && sel->u.expr.method
&& sel->u.expr.method->pupdate)
/* Call recursively for all children unless the children have already been processed */
if (sel->type != SEL_SUBEXPRREF)
{
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
init_item_comg(child, pcc, type, flags);
* Frees the data allocated for the compilation process.
*/
static void
-free_item_compilerdata(t_selelem *sel)
+free_item_compilerdata(const SelectionTreeElementPointer &sel)
{
- t_selelem *child;
-
/* Free compilation data */
- _gmx_selelem_free_compiler_data(sel);
+ sel->freeCompilerData();
/* Call recursively for all children unless the children have already been processed */
if (sel->type != SEL_SUBEXPRREF)
{
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
free_item_compilerdata(child);
{
gmx_ana_selcollection_t *sc = &coll->impl_->sc_;
gmx_sel_evaluate_t evaldata;
- t_selelem *item;
+ SelectionTreeElementPointer item;
e_poscalc_t post;
size_t i;
int flags;
for (i = 0; i < sc->sel.size(); ++i)
{
gmx::internal::SelectionData &sel = *sc->sel[i];
- init_pos_keyword_defaults(sel.rootElement(),
+ init_pos_keyword_defaults(&sel.rootElement(),
coll->impl_->spost_.c_str(),
coll->impl_->rpost_.c_str(),
&sel);
#include <string.h>
-#include "maths.h"
-#include "smalloc.h"
-#include "vec.h"
+#include "gromacs/legacyheaders/maths.h"
+#include "gromacs/legacyheaders/smalloc.h"
+#include "gromacs/legacyheaders/vec.h"
#include "gromacs/selection/indexutil.h"
#include "gromacs/selection/poscalc.h"
#include "selectioncollection-impl.h"
#include "selelem.h"
+using gmx::SelectionTreeElement;
+using gmx::SelectionTreeElementPointer;
+
namespace
{
{
public:
//! Constructs a reserver without initial reservation.
- MempoolSelelemReserver() : sel_(NULL) {}
+ MempoolSelelemReserver() {}
/*! \brief
* Constructs a reserver with initial reservation.
*
*
* \see reserve()
*/
- MempoolSelelemReserver(t_selelem *sel, int count)
- : sel_(NULL)
+ MempoolSelelemReserver(const SelectionTreeElementPointer &sel, int count)
{
reserve(sel, count);
}
//! Frees any memory allocated using this reserver.
~MempoolSelelemReserver()
{
- if (sel_ != NULL)
+ if (sel_)
{
- _gmx_selelem_mempool_release(sel_);
+ sel_->mempoolRelease();
}
}
* memory pool. Type of values to allocate is automatically determined
* from \p sel.
*/
- void reserve(t_selelem *sel, int count)
+ void reserve(const SelectionTreeElementPointer &sel, int count)
{
- GMX_RELEASE_ASSERT(sel_ == NULL, "Can only reserve one element with one instance");
- _gmx_selelem_mempool_reserve(sel, count);
+ GMX_RELEASE_ASSERT(!sel_,
+ "Can only reserve one element with one instance");
+ sel->mempoolReserve(count);
sel_ = sel;
}
private:
- t_selelem *sel_;
+ SelectionTreeElementPointer sel_;
};
/*! \internal \brief
public:
//! Constructs an assigner without an initial assignment.
SelelemTemporaryValueAssigner()
- : sel_(NULL), old_ptr_(NULL), old_nalloc_(0)
+ : old_ptr_(NULL), old_nalloc_(0)
{
}
/*! \brief
*
* \see assign()
*/
- SelelemTemporaryValueAssigner(t_selelem *sel, t_selelem *vsource)
- : sel_(NULL)
+ SelelemTemporaryValueAssigner(const SelectionTreeElementPointer &sel,
+ const SelectionTreeElement &vsource)
{
assign(sel, vsource);
}
//! Undoes any temporary assignment done using this assigner.
~SelelemTemporaryValueAssigner()
{
- if (sel_ != NULL)
+ if (sel_)
{
_gmx_selvalue_setstore_alloc(&sel_->v, old_ptr_, old_nalloc_);
}
* \p vsource, i.e., any access/modification to values in \p sel
* actually accesses values in \p vsource.
*/
- void assign(t_selelem *sel, t_selelem *vsource)
+ void assign(const SelectionTreeElementPointer &sel,
+ const SelectionTreeElement &vsource)
{
- GMX_RELEASE_ASSERT(sel_ == NULL,
+ GMX_RELEASE_ASSERT(!sel_,
"Can only assign one element with one instance");
- GMX_RELEASE_ASSERT(sel->v.type == vsource->v.type,
+ GMX_RELEASE_ASSERT(sel->v.type == vsource.v.type,
"Mismatching selection value types");
old_ptr_ = sel->v.u.ptr;
old_nalloc_ = sel->v.nalloc;
- _gmx_selvalue_setstore(&sel->v, vsource->v.u.ptr);
+ _gmx_selvalue_setstore(&sel->v, vsource.v.u.ptr);
sel_ = sel;
}
private:
- t_selelem *sel_;
- void *old_ptr_;
- int old_nalloc_;
+ SelectionTreeElementPointer sel_;
+ void *old_ptr_;
+ int old_nalloc_;
};
} // namespace
* \param[in] evalfunc Function pointer to print.
*/
void
-_gmx_sel_print_evalfunc_name(FILE *fp, sel_evalfunc evalfunc)
+_gmx_sel_print_evalfunc_name(FILE *fp, gmx::sel_evalfunc evalfunc)
{
if (!evalfunc)
fprintf(fp, "none");
* The \ref SEL_EVALFRAME flag is cleared for all elements.
*/
static void
-init_frame_eval(t_selelem *sel)
+init_frame_eval(SelectionTreeElementPointer sel)
{
while (sel)
{
{
gmx_ana_selcollection_t *sc = &coll->impl_->sc_;
gmx_sel_evaluate_t data;
- t_selelem *sel;
_gmx_sel_evaluate_init(&data, sc->mempool, &sc->gall, sc->top, fr, pbc);
init_frame_eval(sc->root);
- sel = sc->root;
+ SelectionTreeElementPointer sel = sc->root;
while (sel)
{
/* Clear the evaluation group of subexpressions */
* Evaluates each child of \p sel in \p g.
*/
void
-_gmx_sel_evaluate_children(gmx_sel_evaluate_t *data, t_selelem *sel,
+_gmx_sel_evaluate_children(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
gmx_ana_index_t *g)
{
- t_selelem *child;
-
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
if (child->evaluate)
* The value of \p sel is not touched (root elements do not evaluate to
* values).
*
- * This function can be used as \c t_selelem::evaluate for \ref SEL_ROOT
- * elements.
+ * This function can be used as gmx::SelectionTreeElement::evaluate for
+ * \ref SEL_ROOT elements.
*/
void
-_gmx_sel_evaluate_root(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_root(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g)
{
if (sel->u.cgrp.isize == 0 || !sel->child->evaluate)
{
*
* Sets the value of \p sel to the intersection of \p g and \p sel->u.cgrp.
*
- * This function can be used as \c t_selelem::evaluate for \ref SEL_CONST
- * elements with value type \ref GROUP_VALUE.
+ * This function can be used as gmx::SelectionTreeElement::evaluate for
+ * \ref SEL_CONST elements with value type \ref GROUP_VALUE.
*/
void
-_gmx_sel_evaluate_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_static(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g)
{
gmx_ana_index_intersection(sel->v.u.g, &sel->u.cgrp, g);
}
* The compiler has taken care that the child actually stores the evaluated
* value in the value pointer of this element.
*
- * This function is used as \c t_selelem::evaluate for \ref SEL_SUBEXPR
- * elements that are used only once, and hence do not need full subexpression
- * handling.
+ * This function is used as gmx::SelectionTreeElement::evaluate for
+ * \ref SEL_SUBEXPR elements that are used only once, and hence do not need
+ * full subexpression handling.
*/
void
-_gmx_sel_evaluate_subexpr_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_subexpr_simple(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g)
{
if (sel->child->evaluate)
{
* value in the value pointer of this element.
* Assumes that \p g is persistent for the duration of the whole evaluation.
*
- * This function is used as \c t_selelem::evaluate for \ref SEL_SUBEXPR
- * elements that have a static evaluation group, and hence do not need full
- * subexpression handling.
+ * This function is used as gmx::SelectionTreeElement::evaluate for
+ * \ref SEL_SUBEXPR elements that have a static evaluation group, and hence do
+ * not need full subexpression handling.
*/
void
-_gmx_sel_evaluate_subexpr_staticeval(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_subexpr_staticeval(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g)
{
if (sel->u.cgrp.isize == 0)
{
* major problem.
*/
void
-_gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g)
{
gmx_ana_index_t gmiss;
if (sel->u.cgrp.isize == 0)
{
{
- SelelemTemporaryValueAssigner assigner(sel->child, sel);
+ SelelemTemporaryValueAssigner assigner(sel->child, *sel);
sel->child->evaluate(data, sel->child, g);
}
/* We need to keep the name for the cgrp across the copy to avoid
* memory as the value pointer of this element to avoid copying, and then
* evaluates evaluates the child.
*
- * This function is used as \c t_selelem:evaluate for \ref SEL_SUBEXPRREF
- * elements for which the \ref SEL_SUBEXPR does not have other references.
+ * This function is used as gmx::SelectionTreeElement:evaluate for
+ * \ref SEL_SUBEXPRREF elements for which the \ref SEL_SUBEXPR does not have
+ * other references.
*/
void
-_gmx_sel_evaluate_subexprref_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_subexprref_simple(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g)
{
if (g)
{
* group \p g, and the value of the child is then copied.
* There should be only one child element.
*
- * This function is used as \c t_selelem::evaluate for \ref SEL_SUBEXPRREF
- * elements.
+ * This function is used as gmx::SelectionTreeElement::evaluate for
+ * \ref SEL_SUBEXPRREF elements.
*/
void
-_gmx_sel_evaluate_subexprref(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_subexprref(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g)
{
- t_selelem *expr;
int i, j;
if (g)
{
sel->child->evaluate(data, sel->child, g);
}
- expr = sel->child;
+ const SelectionTreeElementPointer &expr = sel->child;
switch (sel->v.type)
{
case INT_VALUE:
* Evaluates each child of a \ref SEL_EXPRESSION element.
* The value of \p sel is not touched.
*
- * This function is not used as \c t_selelem::evaluate,
+ * This function is not used as gmx::SelectionTreeElement::evaluate,
* but is used internally.
*/
void
-_gmx_sel_evaluate_method_params(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_method_params(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g)
{
- t_selelem *child;
-
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
if (child->evaluate && !(child->flags & SEL_EVALFRAME))
* the positions are also updated, and sel_updatefunc_pos() is used to
* evaluate the value. Otherwise, sel_updatefunc() is used.
*
- * This function is used as \c t_selelem::evaluate for \ref SEL_EXPRESSION
- * elements.
+ * This function is used as gmx::SelectionTreeElement::evaluate for
+ * \ref SEL_EXPRESSION elements.
*/
void
-_gmx_sel_evaluate_method(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_method(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g)
{
_gmx_sel_evaluate_method_params(data, sel, g);
if (sel->flags & SEL_INITFRAME)
* the frame, sel_framefunc() callback is called if one is provided.
* The modifier is then evaluated using sel_updatefunc_pos().
*
- * This function is used as \c t_selelem::evaluate for \ref SEL_MODIFIER
- * elements.
+ * This function is used as gmx::SelectionTreeElement::evaluate for
+ * \ref SEL_MODIFIER elements.
*/
void
-_gmx_sel_evaluate_modifier(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_modifier(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g)
{
_gmx_sel_evaluate_method_params(data, sel, g);
if (sel->flags & SEL_INITFRAME)
* \p g, and then sets the value of \p sel to the complement of the
* child value.
*
- * This function is used as \c t_selelem::evaluate for \ref SEL_BOOLEAN
- * elements with \ref BOOL_NOT.
+ * This function is used as gmx::SelectionTreeElement::evaluate for
+ * \ref SEL_BOOLEAN elements with \ref BOOL_NOT.
*/
void
-_gmx_sel_evaluate_not(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_not(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g)
{
MempoolSelelemReserver reserver(sel->child, g->isize);
sel->child->evaluate(data, sel->child, g);
* of the constant group
* (currently, the compiler never detects this).
*
- * This function is used as \c t_selelem::evaluate for \ref SEL_BOOLEAN
- * elements with \ref BOOL_AND.
+ * This function is used as gmx::SelectionTreeElement::evaluate for
+ * \ref SEL_BOOLEAN elements with \ref BOOL_AND.
*/
void
-_gmx_sel_evaluate_and(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_and(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g)
{
- t_selelem *child;
-
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
/* Skip the first child if it does not have an evaluation function. */
if (!child->evaluate)
{
* In this case, the compiler has taken care of that the child value is a
* subset of \p g, making it unnecessary to evaluate it.
*
- * This function is used as \c t_selelem::evaluate for \ref SEL_BOOLEAN
- * elements with \ref BOOL_OR.
+ * This function is used as gmx::SelectionTreeElement::evaluate for
+ * \ref SEL_BOOLEAN elements with \ref BOOL_OR.
*/
void
-_gmx_sel_evaluate_or(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_or(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g)
{
- t_selelem *child;
gmx_ana_index_t tmp, tmp2;
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
if (child->evaluate)
{
MempoolSelelemReserver reserver(child, g->isize);
* \returns 0 on success, a non-zero error code on error.
*/
void
-_gmx_sel_evaluate_arithmetic(gmx_sel_evaluate_t *data, t_selelem *sel,
+_gmx_sel_evaluate_arithmetic(gmx_sel_evaluate_t *data,
+ const SelectionTreeElementPointer &sel,
gmx_ana_index_t *g)
{
int n, i, i1, i2;
real lval, rval=0., val=0.;
- t_selelem *const left = sel->child;
- t_selelem *const right = left->next;
+ const SelectionTreeElementPointer &left = sel->child;
+ const SelectionTreeElementPointer &right = left->next;
SelelemTemporaryValueAssigner assigner;
MempoolSelelemReserver reserver;
if (left->mempool)
{
- assigner.assign(left, sel);
+ assigner.assign(left, *sel);
if (right)
{
reserver.reserve(right, g->isize);
}
else if (right && right->mempool)
{
- assigner.assign(right, sel);
+ assigner.assign(right, *sel);
}
_gmx_sel_evaluate_children(data, sel, g);
* selections.
*
* The functions defined in this header file are all the possible values
- * for the \c t_selelem::evaluate field (in addition to NULL).
+ * for the gmx::SelectionTreeElement::evaluate field (in addition to NULL).
*
* \author Teemu Murtola <teemu.murtola@cbr.su.se>
* \ingroup module_selection
t_topology *top, t_trxframe *fr, t_pbc *pbc);
/** Evaluates the children of a general selection element. */
void
-_gmx_sel_evaluate_children(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_children(gmx_sel_evaluate_t *data,
+ const gmx::SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g);
/** Evaluates the children of a \ref SEL_EXPRESSION element. */
void
-_gmx_sel_evaluate_method_params(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_method_params(gmx_sel_evaluate_t *data,
+ const gmx::SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g);
/*@}*/
/*! \name Misc. evaluation functions
/*@{*/
/** Evaluates a root selection element. */
void
-_gmx_sel_evaluate_root(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_root(gmx_sel_evaluate_t *data,
+ const gmx::SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g);
/** Evaluates a static group selection element. */
void
-_gmx_sel_evaluate_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_static(gmx_sel_evaluate_t *data,
+ const gmx::SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g);
/** Evaluates an arithmetic expression element. */
void
-_gmx_sel_evaluate_arithmetic(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_arithmetic(gmx_sel_evaluate_t *data,
+ const gmx::SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g);
/*@}*/
/*! \name Subexpression evaluation functions
/*@{*/
/** Evaluates a subexpression when there is only one reference. */
void
-_gmx_sel_evaluate_subexpr_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_subexpr_simple(gmx_sel_evaluate_t *data,
+ const gmx::SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g);
/** Evaluates a subexpression when the evaluation group is static. */
void
-_gmx_sel_evaluate_subexpr_staticeval(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_subexpr_staticeval(gmx_sel_evaluate_t *data,
+ const gmx::SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g);
/** Evaluates a subexpression. */
void
-_gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data,
+ const gmx::SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g);
/** Evaluates a subexpression reference when there are no other references. */
void
-_gmx_sel_evaluate_subexprref_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_subexprref_simple(gmx_sel_evaluate_t *data,
+ const gmx::SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g);
/** Evaluates a subexpression reference. */
void
-_gmx_sel_evaluate_subexprref(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_subexprref(gmx_sel_evaluate_t *data,
+ const gmx::SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g);
/*@}*/
/*! \name Method evaluation functions
/** Evaluates a method expression. */
void
-_gmx_sel_evaluate_method(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_method(gmx_sel_evaluate_t *data,
+ const gmx::SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g);
/** Evaluates a modifier expression. */
void
-_gmx_sel_evaluate_modifier(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_modifier(gmx_sel_evaluate_t *data,
+ const gmx::SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g);
/*@}*/
/*! \name Boolean evaluation functions
/*@{*/
/** Evaluates a boolean NOT element. */
void
-_gmx_sel_evaluate_not(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_not(gmx_sel_evaluate_t *data,
+ const gmx::SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g);
/** Evaluates a boolean AND element with short-circuiting. */
void
-_gmx_sel_evaluate_and(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_and(gmx_sel_evaluate_t *data,
+ const gmx::SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g);
/** Evaluates a boolean OR element with short-circuiting. */
void
-_gmx_sel_evaluate_or(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_or(gmx_sel_evaluate_t *data,
+ const gmx::SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g);
/*@}*/
#endif
* \author Teemu Murtola <teemu.murtola@cbr.su.se>
* \ingroup module_selection
*/
-#ifndef SELECTION_KEYWORDS_H
-#define SELECTION_KEYWORDS_H
+#ifndef GMX_SELECTION_KEYWORDS_H
+#define GMX_SELECTION_KEYWORDS_H
+
+#include "selelem.h"
struct gmx_ana_selmethod_t;
-struct t_selelem;
struct t_selexpr_param;
/** Selection method data for comparison expression evaluation. */
/** Sets the position type for position keyword evaluation. */
void
-_gmx_selelem_set_kwpos_type(struct t_selelem *sel, const char *type);
+_gmx_selelem_set_kwpos_type(gmx::SelectionTreeElement *sel, const char *type);
/** Sets the flags for position keyword evaluation. */
void
-_gmx_selelem_set_kwpos_flags(struct t_selelem *sel, int flags);
+_gmx_selelem_set_kwpos_flags(gmx::SelectionTreeElement *sel, int flags);
/** Does custom processing for parameters of the \c same selection method. */
int
struct t_selexpr_param *params, void *scanner);
/** Initializes a selection element for evaluating a keyword in a given group. */
-int
-_gmx_sel_init_keyword_evaluator(struct t_selelem **sel,
- struct gmx_ana_selmethod_t *method,
+gmx::SelectionTreeElementPointer
+_gmx_sel_init_keyword_evaluator(struct gmx_ana_selmethod_t *method,
struct t_selexpr_param *param, void *scanner);
#endif
#include <algorithm>
-#include "smalloc.h"
-#include "string2.h"
-#include "vec.h"
+#include "gromacs/legacyheaders/smalloc.h"
+#include "gromacs/legacyheaders/string2.h"
+#include "gromacs/legacyheaders/vec.h"
#include "gromacs/selection/position.h"
#include "gromacs/selection/selmethod.h"
#include "gromacs/selection/selparam.h"
#include "gromacs/utility/errorcodes.h"
+#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/messagestringcollector.h"
#include "gromacs/utility/stringutil.h"
using std::min;
using std::max;
+using gmx::SelectionTreeElement;
+using gmx::SelectionTreeElementPointer;
+
/*!
* \param[in] name Name of the parameter to search.
* \param[in] nparam Number of parameters in the \p param array.
{
return 0;
}
- if (value->bExpr)
+ if (value->hasExpressionValue())
{
/* Conversion from atom selection to position using default
* reference positions. */
if (value->type == GROUP_VALUE && type == POS_VALUE)
{
- value->u.expr =
- _gmx_sel_init_position(value->u.expr, NULL, scanner);
- if (value->u.expr == NULL)
+ value->expr =
+ _gmx_sel_init_position(value->expr, NULL, scanner);
+ // FIXME: Use exceptions
+ if (!value->expr)
{
return -1;
}
* in the same order as the corresponding parameters.
*/
static void
-place_child(t_selelem *root, t_selelem *child, gmx_ana_selparam_t *param)
+place_child(const SelectionTreeElementPointer &root,
+ const SelectionTreeElementPointer &child,
+ gmx_ana_selparam_t *param)
{
gmx_ana_selparam_t *ps;
int n;
}
else
{
- t_selelem *prev;
-
- prev = root->child;
+ SelectionTreeElementPointer prev = root->child;
while (prev->next && prev->next->u.param - ps >= n)
{
prev = prev->next;
i = 0;
while (value)
{
- if (value->bExpr)
+ if (value->hasExpressionValue())
{
_gmx_selparser_error(scanner, "expressions not supported within range parameters");
return false;
*/
static bool
parse_values_varnum(int nval, t_selexpr_value *values,
- gmx_ana_selparam_t *param, t_selelem *root, void *scanner)
+ gmx_ana_selparam_t *param,
+ const SelectionTreeElementPointer &root,
+ void *scanner)
{
t_selexpr_value *value;
int i, j;
value = values;
while (value)
{
- if (value->type == INT_VALUE && !value->bExpr)
+ if (value->type == INT_VALUE && !value->hasExpressionValue())
{
nval += abs(value->u.i.i2 - value->u.i.i1);
}
i = 0;
while (value)
{
- if (value->bExpr)
+ if (value->hasExpressionValue())
{
_gmx_selparser_error(scanner, "expressions not supported within value lists");
return false;
* other function. */
if (param->val.type == STR_VALUE)
{
- t_selelem *child;
-
- child = _gmx_selelem_create(SEL_CONST);
+ SelectionTreeElementPointer child(new SelectionTreeElement(SEL_CONST));
_gmx_selelem_set_vtype(child, STR_VALUE);
child->name = param->name;
child->flags &= ~SEL_ALLOCVAL;
* If \p expr is already a \ref SEL_SUBEXPRREF, it is used as it is.
* \ref SEL_ALLOCVAL is cleared for the returned element.
*/
-static t_selelem *
-add_child(t_selelem *root, gmx_ana_selparam_t *param, t_selelem *expr,
- void *scanner)
+static SelectionTreeElementPointer
+add_child(const SelectionTreeElementPointer &root, gmx_ana_selparam_t *param,
+ const SelectionTreeElementPointer &expr, void *scanner)
{
- t_selelem *child;
- int rc;
-
- if (root->type != SEL_EXPRESSION && root->type != SEL_MODIFIER)
- {
- GMX_ERROR_NORET(gmx::eeInternalError,
- "Unsupported root element for selection parameter parser");
- return NULL;
- }
+ GMX_RELEASE_ASSERT(root->type == SEL_EXPRESSION || root->type == SEL_MODIFIER,
+ "Unsupported root element for selection parameter parser");
+ SelectionTreeElementPointer child;
/* Create a subexpression reference element if necessary */
if (expr->type == SEL_SUBEXPRREF)
{
}
else
{
- child = _gmx_selelem_create(SEL_SUBEXPRREF);
- if (!child)
- {
- return NULL;
- }
+ child.reset(new SelectionTreeElement(SEL_SUBEXPRREF));
_gmx_selelem_set_vtype(child, expr->v.type);
child->child = expr;
}
if (child->v.type != param->val.type)
{
_gmx_selparser_error(scanner, "invalid expression value");
- goto on_error;
- }
- rc = _gmx_selelem_update_flags(child, scanner);
- if (rc != 0)
- {
- goto on_error;
+ // FIXME: Use exceptions.
+ return SelectionTreeElementPointer();
}
+ _gmx_selelem_update_flags(child, scanner);
if ((child->flags & SEL_DYNAMIC) && !(param->flags & SPAR_DYNAMIC))
{
_gmx_selparser_error(scanner, "dynamic values not supported");
- goto on_error;
+ // FIXME: Use exceptions.
+ return SelectionTreeElementPointer();
}
if (!(child->flags & SEL_DYNAMIC))
{
/* Put the child element in the correct place */
place_child(root, child, param);
return child;
-
-on_error:
- if (child != expr)
- {
- _gmx_selelem_free(child);
- }
- return NULL;
}
/*! \brief
*/
static bool
parse_values_varnum_expr(int nval, t_selexpr_value *values,
- gmx_ana_selparam_t *param, t_selelem *root,
+ gmx_ana_selparam_t *param,
+ const SelectionTreeElementPointer &root,
void *scanner)
{
- t_selexpr_value *value;
- t_selelem *child;
-
- if (nval != 1 || !values->bExpr)
+ if (nval != 1 || !values->hasExpressionValue())
{
GMX_ERROR_NORET(gmx::eeInternalError, "Invalid expression value");
return false;
}
- value = values;
- child = add_child(root, param, value->u.expr, scanner);
- value->u.expr = NULL;
+ t_selexpr_value *value = values;
+ SelectionTreeElementPointer child
+ = add_child(root, param, value->expr, scanner);
if (!child)
{
return false;
* This function is used internally by parse_values_std().
*/
static bool
-set_expr_value_store(t_selelem *sel, gmx_ana_selparam_t *param, int i,
- void *scanner)
+set_expr_value_store(const SelectionTreeElementPointer &sel,
+ gmx_ana_selparam_t *param, int i, void *scanner)
{
if (sel->v.type != GROUP_VALUE && !(sel->flags & SEL_SINGLEVAL))
{
*/
static bool
parse_values_std(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param,
- t_selelem *root, void *scanner)
+ const SelectionTreeElementPointer &root, void *scanner)
{
t_selexpr_value *value;
- t_selelem *child;
int i, j;
bool bDynamic;
return false;
}
value = values;
- if (value->bExpr)
+ if (value->hasExpressionValue())
{
- child = add_child(root, param, value->u.expr, scanner);
- value->u.expr = NULL;
+ SelectionTreeElementPointer child
+ = add_child(root, param, value->expr, scanner);
if (!child)
{
return false;
value = value->next;
continue;
}
- if (value->bExpr)
+ if (value->hasExpressionValue())
{
- child = add_child(root, param, value->u.expr, scanner);
- /* Clear the expression from the value once it is stored */
- value->u.expr = NULL;
+ SelectionTreeElementPointer child
+ = add_child(root, param, value->expr, scanner);
/* Check that the expression is valid */
if (!child)
{
GMX_ERROR_NORET(gmx::eeInternalError, "Invalid enum parameter");
return false;
}
- if (values->bExpr)
+ if (values->hasExpressionValue())
{
_gmx_selparser_error(scanner, "expression value for enumerated parameter not supported");
return false;
val = values;
while (val)
{
- if (val->bExpr && val->u.expr->v.type != GROUP_VALUE &&
- val->u.expr->type == SEL_CONST)
+ if (val->hasExpressionValue() && val->expr->v.type != GROUP_VALUE &&
+ val->expr->type == SEL_CONST)
{
- t_selelem *expr = val->u.expr;
- val->bExpr = false;
+ SelectionTreeElementPointer expr = val->expr;
+ val->expr.reset();
switch (expr->v.type)
{
case INT_VALUE:
"Unsupported value type");
break;
}
- _gmx_selelem_free(expr);
}
val = val->next;
}
*/
bool
_gmx_sel_parse_params(t_selexpr_param *pparams, int nparam, gmx_ana_selparam_t *params,
- t_selelem *root, void *scanner)
+ const SelectionTreeElementPointer &root, void *scanner)
{
gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
t_selexpr_param *pparam;
}
else if (oparam->flags & SPAR_VARNUM)
{
- if (pparam->nval == 1 && pparam->value->bExpr)
+ if (pparam->nval == 1 && pparam->value->hasExpressionValue())
{
rc = parse_values_varnum_expr(pparam->nval, pparam->value, oparam, root, scanner);
}
#include <exception>
+#include "gromacs/legacyheaders/smalloc.h"
#include "gromacs/legacyheaders/string2.h"
#include "parsetree.h"
#include "scanner.h"
+using gmx::scoped_ptr_sfree;
+using gmx::SelectionTreeElement;
+using gmx::SelectionTreeElementPointer;
+
//! Helper method to reorder a list of parameter values and to count the values.
static t_selexpr_value *
process_value_list(t_selexpr_value *values, int *nr);
static t_selexpr_param *
process_param_list(t_selexpr_param *params);
+/*! \brief
+ * Retrieves a selection tree pointer from a semantic value.
+ *
+ * \param[in] src Semantic value to get the tree from.
+ * \returns Pointer to the selection tree.
+ *
+ * There should be no statements that may throw exceptions in actions before
+ * this function has been called for all semantic values that have a tree
+ * argument. Together with set(), this function abstracts away exception
+ * safety issues that arise from the use of a plain pointer for storing the
+ * selection tree semantic values.
+ *
+ * Does not throw.
+ */
+static SelectionTreeElementPointer
+get(SelectionTreeElementPointer *src)
+{
+ SelectionTreeElementPointer result;
+ if (src != NULL)
+ {
+ result.swap(*src);
+ delete src;
+ }
+ return result;
+}
+/*! \brief
+ * Sets a selection tree pointer to a semantic value.
+ *
+ * \param[out] dest Semantic value to set the tree to.
+ * \param[in] value Pointer to the selection tree to set.
+ * \throws std::bad_alloc if out of memory.
+ *
+ * This should be the last statement before ::END_ACTION, except for a
+ * possible ::CHECK_SEL.
+ */
+static void
+set(SelectionTreeElementPointer *&dest,
+ const SelectionTreeElementPointer &value)
+{
+ dest = new SelectionTreeElementPointer(value);
+}
+/*! \brief
+ * Checks that a valid tree was set.
+ *
+ * Should be called after set() if it was used to set a value where NULL
+ * pointer indicates an error.
+ *
+ * \todo
+ * Get rid of this macro. It should now be possible to handle all errors using
+ * exceptions.
+ */
+#define CHECK_SEL(sel) \
+ if (!*(sel)) { \
+ delete sel; \
+ YYERROR; \
+ }
+
//! Error handler needed by Bison.
static void
yyerror(yyscan_t, char const *s);
/* Line 268 of yacc.c */
-#line 150 "parser.cpp"
+#line 212 "parser.cpp"
/* Enabling traces. */
#ifndef YYDEBUG
# define YYTOKEN_TABLE 0
#endif
+/* "%code requires" blocks. */
+
+/* Line 288 of yacc.c */
+#line 166 "parser.y"
+
+#include "selelem.h"
+
+
+
+/* Line 288 of yacc.c */
+#line 242 "parser.cpp"
/* Tokens. */
#ifndef YYTOKENTYPE
{
/* Line 293 of yacc.c */
-#line 104 "parser.y"
+#line 170 "parser.y"
int i;
real r;
char *str;
struct gmx_ana_selmethod_t *meth;
- struct t_selelem *sel;
+ gmx::SelectionTreeElementPointer *sel;
struct t_selexpr_value *val;
struct t_selexpr_param *param;
/* Line 293 of yacc.c */
-#line 235 "parser.cpp"
+#line 308 "parser.cpp"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
/* Line 343 of yacc.c */
-#line 271 "parser.cpp"
+#line 344 "parser.cpp"
#ifdef short
# undef short
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 220, 220, 221, 232, 233, 255, 261, 262, 273,
- 285, 291, 297, 303, 309, 319, 327, 328, 338, 339,
- 346, 347, 361, 362, 366, 367, 370, 371, 374, 375,
- 383, 391, 399, 407, 411, 421, 429, 439, 440, 444,
- 451, 458, 468, 482, 491, 503, 510, 520, 526, 532,
- 538, 544, 550, 556, 563, 572, 586, 595, 599, 609,
- 622, 630, 638, 651, 653, 658, 659, 664, 673, 674,
- 675, 679, 680, 682, 687, 688, 692, 693, 695, 699,
- 705, 711, 717, 723, 727, 734, 741, 748, 752, 759,
- 766
+ 0, 285, 285, 286, 297, 298, 320, 326, 327, 339,
+ 352, 358, 365, 372, 379, 390, 398, 399, 409, 410,
+ 417, 418, 432, 433, 437, 438, 441, 442, 445, 446,
+ 454, 465, 476, 487, 491, 501, 509, 519, 520, 524,
+ 531, 538, 548, 562, 573, 587, 594, 604, 610, 616,
+ 622, 628, 634, 640, 647, 658, 672, 681, 685, 695,
+ 708, 716, 724, 737, 739, 744, 745, 750, 759, 760,
+ 761, 765, 766, 768, 773, 774, 778, 779, 781, 785,
+ 791, 797, 803, 809, 813, 820, 827, 834, 838, 845,
+ 852
};
#endif
case 5: /* "HELP_TOPIC" */
/* Line 1391 of yacc.c */
-#line 199 "parser.y"
+#line 265 "parser.y"
{ free((yyvaluep->str)); };
/* Line 1391 of yacc.c */
-#line 1377 "parser.cpp"
+#line 1450 "parser.cpp"
break;
case 8: /* "STR" */
/* Line 1391 of yacc.c */
-#line 199 "parser.y"
+#line 265 "parser.y"
{ free((yyvaluep->str)); };
/* Line 1391 of yacc.c */
-#line 1386 "parser.cpp"
+#line 1459 "parser.cpp"
break;
case 9: /* "IDENTIFIER" */
/* Line 1391 of yacc.c */
-#line 199 "parser.y"
+#line 265 "parser.y"
{ free((yyvaluep->str)); };
/* Line 1391 of yacc.c */
-#line 1395 "parser.cpp"
+#line 1468 "parser.cpp"
break;
case 25: /* "PARAM" */
/* Line 1391 of yacc.c */
-#line 200 "parser.y"
+#line 266 "parser.y"
{ if((yyvaluep->str)) free((yyvaluep->str)); };
/* Line 1391 of yacc.c */
-#line 1404 "parser.cpp"
+#line 1477 "parser.cpp"
break;
case 28: /* "CMP_OP" */
/* Line 1391 of yacc.c */
-#line 199 "parser.y"
+#line 265 "parser.y"
{ free((yyvaluep->str)); };
/* Line 1391 of yacc.c */
-#line 1413 "parser.cpp"
+#line 1486 "parser.cpp"
+ break;
+ case 50: /* "commands" */
+
+/* Line 1391 of yacc.c */
+#line 267 "parser.y"
+ { delete (yyvaluep->sel); };
+
+/* Line 1391 of yacc.c */
+#line 1495 "parser.cpp"
break;
case 51: /* "command" */
/* Line 1391 of yacc.c */
-#line 201 "parser.y"
- { if((yyvaluep->sel)) _gmx_selelem_free((yyvaluep->sel)); };
+#line 267 "parser.y"
+ { delete (yyvaluep->sel); };
/* Line 1391 of yacc.c */
-#line 1422 "parser.cpp"
+#line 1504 "parser.cpp"
break;
case 52: /* "cmd_plain" */
/* Line 1391 of yacc.c */
-#line 201 "parser.y"
- { if((yyvaluep->sel)) _gmx_selelem_free((yyvaluep->sel)); };
+#line 267 "parser.y"
+ { delete (yyvaluep->sel); };
/* Line 1391 of yacc.c */
-#line 1431 "parser.cpp"
+#line 1513 "parser.cpp"
break;
case 54: /* "help_topic" */
/* Line 1391 of yacc.c */
-#line 207 "parser.y"
+#line 272 "parser.y"
{ _gmx_selexpr_free_values((yyvaluep->val)); };
/* Line 1391 of yacc.c */
-#line 1440 "parser.cpp"
+#line 1522 "parser.cpp"
break;
case 55: /* "selection" */
/* Line 1391 of yacc.c */
-#line 202 "parser.y"
- { _gmx_selelem_free_chain((yyvaluep->sel)); };
+#line 267 "parser.y"
+ { delete (yyvaluep->sel); };
/* Line 1391 of yacc.c */
-#line 1449 "parser.cpp"
+#line 1531 "parser.cpp"
break;
case 59: /* "string" */
/* Line 1391 of yacc.c */
-#line 199 "parser.y"
+#line 265 "parser.y"
{ free((yyvaluep->str)); };
/* Line 1391 of yacc.c */
-#line 1458 "parser.cpp"
+#line 1540 "parser.cpp"
break;
case 60: /* "sel_expr" */
/* Line 1391 of yacc.c */
-#line 203 "parser.y"
- { _gmx_selelem_free((yyvaluep->sel)); };
+#line 268 "parser.y"
+ { delete (yyvaluep->sel); };
/* Line 1391 of yacc.c */
-#line 1467 "parser.cpp"
+#line 1549 "parser.cpp"
break;
case 62: /* "num_expr" */
/* Line 1391 of yacc.c */
-#line 203 "parser.y"
- { _gmx_selelem_free((yyvaluep->sel)); };
+#line 268 "parser.y"
+ { delete (yyvaluep->sel); };
/* Line 1391 of yacc.c */
-#line 1476 "parser.cpp"
+#line 1558 "parser.cpp"
break;
case 63: /* "str_expr" */
/* Line 1391 of yacc.c */
-#line 203 "parser.y"
- { _gmx_selelem_free((yyvaluep->sel)); };
+#line 268 "parser.y"
+ { delete (yyvaluep->sel); };
/* Line 1391 of yacc.c */
-#line 1485 "parser.cpp"
+#line 1567 "parser.cpp"
break;
case 64: /* "pos_expr" */
/* Line 1391 of yacc.c */
-#line 203 "parser.y"
- { _gmx_selelem_free((yyvaluep->sel)); };
+#line 268 "parser.y"
+ { delete (yyvaluep->sel); };
/* Line 1391 of yacc.c */
-#line 1494 "parser.cpp"
+#line 1576 "parser.cpp"
break;
case 65: /* "method_params" */
/* Line 1391 of yacc.c */
-#line 204 "parser.y"
+#line 269 "parser.y"
{ _gmx_selexpr_free_params((yyvaluep->param)); };
/* Line 1391 of yacc.c */
-#line 1503 "parser.cpp"
+#line 1585 "parser.cpp"
break;
case 66: /* "method_param_list" */
/* Line 1391 of yacc.c */
-#line 204 "parser.y"
+#line 269 "parser.y"
{ _gmx_selexpr_free_params((yyvaluep->param)); };
/* Line 1391 of yacc.c */
-#line 1512 "parser.cpp"
+#line 1594 "parser.cpp"
break;
case 67: /* "method_param" */
/* Line 1391 of yacc.c */
-#line 204 "parser.y"
+#line 269 "parser.y"
{ _gmx_selexpr_free_params((yyvaluep->param)); };
/* Line 1391 of yacc.c */
-#line 1521 "parser.cpp"
+#line 1603 "parser.cpp"
break;
case 68: /* "value_list" */
/* Line 1391 of yacc.c */
-#line 205 "parser.y"
+#line 270 "parser.y"
{ _gmx_selexpr_free_values((yyvaluep->val)); };
/* Line 1391 of yacc.c */
-#line 1530 "parser.cpp"
+#line 1612 "parser.cpp"
break;
case 69: /* "value_list_contents" */
/* Line 1391 of yacc.c */
-#line 205 "parser.y"
+#line 270 "parser.y"
{ _gmx_selexpr_free_values((yyvaluep->val)); };
/* Line 1391 of yacc.c */
-#line 1539 "parser.cpp"
+#line 1621 "parser.cpp"
break;
case 70: /* "basic_value_list" */
/* Line 1391 of yacc.c */
-#line 206 "parser.y"
+#line 271 "parser.y"
{ _gmx_selexpr_free_values((yyvaluep->val)); };
/* Line 1391 of yacc.c */
-#line 1548 "parser.cpp"
+#line 1630 "parser.cpp"
break;
case 71: /* "basic_value_list_contents" */
/* Line 1391 of yacc.c */
-#line 206 "parser.y"
+#line 271 "parser.y"
{ _gmx_selexpr_free_values((yyvaluep->val)); };
/* Line 1391 of yacc.c */
-#line 1557 "parser.cpp"
+#line 1639 "parser.cpp"
break;
case 72: /* "value_item" */
/* Line 1391 of yacc.c */
-#line 205 "parser.y"
+#line 270 "parser.y"
{ _gmx_selexpr_free_values((yyvaluep->val)); };
/* Line 1391 of yacc.c */
-#line 1566 "parser.cpp"
+#line 1648 "parser.cpp"
break;
case 73: /* "basic_value_item" */
/* Line 1391 of yacc.c */
-#line 206 "parser.y"
+#line 271 "parser.y"
{ _gmx_selexpr_free_values((yyvaluep->val)); };
/* Line 1391 of yacc.c */
-#line 1575 "parser.cpp"
+#line 1657 "parser.cpp"
break;
case 74: /* "value_item_range" */
/* Line 1391 of yacc.c */
-#line 205 "parser.y"
+#line 270 "parser.y"
{ _gmx_selexpr_free_values((yyvaluep->val)); };
/* Line 1391 of yacc.c */
-#line 1584 "parser.cpp"
+#line 1666 "parser.cpp"
break;
default:
case 2:
/* Line 1806 of yacc.c */
-#line 220 "parser.y"
+#line 285 "parser.y"
{ (yyval.sel) = NULL; }
break;
case 3:
/* Line 1806 of yacc.c */
-#line 222 "parser.y"
+#line 287 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_append_selection((yyvsp[(2) - (2)].sel), (yyvsp[(1) - (2)].sel), scanner);
+ set((yyval.sel), _gmx_sel_append_selection(get((yyvsp[(2) - (2)].sel)), get((yyvsp[(1) - (2)].sel)), scanner));
if (_gmx_sel_parser_should_finish(scanner))
YYACCEPT;
END_ACTION;
case 4:
/* Line 1806 of yacc.c */
-#line 232 "parser.y"
+#line 297 "parser.y"
{ (yyval.sel) = (yyvsp[(1) - (2)].sel); }
break;
case 5:
/* Line 1806 of yacc.c */
-#line 234 "parser.y"
+#line 299 "parser.y"
{
BEGIN_ACTION;
(yyval.sel) = NULL;
case 6:
/* Line 1806 of yacc.c */
-#line 255 "parser.y"
+#line 320 "parser.y"
{
BEGIN_ACTION;
(yyval.sel) = NULL;
case 7:
/* Line 1806 of yacc.c */
-#line 261 "parser.y"
+#line 326 "parser.y"
{ (yyval.sel) = NULL; }
break;
case 8:
/* Line 1806 of yacc.c */
-#line 263 "parser.y"
+#line 328 "parser.y"
{
BEGIN_ACTION;
- t_selelem *s, *p;
- s = _gmx_sel_init_group_by_id((yyvsp[(1) - (1)].i), scanner);
- if (s == NULL) YYERROR;
- p = _gmx_sel_init_position(s, NULL, scanner);
- if (p == NULL) YYERROR;
- (yyval.sel) = _gmx_sel_init_selection(strdup(s->name), p, scanner);
+ SelectionTreeElementPointer s
+ = _gmx_sel_init_group_by_id((yyvsp[(1) - (1)].i), scanner);
+ if (!s) YYERROR;
+ SelectionTreeElementPointer p
+ = _gmx_sel_init_position(s, NULL, scanner);
+ if (!p) YYERROR;
+ set((yyval.sel), _gmx_sel_init_selection(s->name, p, scanner));
END_ACTION;
}
break;
case 9:
/* Line 1806 of yacc.c */
-#line 274 "parser.y"
+#line 340 "parser.y"
{
BEGIN_ACTION;
- t_selelem *s, *p;
- s = _gmx_sel_init_group_by_name((yyvsp[(1) - (1)].str), scanner);
- free((yyvsp[(1) - (1)].str));
- if (s == NULL) YYERROR;
- p = _gmx_sel_init_position(s, NULL, scanner);
- if (p == NULL) YYERROR;
- (yyval.sel) = _gmx_sel_init_selection(strdup(s->name), p, scanner);
+ scoped_ptr_sfree nameGuard((yyvsp[(1) - (1)].str));
+ SelectionTreeElementPointer s
+ = _gmx_sel_init_group_by_name((yyvsp[(1) - (1)].str), scanner);
+ if (!s) YYERROR;
+ SelectionTreeElementPointer p
+ = _gmx_sel_init_position(s, NULL, scanner);
+ if (!p) YYERROR;
+ set((yyval.sel), _gmx_sel_init_selection(s->name, p, scanner));
END_ACTION;
}
break;
case 10:
/* Line 1806 of yacc.c */
-#line 286 "parser.y"
+#line 353 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_selection(NULL, (yyvsp[(1) - (1)].sel), scanner);
+ set((yyval.sel), _gmx_sel_init_selection(NULL, get((yyvsp[(1) - (1)].sel)), scanner));
END_ACTION;
}
break;
case 11:
/* Line 1806 of yacc.c */
-#line 292 "parser.y"
+#line 359 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_selection((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].sel), scanner);
+ scoped_ptr_sfree nameGuard((yyvsp[(1) - (2)].str));
+ set((yyval.sel), _gmx_sel_init_selection((yyvsp[(1) - (2)].str), get((yyvsp[(2) - (2)].sel)), scanner));
END_ACTION;
}
break;
case 12:
/* Line 1806 of yacc.c */
-#line 298 "parser.y"
+#line 366 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);
+ scoped_ptr_sfree nameGuard((yyvsp[(1) - (3)].str));
+ set((yyval.sel), _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), get((yyvsp[(3) - (3)].sel)), scanner));
END_ACTION;
}
break;
case 13:
/* Line 1806 of yacc.c */
-#line 304 "parser.y"
+#line 373 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);
+ scoped_ptr_sfree nameGuard((yyvsp[(1) - (3)].str));
+ set((yyval.sel), _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), get((yyvsp[(3) - (3)].sel)), scanner));
END_ACTION;
}
break;
case 14:
/* Line 1806 of yacc.c */
-#line 310 "parser.y"
+#line 380 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);
+ scoped_ptr_sfree nameGuard((yyvsp[(1) - (3)].str));
+ set((yyval.sel), _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), get((yyvsp[(3) - (3)].sel)), scanner));
END_ACTION;
}
break;
case 15:
/* Line 1806 of yacc.c */
-#line 320 "parser.y"
+#line 391 "parser.y"
{
BEGIN_ACTION;
_gmx_sel_handle_help_cmd(process_value_list((yyvsp[(2) - (2)].val), NULL), scanner);
case 16:
/* Line 1806 of yacc.c */
-#line 327 "parser.y"
+#line 398 "parser.y"
{ (yyval.val) = NULL; }
break;
case 17:
/* Line 1806 of yacc.c */
-#line 329 "parser.y"
+#line 400 "parser.y"
{
BEGIN_ACTION;
(yyval.val) = _gmx_selexpr_create_value(STR_VALUE);
case 18:
/* Line 1806 of yacc.c */
-#line 338 "parser.y"
+#line 409 "parser.y"
{ (yyval.sel) = (yyvsp[(1) - (1)].sel); }
break;
case 19:
/* Line 1806 of yacc.c */
-#line 340 "parser.y"
+#line 411 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_position((yyvsp[(1) - (1)].sel), NULL, scanner);
- if ((yyval.sel) == NULL) YYERROR;
+ set((yyval.sel), _gmx_sel_init_position(get((yyvsp[(1) - (1)].sel)), NULL, scanner));
+ CHECK_SEL((yyval.sel));
END_ACTION;
}
break;
case 20:
/* Line 1806 of yacc.c */
-#line 346 "parser.y"
+#line 417 "parser.y"
{ (yyval.sel) = (yyvsp[(2) - (3)].sel); }
break;
case 21:
/* Line 1806 of yacc.c */
-#line 348 "parser.y"
+#line 419 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_modifier((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].sel), scanner);
- if ((yyval.sel) == NULL) YYERROR;
+ set((yyval.sel), _gmx_sel_init_modifier((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), get((yyvsp[(1) - (3)].sel)), scanner));
+ CHECK_SEL((yyval.sel));
END_ACTION;
}
break;
case 22:
/* Line 1806 of yacc.c */
-#line 361 "parser.y"
+#line 432 "parser.y"
{ (yyval.i) = (yyvsp[(1) - (1)].i); }
break;
case 23:
/* Line 1806 of yacc.c */
-#line 362 "parser.y"
+#line 433 "parser.y"
{ (yyval.i) = -(yyvsp[(2) - (2)].i); }
break;
case 24:
/* Line 1806 of yacc.c */
-#line 366 "parser.y"
+#line 437 "parser.y"
{ (yyval.r) = (yyvsp[(1) - (1)].r); }
break;
case 25:
/* Line 1806 of yacc.c */
-#line 367 "parser.y"
+#line 438 "parser.y"
{ (yyval.r) = -(yyvsp[(2) - (2)].r); }
break;
case 26:
/* Line 1806 of yacc.c */
-#line 370 "parser.y"
+#line 441 "parser.y"
{ (yyval.r) = (yyvsp[(1) - (1)].i); }
break;
case 27:
/* Line 1806 of yacc.c */
-#line 371 "parser.y"
+#line 442 "parser.y"
{ (yyval.r) = (yyvsp[(1) - (1)].r); }
break;
case 28:
/* Line 1806 of yacc.c */
-#line 374 "parser.y"
+#line 445 "parser.y"
{ (yyval.str) = (yyvsp[(1) - (1)].str); }
break;
case 29:
/* Line 1806 of yacc.c */
-#line 375 "parser.y"
+#line 446 "parser.y"
{ (yyval.str) = (yyvsp[(1) - (1)].str); }
break;
case 30:
/* Line 1806 of yacc.c */
-#line 384 "parser.y"
+#line 455 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
- (yyval.sel)->u.boolt = BOOL_NOT;
- (yyval.sel)->child = (yyvsp[(2) - (2)].sel);
+ SelectionTreeElementPointer arg(get((yyvsp[(2) - (2)].sel)));
+ SelectionTreeElementPointer sel(
+ new SelectionTreeElement(SEL_BOOLEAN));
+ sel->u.boolt = BOOL_NOT;
+ sel->child = arg;
+ set((yyval.sel), sel);
END_ACTION;
}
break;
case 31:
/* Line 1806 of yacc.c */
-#line 392 "parser.y"
+#line 466 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
- (yyval.sel)->u.boolt = BOOL_AND;
- (yyval.sel)->child = (yyvsp[(1) - (3)].sel); (yyval.sel)->child->next = (yyvsp[(3) - (3)].sel);
+ SelectionTreeElementPointer arg1(get((yyvsp[(1) - (3)].sel))), arg2(get((yyvsp[(3) - (3)].sel)));
+ SelectionTreeElementPointer sel(
+ new SelectionTreeElement(SEL_BOOLEAN));
+ sel->u.boolt = BOOL_AND;
+ sel->child = arg1; sel->child->next = arg2;
+ set((yyval.sel), sel);
END_ACTION;
}
break;
case 32:
/* Line 1806 of yacc.c */
-#line 400 "parser.y"
+#line 477 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
- (yyval.sel)->u.boolt = BOOL_OR;
- (yyval.sel)->child = (yyvsp[(1) - (3)].sel); (yyval.sel)->child->next = (yyvsp[(3) - (3)].sel);
+ SelectionTreeElementPointer arg1(get((yyvsp[(1) - (3)].sel))), arg2(get((yyvsp[(3) - (3)].sel)));
+ SelectionTreeElementPointer sel(
+ new SelectionTreeElement(SEL_BOOLEAN));
+ sel->u.boolt = BOOL_OR;
+ sel->child = arg1; sel->child->next = arg2;
+ set((yyval.sel), sel);
END_ACTION;
}
break;
case 33:
/* Line 1806 of yacc.c */
-#line 407 "parser.y"
+#line 487 "parser.y"
{ (yyval.sel) = (yyvsp[(2) - (3)].sel); }
break;
case 34:
/* Line 1806 of yacc.c */
-#line 412 "parser.y"
+#line 492 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_comparison((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), (yyvsp[(2) - (3)].str), scanner);
- if ((yyval.sel) == NULL) YYERROR;
+ set((yyval.sel), _gmx_sel_init_comparison(get((yyvsp[(1) - (3)].sel)), get((yyvsp[(3) - (3)].sel)), (yyvsp[(2) - (3)].str), scanner));
+ CHECK_SEL((yyval.sel));
END_ACTION;
}
break;
case 35:
/* Line 1806 of yacc.c */
-#line 422 "parser.y"
+#line 502 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_group_by_name((yyvsp[(2) - (2)].str), scanner);
- free((yyvsp[(2) - (2)].str));
- if ((yyval.sel) == NULL) YYERROR;
+ scoped_ptr_sfree nameGuard((yyvsp[(2) - (2)].str));
+ set((yyval.sel), _gmx_sel_init_group_by_name((yyvsp[(2) - (2)].str), scanner));
+ CHECK_SEL((yyval.sel));
END_ACTION;
}
break;
case 36:
/* Line 1806 of yacc.c */
-#line 430 "parser.y"
+#line 510 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_group_by_id((yyvsp[(2) - (2)].i), scanner);
- if ((yyval.sel) == NULL) YYERROR;
+ set((yyval.sel), _gmx_sel_init_group_by_id((yyvsp[(2) - (2)].i), scanner));
+ CHECK_SEL((yyval.sel));
END_ACTION;
}
break;
case 37:
/* Line 1806 of yacc.c */
-#line 439 "parser.y"
+#line 519 "parser.y"
{ (yyval.str) = NULL; }
break;
case 38:
/* Line 1806 of yacc.c */
-#line 440 "parser.y"
+#line 520 "parser.y"
{ (yyval.str) = (yyvsp[(1) - (1)].str); }
break;
case 39:
/* Line 1806 of yacc.c */
-#line 445 "parser.y"
+#line 525 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
- if ((yyval.sel) == NULL) YYERROR;
+ set((yyval.sel), _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner));
+ CHECK_SEL((yyval.sel));
END_ACTION;
}
break;
case 40:
/* Line 1806 of yacc.c */
-#line 452 "parser.y"
+#line 532 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (3)].meth), process_value_list((yyvsp[(3) - (3)].val), NULL), (yyvsp[(1) - (3)].str), scanner);
- if ((yyval.sel) == NULL) YYERROR;
+ set((yyval.sel), _gmx_sel_init_keyword((yyvsp[(2) - (3)].meth), process_value_list((yyvsp[(3) - (3)].val), NULL), (yyvsp[(1) - (3)].str), scanner));
+ CHECK_SEL((yyval.sel));
END_ACTION;
}
break;
case 41:
/* Line 1806 of yacc.c */
-#line 459 "parser.y"
+#line 539 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (3)].meth), process_value_list((yyvsp[(3) - (3)].val), NULL), (yyvsp[(1) - (3)].str), scanner);
- if ((yyval.sel) == NULL) YYERROR;
+ set((yyval.sel), _gmx_sel_init_keyword((yyvsp[(2) - (3)].meth), process_value_list((yyvsp[(3) - (3)].val), NULL), (yyvsp[(1) - (3)].str), scanner));
+ CHECK_SEL((yyval.sel));
END_ACTION;
}
break;
case 42:
/* Line 1806 of yacc.c */
-#line 469 "parser.y"
+#line 549 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_method((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].str), scanner);
- if ((yyval.sel) == NULL) YYERROR;
+ set((yyval.sel), _gmx_sel_init_method((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].str), scanner));
+ CHECK_SEL((yyval.sel));
END_ACTION;
}
break;
case 43:
/* Line 1806 of yacc.c */
-#line 483 "parser.y"
+#line 563 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_selelem_create(SEL_CONST);
- _gmx_selelem_set_vtype((yyval.sel), INT_VALUE);
- _gmx_selvalue_reserve(&(yyval.sel)->v, 1);
- (yyval.sel)->v.u.i[0] = (yyvsp[(1) - (1)].i);
+ SelectionTreeElementPointer sel(
+ new SelectionTreeElement(SEL_CONST));
+ _gmx_selelem_set_vtype(sel, INT_VALUE);
+ _gmx_selvalue_reserve(&sel->v, 1);
+ sel->v.u.i[0] = (yyvsp[(1) - (1)].i);
+ set((yyval.sel), sel);
END_ACTION;
}
break;
case 44:
/* Line 1806 of yacc.c */
-#line 492 "parser.y"
+#line 574 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_selelem_create(SEL_CONST);
- _gmx_selelem_set_vtype((yyval.sel), REAL_VALUE);
- _gmx_selvalue_reserve(&(yyval.sel)->v, 1);
- (yyval.sel)->v.u.r[0] = (yyvsp[(1) - (1)].r);
+ SelectionTreeElementPointer sel(
+ new SelectionTreeElement(SEL_CONST));
+ _gmx_selelem_set_vtype(sel, REAL_VALUE);
+ _gmx_selvalue_reserve(&sel->v, 1);
+ sel->v.u.r[0] = (yyvsp[(1) - (1)].r);
+ set((yyval.sel), sel);
END_ACTION;
}
break;
case 45:
/* Line 1806 of yacc.c */
-#line 504 "parser.y"
+#line 588 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
- if ((yyval.sel) == NULL) YYERROR;
+ set((yyval.sel), _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner));
+ CHECK_SEL((yyval.sel));
END_ACTION;
}
break;
case 46:
/* Line 1806 of yacc.c */
-#line 511 "parser.y"
+#line 595 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_method((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].str), scanner);
- if ((yyval.sel) == NULL) YYERROR;
+ set((yyval.sel), _gmx_sel_init_method((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].str), scanner));
+ CHECK_SEL((yyval.sel));
END_ACTION;
}
break;
case 47:
/* Line 1806 of yacc.c */
-#line 521 "parser.y"
+#line 605 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '+', scanner);
+ set((yyval.sel), _gmx_sel_init_arithmetic(get((yyvsp[(1) - (3)].sel)), get((yyvsp[(3) - (3)].sel)), '+', scanner));
END_ACTION;
}
break;
case 48:
/* Line 1806 of yacc.c */
-#line 527 "parser.y"
+#line 611 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '-', scanner);
+ set((yyval.sel), _gmx_sel_init_arithmetic(get((yyvsp[(1) - (3)].sel)), get((yyvsp[(3) - (3)].sel)), '-', scanner));
END_ACTION;
}
break;
case 49:
/* Line 1806 of yacc.c */
-#line 533 "parser.y"
+#line 617 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '*', scanner);
+ set((yyval.sel), _gmx_sel_init_arithmetic(get((yyvsp[(1) - (3)].sel)), get((yyvsp[(3) - (3)].sel)), '*', scanner));
END_ACTION;
}
break;
case 50:
/* Line 1806 of yacc.c */
-#line 539 "parser.y"
+#line 623 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '/', scanner);
+ set((yyval.sel), _gmx_sel_init_arithmetic(get((yyvsp[(1) - (3)].sel)), get((yyvsp[(3) - (3)].sel)), '/', scanner));
END_ACTION;
}
break;
case 51:
/* Line 1806 of yacc.c */
-#line 545 "parser.y"
+#line 629 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(2) - (2)].sel), NULL, '-', scanner);
+ set((yyval.sel), _gmx_sel_init_arithmetic(get((yyvsp[(2) - (2)].sel)), SelectionTreeElementPointer(), '-', scanner));
END_ACTION;
}
break;
case 52:
/* Line 1806 of yacc.c */
-#line 551 "parser.y"
+#line 635 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '^', scanner);
+ set((yyval.sel), _gmx_sel_init_arithmetic(get((yyvsp[(1) - (3)].sel)), get((yyvsp[(3) - (3)].sel)), '^', scanner));
END_ACTION;
}
break;
case 53:
/* Line 1806 of yacc.c */
-#line 556 "parser.y"
+#line 640 "parser.y"
{ (yyval.sel) = (yyvsp[(2) - (3)].sel); }
break;
case 54:
/* Line 1806 of yacc.c */
-#line 564 "parser.y"
+#line 648 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_selelem_create(SEL_CONST);
- _gmx_selelem_set_vtype((yyval.sel), STR_VALUE);
- _gmx_selvalue_reserve(&(yyval.sel)->v, 1);
- (yyval.sel)->v.u.s[0] = (yyvsp[(1) - (1)].str);
+ SelectionTreeElementPointer sel(
+ new SelectionTreeElement(SEL_CONST));
+ _gmx_selelem_set_vtype(sel, STR_VALUE);
+ _gmx_selvalue_reserve(&sel->v, 1);
+ sel->v.u.s[0] = (yyvsp[(1) - (1)].str);
+ set((yyval.sel), sel);
END_ACTION;
}
break;
case 55:
/* Line 1806 of yacc.c */
-#line 573 "parser.y"
+#line 659 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
- if ((yyval.sel) == NULL) YYERROR;
+ set((yyval.sel), _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner));
+ CHECK_SEL((yyval.sel));
END_ACTION;
}
break;
case 56:
/* Line 1806 of yacc.c */
-#line 587 "parser.y"
+#line 673 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_const_position((yyvsp[(2) - (7)].r), (yyvsp[(4) - (7)].r), (yyvsp[(6) - (7)].r));
+ set((yyval.sel), _gmx_sel_init_const_position((yyvsp[(2) - (7)].r), (yyvsp[(4) - (7)].r), (yyvsp[(6) - (7)].r)));
END_ACTION;
}
break;
case 57:
/* Line 1806 of yacc.c */
-#line 595 "parser.y"
+#line 681 "parser.y"
{ (yyval.sel) = (yyvsp[(2) - (3)].sel); }
break;
case 58:
/* Line 1806 of yacc.c */
-#line 600 "parser.y"
+#line 686 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_method((yyvsp[(1) - (2)].meth), (yyvsp[(2) - (2)].param), NULL, scanner);
- if ((yyval.sel) == NULL) YYERROR;
+ set((yyval.sel), _gmx_sel_init_method((yyvsp[(1) - (2)].meth), (yyvsp[(2) - (2)].param), NULL, scanner));
+ CHECK_SEL((yyval.sel));
END_ACTION;
}
break;
case 59:
/* Line 1806 of yacc.c */
-#line 610 "parser.y"
+#line 696 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_position((yyvsp[(3) - (3)].sel), (yyvsp[(1) - (3)].str), scanner);
- if ((yyval.sel) == NULL) YYERROR;
+ set((yyval.sel), _gmx_sel_init_position(get((yyvsp[(3) - (3)].sel)), (yyvsp[(1) - (3)].str), scanner));
+ CHECK_SEL((yyval.sel));
END_ACTION;
}
break;
case 60:
/* Line 1806 of yacc.c */
-#line 623 "parser.y"
+#line 709 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel));
+ set((yyval.sel), _gmx_sel_init_variable_ref(get((yyvsp[(1) - (1)].sel))));
END_ACTION;
}
break;
case 61:
/* Line 1806 of yacc.c */
-#line 631 "parser.y"
+#line 717 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel));
+ set((yyval.sel), _gmx_sel_init_variable_ref(get((yyvsp[(1) - (1)].sel))));
END_ACTION;
}
break;
case 62:
/* Line 1806 of yacc.c */
-#line 639 "parser.y"
+#line 725 "parser.y"
{
BEGIN_ACTION;
- (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel));
+ set((yyval.sel), _gmx_sel_init_variable_ref(get((yyvsp[(1) - (1)].sel))));
END_ACTION;
}
break;
case 63:
/* Line 1806 of yacc.c */
-#line 652 "parser.y"
+#line 738 "parser.y"
{ (yyval.param) = process_param_list((yyvsp[(1) - (1)].param)); }
break;
case 64:
/* Line 1806 of yacc.c */
-#line 654 "parser.y"
+#line 740 "parser.y"
{ (yyval.param) = process_param_list((yyvsp[(1) - (2)].param)); }
break;
case 65:
/* Line 1806 of yacc.c */
-#line 658 "parser.y"
+#line 744 "parser.y"
{ (yyval.param) = NULL; }
break;
case 66:
/* Line 1806 of yacc.c */
-#line 660 "parser.y"
+#line 746 "parser.y"
{ (yyvsp[(2) - (2)].param)->next = (yyvsp[(1) - (2)].param); (yyval.param) = (yyvsp[(2) - (2)].param); }
break;
case 67:
/* Line 1806 of yacc.c */
-#line 665 "parser.y"
+#line 751 "parser.y"
{
BEGIN_ACTION;
(yyval.param) = _gmx_selexpr_create_param((yyvsp[(1) - (2)].str));
case 68:
/* Line 1806 of yacc.c */
-#line 673 "parser.y"
+#line 759 "parser.y"
{ (yyval.val) = NULL; }
break;
case 69:
/* Line 1806 of yacc.c */
-#line 674 "parser.y"
+#line 760 "parser.y"
{ (yyval.val) = (yyvsp[(1) - (1)].val); }
break;
case 70:
/* Line 1806 of yacc.c */
-#line 675 "parser.y"
+#line 761 "parser.y"
{ (yyval.val) = (yyvsp[(2) - (3)].val); }
break;
case 71:
/* Line 1806 of yacc.c */
-#line 679 "parser.y"
+#line 765 "parser.y"
{ (yyval.val) = (yyvsp[(1) - (1)].val); }
break;
case 72:
/* Line 1806 of yacc.c */
-#line 681 "parser.y"
+#line 767 "parser.y"
{ (yyvsp[(2) - (2)].val)->next = (yyvsp[(1) - (2)].val); (yyval.val) = (yyvsp[(2) - (2)].val); }
break;
case 73:
/* Line 1806 of yacc.c */
-#line 683 "parser.y"
+#line 769 "parser.y"
{ (yyvsp[(3) - (3)].val)->next = (yyvsp[(1) - (3)].val); (yyval.val) = (yyvsp[(3) - (3)].val); }
break;
case 74:
/* Line 1806 of yacc.c */
-#line 687 "parser.y"
+#line 773 "parser.y"
{ (yyval.val) = (yyvsp[(1) - (1)].val); }
break;
case 75:
/* Line 1806 of yacc.c */
-#line 688 "parser.y"
+#line 774 "parser.y"
{ (yyval.val) = (yyvsp[(2) - (3)].val); }
break;
case 76:
/* Line 1806 of yacc.c */
-#line 692 "parser.y"
+#line 778 "parser.y"
{ (yyval.val) = (yyvsp[(1) - (1)].val); }
break;
case 77:
/* Line 1806 of yacc.c */
-#line 694 "parser.y"
+#line 780 "parser.y"
{ (yyvsp[(2) - (2)].val)->next = (yyvsp[(1) - (2)].val); (yyval.val) = (yyvsp[(2) - (2)].val); }
break;
case 78:
/* Line 1806 of yacc.c */
-#line 696 "parser.y"
+#line 782 "parser.y"
{ (yyvsp[(3) - (3)].val)->next = (yyvsp[(1) - (3)].val); (yyval.val) = (yyvsp[(3) - (3)].val); }
break;
case 79:
/* Line 1806 of yacc.c */
-#line 700 "parser.y"
+#line 786 "parser.y"
{
BEGIN_ACTION;
- (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel));
+ (yyval.val) = _gmx_selexpr_create_value_expr(get((yyvsp[(1) - (1)].sel)));
END_ACTION;
}
break;
case 80:
/* Line 1806 of yacc.c */
-#line 706 "parser.y"
+#line 792 "parser.y"
{
BEGIN_ACTION;
- (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel));
+ (yyval.val) = _gmx_selexpr_create_value_expr(get((yyvsp[(1) - (1)].sel)));
END_ACTION;
}
break;
case 81:
/* Line 1806 of yacc.c */
-#line 712 "parser.y"
+#line 798 "parser.y"
{
BEGIN_ACTION;
- (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel));
+ (yyval.val) = _gmx_selexpr_create_value_expr(get((yyvsp[(1) - (1)].sel)));
END_ACTION;
}
break;
case 82:
/* Line 1806 of yacc.c */
-#line 718 "parser.y"
+#line 804 "parser.y"
{
BEGIN_ACTION;
- (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel));
+ (yyval.val) = _gmx_selexpr_create_value_expr(get((yyvsp[(1) - (1)].sel)));
END_ACTION;
}
break;
case 83:
/* Line 1806 of yacc.c */
-#line 723 "parser.y"
+#line 809 "parser.y"
{ (yyval.val) = (yyvsp[(1) - (1)].val); }
break;
case 84:
/* Line 1806 of yacc.c */
-#line 728 "parser.y"
+#line 814 "parser.y"
{
BEGIN_ACTION;
(yyval.val) = _gmx_selexpr_create_value(INT_VALUE);
case 85:
/* Line 1806 of yacc.c */
-#line 735 "parser.y"
+#line 821 "parser.y"
{
BEGIN_ACTION;
(yyval.val) = _gmx_selexpr_create_value(REAL_VALUE);
case 86:
/* Line 1806 of yacc.c */
-#line 742 "parser.y"
+#line 828 "parser.y"
{
BEGIN_ACTION;
(yyval.val) = _gmx_selexpr_create_value(STR_VALUE);
case 87:
/* Line 1806 of yacc.c */
-#line 748 "parser.y"
+#line 834 "parser.y"
{ (yyval.val) = (yyvsp[(1) - (1)].val); }
break;
case 88:
/* Line 1806 of yacc.c */
-#line 753 "parser.y"
+#line 839 "parser.y"
{
BEGIN_ACTION;
(yyval.val) = _gmx_selexpr_create_value(INT_VALUE);
case 89:
/* Line 1806 of yacc.c */
-#line 760 "parser.y"
+#line 846 "parser.y"
{
BEGIN_ACTION;
(yyval.val) = _gmx_selexpr_create_value(REAL_VALUE);
case 90:
/* Line 1806 of yacc.c */
-#line 767 "parser.y"
+#line 853 "parser.y"
{
BEGIN_ACTION;
(yyval.val) = _gmx_selexpr_create_value(REAL_VALUE);
/* Line 1806 of yacc.c */
-#line 2832 "parser.cpp"
+#line 2935 "parser.cpp"
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
/* Line 2067 of yacc.c */
-#line 775 "parser.y"
+#line 861 "parser.y"
static t_selexpr_value *
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
+/* "%code requires" blocks. */
+
+/* Line 2068 of yacc.c */
+#line 166 "parser.y"
+
+#include "selelem.h"
+
+
+
+/* Line 2068 of yacc.c */
+#line 44 "parser.h"
/* Tokens. */
#ifndef YYTOKENTYPE
{
/* Line 2068 of yacc.c */
-#line 104 "parser.y"
+#line 170 "parser.y"
int i;
real r;
char *str;
struct gmx_ana_selmethod_t *meth;
- struct t_selelem *sel;
+ gmx::SelectionTreeElementPointer *sel;
struct t_selexpr_value *val;
struct t_selexpr_param *param;
/* Line 2068 of yacc.c */
-#line 99 "parser.h"
+#line 110 "parser.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
#include <exception>
+#include "gromacs/legacyheaders/smalloc.h"
#include "gromacs/legacyheaders/string2.h"
#include "parsetree.h"
#include "scanner.h"
+using gmx::scoped_ptr_sfree;
+using gmx::SelectionTreeElement;
+using gmx::SelectionTreeElementPointer;
+
//! Helper method to reorder a list of parameter values and to count the values.
static t_selexpr_value *
process_value_list(t_selexpr_value *values, int *nr);
static t_selexpr_param *
process_param_list(t_selexpr_param *params);
+/*! \brief
+ * Retrieves a selection tree pointer from a semantic value.
+ *
+ * \param[in] src Semantic value to get the tree from.
+ * \returns Pointer to the selection tree.
+ *
+ * There should be no statements that may throw exceptions in actions before
+ * this function has been called for all semantic values that have a tree
+ * argument. Together with set(), this function abstracts away exception
+ * safety issues that arise from the use of a plain pointer for storing the
+ * selection tree semantic values.
+ *
+ * Does not throw.
+ */
+static SelectionTreeElementPointer
+get(SelectionTreeElementPointer *src)
+{
+ SelectionTreeElementPointer result;
+ if (src != NULL)
+ {
+ result.swap(*src);
+ delete src;
+ }
+ return result;
+}
+/*! \brief
+ * Sets a selection tree pointer to a semantic value.
+ *
+ * \param[out] dest Semantic value to set the tree to.
+ * \param[in] value Pointer to the selection tree to set.
+ * \throws std::bad_alloc if out of memory.
+ *
+ * This should be the last statement before ::END_ACTION, except for a
+ * possible ::CHECK_SEL.
+ */
+static void
+set(SelectionTreeElementPointer *&dest,
+ const SelectionTreeElementPointer &value)
+{
+ dest = new SelectionTreeElementPointer(value);
+}
+/*! \brief
+ * Checks that a valid tree was set.
+ *
+ * Should be called after set() if it was used to set a value where NULL
+ * pointer indicates an error.
+ *
+ * \todo
+ * Get rid of this macro. It should now be possible to handle all errors using
+ * exceptions.
+ */
+#define CHECK_SEL(sel) \
+ if (!*(sel)) { \
+ delete sel; \
+ YYERROR; \
+ }
+
//! Error handler needed by Bison.
static void
yyerror(yyscan_t, char const *s);
//!\}
%}
+%code requires{
+#include "selelem.h"
+}
+
%union{
int i;
real r;
char *str;
struct gmx_ana_selmethod_t *meth;
- struct t_selelem *sel;
+ gmx::SelectionTreeElementPointer *sel;
struct t_selexpr_value *val;
struct t_selexpr_param *param;
%destructor { free($$); } HELP_TOPIC STR IDENTIFIER CMP_OP string
%destructor { if($$) free($$); } PARAM
-%destructor { if($$) _gmx_selelem_free($$); } command cmd_plain
-%destructor { _gmx_selelem_free_chain($$); } selection
-%destructor { _gmx_selelem_free($$); } sel_expr num_expr str_expr pos_expr
+%destructor { delete $$; } commands command cmd_plain selection
+%destructor { delete $$; } sel_expr num_expr str_expr pos_expr
%destructor { _gmx_selexpr_free_params($$); } method_params method_param_list method_param
%destructor { _gmx_selexpr_free_values($$); } value_list value_list_contents value_item value_item_range
%destructor { _gmx_selexpr_free_values($$); } basic_value_list basic_value_list_contents basic_value_item
| commands command
{
BEGIN_ACTION;
- $$ = _gmx_sel_append_selection($2, $1, scanner);
+ set($$, _gmx_sel_append_selection(get($2), get($1), scanner));
if (_gmx_sel_parser_should_finish(scanner))
YYACCEPT;
END_ACTION;
| TOK_INT
{
BEGIN_ACTION;
- t_selelem *s, *p;
- s = _gmx_sel_init_group_by_id($1, scanner);
- if (s == NULL) YYERROR;
- p = _gmx_sel_init_position(s, NULL, scanner);
- if (p == NULL) YYERROR;
- $$ = _gmx_sel_init_selection(strdup(s->name), p, scanner);
+ SelectionTreeElementPointer s
+ = _gmx_sel_init_group_by_id($1, scanner);
+ if (!s) YYERROR;
+ SelectionTreeElementPointer p
+ = _gmx_sel_init_position(s, NULL, scanner);
+ if (!p) YYERROR;
+ set($$, _gmx_sel_init_selection(s->name, p, scanner));
END_ACTION;
}
| string
{
BEGIN_ACTION;
- t_selelem *s, *p;
- s = _gmx_sel_init_group_by_name($1, scanner);
- free($1);
- if (s == NULL) YYERROR;
- p = _gmx_sel_init_position(s, NULL, scanner);
- if (p == NULL) YYERROR;
- $$ = _gmx_sel_init_selection(strdup(s->name), p, scanner);
+ scoped_ptr_sfree nameGuard($1);
+ SelectionTreeElementPointer s
+ = _gmx_sel_init_group_by_name($1, scanner);
+ if (!s) YYERROR;
+ SelectionTreeElementPointer p
+ = _gmx_sel_init_position(s, NULL, scanner);
+ if (!p) YYERROR;
+ set($$, _gmx_sel_init_selection(s->name, p, scanner));
END_ACTION;
}
| selection
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_selection(NULL, $1, scanner);
+ set($$, _gmx_sel_init_selection(NULL, get($1), scanner));
END_ACTION;
}
| string selection
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_selection($1, $2, scanner);
+ scoped_ptr_sfree nameGuard($1);
+ set($$, _gmx_sel_init_selection($1, get($2), scanner));
END_ACTION;
}
| IDENTIFIER '=' sel_expr
{
BEGIN_ACTION;
- $$ = _gmx_sel_assign_variable($1, $3, scanner);
+ scoped_ptr_sfree nameGuard($1);
+ set($$, _gmx_sel_assign_variable($1, get($3), scanner));
END_ACTION;
}
| IDENTIFIER '=' num_expr
{
BEGIN_ACTION;
- $$ = _gmx_sel_assign_variable($1, $3, scanner);
+ scoped_ptr_sfree nameGuard($1);
+ set($$, _gmx_sel_assign_variable($1, get($3), scanner));
END_ACTION;
}
| IDENTIFIER '=' pos_expr
{
BEGIN_ACTION;
- $$ = _gmx_sel_assign_variable($1, $3, scanner);
+ scoped_ptr_sfree nameGuard($1);
+ set($$, _gmx_sel_assign_variable($1, get($3), scanner));
END_ACTION;
}
;
| sel_expr
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_position($1, NULL, scanner);
- if ($$ == NULL) YYERROR;
+ set($$, _gmx_sel_init_position(get($1), NULL, scanner));
+ CHECK_SEL($$);
END_ACTION;
}
| '(' selection ')' { $$ = $2; }
| selection MODIFIER method_params
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_modifier($2, $3, $1, scanner);
- if ($$ == NULL) YYERROR;
+ set($$, _gmx_sel_init_modifier($2, $3, get($1), scanner));
+ CHECK_SEL($$);
END_ACTION;
}
;
sel_expr: NOT sel_expr
{
BEGIN_ACTION;
- $$ = _gmx_selelem_create(SEL_BOOLEAN);
- $$->u.boolt = BOOL_NOT;
- $$->child = $2;
+ SelectionTreeElementPointer arg(get($2));
+ SelectionTreeElementPointer sel(
+ new SelectionTreeElement(SEL_BOOLEAN));
+ sel->u.boolt = BOOL_NOT;
+ sel->child = arg;
+ set($$, sel);
END_ACTION;
}
| sel_expr AND sel_expr
{
BEGIN_ACTION;
- $$ = _gmx_selelem_create(SEL_BOOLEAN);
- $$->u.boolt = BOOL_AND;
- $$->child = $1; $$->child->next = $3;
+ SelectionTreeElementPointer arg1(get($1)), arg2(get($3));
+ SelectionTreeElementPointer sel(
+ new SelectionTreeElement(SEL_BOOLEAN));
+ sel->u.boolt = BOOL_AND;
+ sel->child = arg1; sel->child->next = arg2;
+ set($$, sel);
END_ACTION;
}
| sel_expr OR sel_expr
{
BEGIN_ACTION;
- $$ = _gmx_selelem_create(SEL_BOOLEAN);
- $$->u.boolt = BOOL_OR;
- $$->child = $1; $$->child->next = $3;
+ SelectionTreeElementPointer arg1(get($1)), arg2(get($3));
+ SelectionTreeElementPointer sel(
+ new SelectionTreeElement(SEL_BOOLEAN));
+ sel->u.boolt = BOOL_OR;
+ sel->child = arg1; sel->child->next = arg2;
+ set($$, sel);
END_ACTION;
}
| '(' sel_expr ')' { $$ = $2; }
sel_expr: num_expr CMP_OP num_expr
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_comparison($1, $3, $2, scanner);
- if ($$ == NULL) YYERROR;
+ set($$, _gmx_sel_init_comparison(get($1), get($3), $2, scanner));
+ CHECK_SEL($$);
END_ACTION;
}
;
sel_expr: GROUP string
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_group_by_name($2, scanner);
- free($2);
- if ($$ == NULL) YYERROR;
+ scoped_ptr_sfree nameGuard($2);
+ set($$, _gmx_sel_init_group_by_name($2, scanner));
+ CHECK_SEL($$);
END_ACTION;
}
| GROUP TOK_INT
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_group_by_id($2, scanner);
- if ($$ == NULL) YYERROR;
+ set($$, _gmx_sel_init_group_by_id($2, scanner));
+ CHECK_SEL($$);
END_ACTION;
}
;
sel_expr: pos_mod KEYWORD_GROUP
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
- if ($$ == NULL) YYERROR;
+ set($$, _gmx_sel_init_keyword($2, NULL, $1, scanner));
+ CHECK_SEL($$);
END_ACTION;
}
| pos_mod KEYWORD_STR basic_value_list
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_keyword($2, process_value_list($3, NULL), $1, scanner);
- if ($$ == NULL) YYERROR;
+ set($$, _gmx_sel_init_keyword($2, process_value_list($3, NULL), $1, scanner));
+ CHECK_SEL($$);
END_ACTION;
}
| pos_mod KEYWORD_NUMERIC basic_value_list
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_keyword($2, process_value_list($3, NULL), $1, scanner);
- if ($$ == NULL) YYERROR;
+ set($$, _gmx_sel_init_keyword($2, process_value_list($3, NULL), $1, scanner));
+ CHECK_SEL($$);
END_ACTION;
}
;
sel_expr: pos_mod METHOD_GROUP method_params
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_method($2, $3, $1, scanner);
- if ($$ == NULL) YYERROR;
+ set($$, _gmx_sel_init_method($2, $3, $1, scanner));
+ CHECK_SEL($$);
END_ACTION;
}
;
num_expr: TOK_INT
{
BEGIN_ACTION;
- $$ = _gmx_selelem_create(SEL_CONST);
- _gmx_selelem_set_vtype($$, INT_VALUE);
- _gmx_selvalue_reserve(&$$->v, 1);
- $$->v.u.i[0] = $1;
+ SelectionTreeElementPointer sel(
+ new SelectionTreeElement(SEL_CONST));
+ _gmx_selelem_set_vtype(sel, INT_VALUE);
+ _gmx_selvalue_reserve(&sel->v, 1);
+ sel->v.u.i[0] = $1;
+ set($$, sel);
END_ACTION;
}
| TOK_REAL
{
BEGIN_ACTION;
- $$ = _gmx_selelem_create(SEL_CONST);
- _gmx_selelem_set_vtype($$, REAL_VALUE);
- _gmx_selvalue_reserve(&$$->v, 1);
- $$->v.u.r[0] = $1;
+ SelectionTreeElementPointer sel(
+ new SelectionTreeElement(SEL_CONST));
+ _gmx_selelem_set_vtype(sel, REAL_VALUE);
+ _gmx_selvalue_reserve(&sel->v, 1);
+ sel->v.u.r[0] = $1;
+ set($$, sel);
END_ACTION;
}
;
num_expr: pos_mod KEYWORD_NUMERIC %prec NUM_REDUCT
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
- if ($$ == NULL) YYERROR;
+ set($$, _gmx_sel_init_keyword($2, NULL, $1, scanner));
+ CHECK_SEL($$);
END_ACTION;
}
| pos_mod METHOD_NUMERIC method_params
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_method($2, $3, $1, scanner);
- if ($$ == NULL) YYERROR;
+ set($$, _gmx_sel_init_method($2, $3, $1, scanner));
+ CHECK_SEL($$);
END_ACTION;
}
;
num_expr: num_expr '+' num_expr
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_arithmetic($1, $3, '+', scanner);
+ set($$, _gmx_sel_init_arithmetic(get($1), get($3), '+', scanner));
END_ACTION;
}
| num_expr '-' num_expr
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_arithmetic($1, $3, '-', scanner);
+ set($$, _gmx_sel_init_arithmetic(get($1), get($3), '-', scanner));
END_ACTION;
}
| num_expr '*' num_expr
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_arithmetic($1, $3, '*', scanner);
+ set($$, _gmx_sel_init_arithmetic(get($1), get($3), '*', scanner));
END_ACTION;
}
| num_expr '/' num_expr
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_arithmetic($1, $3, '/', scanner);
+ set($$, _gmx_sel_init_arithmetic(get($1), get($3), '/', scanner));
END_ACTION;
}
| '-' num_expr %prec UNARY_NEG
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_arithmetic($2, NULL, '-', scanner);
+ set($$, _gmx_sel_init_arithmetic(get($2), SelectionTreeElementPointer(), '-', scanner));
END_ACTION;
}
| num_expr '^' num_expr
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_arithmetic($1, $3, '^', scanner);
+ set($$, _gmx_sel_init_arithmetic(get($1), get($3), '^', scanner));
END_ACTION;
}
| '(' num_expr ')' { $$ = $2; }
str_expr: string
{
BEGIN_ACTION;
- $$ = _gmx_selelem_create(SEL_CONST);
- _gmx_selelem_set_vtype($$, STR_VALUE);
- _gmx_selvalue_reserve(&$$->v, 1);
- $$->v.u.s[0] = $1;
+ SelectionTreeElementPointer sel(
+ new SelectionTreeElement(SEL_CONST));
+ _gmx_selelem_set_vtype(sel, STR_VALUE);
+ _gmx_selvalue_reserve(&sel->v, 1);
+ sel->v.u.s[0] = $1;
+ set($$, sel);
END_ACTION;
}
| pos_mod KEYWORD_STR
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
- if ($$ == NULL) YYERROR;
+ set($$, _gmx_sel_init_keyword($2, NULL, $1, scanner));
+ CHECK_SEL($$);
END_ACTION;
}
;
pos_expr: '[' number ',' number ',' number ']'
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_const_position($2, $4, $6);
+ set($$, _gmx_sel_init_const_position($2, $4, $6));
END_ACTION;
}
;
pos_expr: METHOD_POS method_params
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_method($1, $2, NULL, scanner);
- if ($$ == NULL) YYERROR;
+ set($$, _gmx_sel_init_method($1, $2, NULL, scanner));
+ CHECK_SEL($$);
END_ACTION;
}
;
pos_expr: KEYWORD_POS OF sel_expr %prec PARAM_REDUCT
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_position($3, $1, scanner);
- if ($$ == NULL) YYERROR;
+ set($$, _gmx_sel_init_position(get($3), $1, scanner));
+ CHECK_SEL($$);
END_ACTION;
}
;
sel_expr: VARIABLE_GROUP
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_variable_ref($1);
+ set($$, _gmx_sel_init_variable_ref(get($1)));
END_ACTION;
}
;
num_expr: VARIABLE_NUMERIC
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_variable_ref($1);
+ set($$, _gmx_sel_init_variable_ref(get($1)));
END_ACTION;
}
;
pos_expr: VARIABLE_POS
{
BEGIN_ACTION;
- $$ = _gmx_sel_init_variable_ref($1);
+ set($$, _gmx_sel_init_variable_ref(get($1)));
END_ACTION;
}
;
value_item: sel_expr %prec PARAM_REDUCT
{
BEGIN_ACTION;
- $$ = _gmx_selexpr_create_value_expr($1);
+ $$ = _gmx_selexpr_create_value_expr(get($1));
END_ACTION;
}
| pos_expr %prec PARAM_REDUCT
{
BEGIN_ACTION;
- $$ = _gmx_selexpr_create_value_expr($1);
+ $$ = _gmx_selexpr_create_value_expr(get($1));
END_ACTION;
}
| num_expr %prec PARAM_REDUCT
{
BEGIN_ACTION;
- $$ = _gmx_selexpr_create_value_expr($1);
+ $$ = _gmx_selexpr_create_value_expr(get($1));
END_ACTION;
}
| str_expr %prec PARAM_REDUCT
{
BEGIN_ACTION;
- $$ = _gmx_selexpr_create_value_expr($1);
+ $$ = _gmx_selexpr_create_value_expr(get($1));
END_ACTION;
}
| value_item_range { $$ = $1; }
* and bookkeeping are done by functions in scanner_internal.cpp) and uses the
* grammar rules to decide what to do with them. Whenever a grammar rule
* matches, a corresponding function in parsetree.cpp is called to construct
- * either a temporary representation for the object or a ::t_selelem object
+ * either a temporary representation for the object or a
+ * gmx::SelectionTreeElement object
* (some simple rules are handled internally in parser.y).
* When a complete selection has been parsed, the functions in parsetree.cpp
* also take care of updating the ::gmx_ana_selcollection_t structure
* appropriately.
*
- * The rest of this page describes the resulting ::t_selelem object tree.
+ * The rest of this page describes the resulting gmx::SelectionTreeElement
+ * object tree.
* Before the selections can be evaluated, this tree needs to be passed to
* the selection compiler, which is described on a separate page:
* \ref page_module_selection_compiler
* \section selparser_tree Element tree constructed by the parser
*
* The parser initializes the following fields in all selection elements:
- * \c t_selelem::name, \c t_selelem::type, \c t_selelem::v\c .type,
- * \c t_selelem::flags, \c t_selelem::child, \c t_selelem::next, and
- * \c t_selelem::refcount.
+ * gmx::SelectionTreeElement::name, gmx::SelectionTreeElement::type,
+ * gmx::SelectionTreeElement::v\c .type,
+ * gmx::SelectionTreeElement::flags, gmx::SelectionTreeElement::child, and
+ * gmx::SelectionTreeElement::next.
* Some other fields are also initialized for particular element types as
* discussed below.
* Fields that are not initialized are set to zero, NULL, or other similar
* The rest of the children are \ref SEL_MODIFIER elements with
* \ref NO_VALUE, in the order given by the user.
* .
- * The name of the selection/variable is stored in \c t_selelem::cgrp\c .name.
+ * The name of the selection/variable is stored in
+ * gmx::SelectionTreeElement::cgrp\c .name.
* It is set to either the name provided by the user or the selection string
* for selections not explicitly named by the user.
* \ref SEL_ROOT or \ref SEL_SUBEXPR elements do not appear anywhere else.
* - \ref GROUP_VALUE method parameters if provided using external index
* groups,
* .
- * For group-valued elements, the value is stored in \c t_selelem::cgrp;
- * other types of values are stored in \c t_selelem::v.
+ * For group-valued elements, the value is stored in
+ * gmx::SelectionTreeElement::cgrp; other types of values are stored in
+ * gmx::SelectionTreeElement::v.
* Constants that appear as parameters for selection methods are not present
* in the selection tree unless they have \ref GROUP_VALUE.
* \ref SEL_CONST elements have no children.
*
* \ref SEL_EXPRESSION and \ref SEL_MODIFIER elements are treated very
* similarly. The \c gmx_ana_selmethod_t structure corresponding to the
- * evaluation method is in \c t_selelem::method, and the method data in
- * \c t_selelem::mdata has been allocated using sel_datafunc().
- * If a non-standard reference position type was set, \c t_selelem::pc has
- * also been created, but only the type has been set.
+ * evaluation method is in gmx::SelectionTreeElement::method, and the method
+ * data in gmx::SelectionTreeElement::mdata has been allocated using
+ * sel_datafunc().
+ * If a non-standard reference position type was set,
+ * gmx::SelectionTreeElement::pc has also been created, but only the type has
+ * been set.
* All children of these elements are of the type \ref SEL_SUBEXPRREF, and
* each describes a selection that needs to be evaluated to obtain a value
* for one parameter of the method.
* \subsection selparser_tree_subexpr Subexpression elements
*
* \ref SEL_SUBEXPR elements only appear for variables, as described above.
- * \c t_selelem::name points to the name of the variable (from the
+ * gmx::SelectionTreeElement::name points to the name of the variable (from the
* \ref SEL_ROOT element).
* The element always has exactly one child, which represents the value of
* the variable.
- * \ref SEL_SUBEXPR element is the only element type that can have
- * \c t_selelem::refcount different from 1.
*
* \ref SEL_SUBEXPRREF elements are used for two purposes:
* - Variable references that need to be evaluated (i.e., there is a
* \ref SEL_SUBEXPR element for the variable) are represented using
* \ref SEL_SUBEXPRREF elements.
- * In this case, \c t_selelem::param is NULL, and the first and only
- * child of the element is the \ref SEL_SUBEXPR element of the variable.
+ * In this case, gmx::SelectionTreeElement::param is NULL, and the first and
+ * only child of the element is the \ref SEL_SUBEXPR element of the
+ * variable.
* Such references can appear anywhere where the variable value
* (the child of the \ref SEL_SUBEXPR element) would be valid.
* - Children of \ref SEL_EXPRESSION and \ref SEL_MODIFIER elements are
- * always of this type. For these elements, \c t_selelem::param is
- * initialized to point to the parameter that receives the value from
+ * always of this type. For these elements, gmx::SelectionTreeElement::param
+ * is initialized to point to the parameter that receives the value from
* the expression.
* Each such element has exactly one child, which can be of any type;
* the \ref SEL_SUBEXPR element of a variable is used if the value comes
*
* One \ref SEL_BOOLEAN element is created for each boolean keyword in the
* input, and the tree structure represents the evaluation order.
- * The \c t_selelem::boolt type gives the type of the operation.
+ * The gmx::SelectionTreeElement::boolt type gives the type of the operation.
* Each element has exactly two children (one for \ref BOOL_NOT elements),
* which are in the order given in the input.
* The children always have \ref GROUP_VALUE, but different element types
*
* One \ref SEL_ARITHMETIC element is created for each arithmetic operation in
* the input, and the tree structure represents the evaluation order.
- * The \c t_selelem::optype type gives the name of the operation.
+ * The gmx::SelectionTreeElement::optype type gives the name of the operation.
* Each element has exactly two children (one for unary negation elements),
* which are in the order given in the input.
*/
#include <boost/exception_ptr.hpp>
#include <boost/shared_ptr.hpp>
-#include "futil.h"
-#include "smalloc.h"
-#include "string2.h"
+#include "gromacs/legacyheaders/futil.h"
+#include "gromacs/legacyheaders/smalloc.h"
+#include "gromacs/legacyheaders/string2.h"
#include "gromacs/onlinehelp/helpmanager.h"
#include "gromacs/onlinehelp/helpwritercontext.h"
#include "scanner.h"
+using gmx::SelectionTreeElement;
+using gmx::SelectionTreeElementPointer;
+
void
_gmx_selparser_error(yyscan_t scanner, const char *fmt, ...)
{
t_selexpr_value *
_gmx_selexpr_create_value(e_selvalue_t type)
{
- t_selexpr_value *value;
- snew(value, 1);
+ t_selexpr_value *value = new t_selexpr_value();
value->type = type;
- value->bExpr = false;
+ memset(&value->u, 0, sizeof(value->u));
value->next = NULL;
return value;
}
* \returns Pointer to the newly allocated value.
*/
t_selexpr_value *
-_gmx_selexpr_create_value_expr(t_selelem *expr)
+_gmx_selexpr_create_value_expr(const SelectionTreeElementPointer &expr)
{
- t_selexpr_value *value;
- snew(value, 1);
+ t_selexpr_value *value = new t_selexpr_value();
value->type = expr->v.type;
- value->bExpr = true;
- value->u.expr = expr;
+ value->expr = expr;
+ memset(&value->u, 0, sizeof(value->u));
value->next = NULL;
return value;
}
void
_gmx_selexpr_free_values(t_selexpr_value *value)
{
- t_selexpr_value *old;
while (value)
{
- if (value->bExpr)
- {
- if (value->u.expr)
- {
- _gmx_selelem_free(value->u.expr);
- }
- }
- else if (value->type == STR_VALUE)
+ if (!value->expr && value->type == STR_VALUE)
{
sfree(value->u.s);
}
- old = value;
+ t_selexpr_value *old = value;
value = value->next;
- sfree(old);
+ delete old;
}
}
* is set for an element, the function returns immediately, and the recursive
* operation does not descend beyond such elements.
*/
-int
-_gmx_selelem_update_flags(t_selelem *sel, yyscan_t scanner)
+void
+_gmx_selelem_update_flags(const SelectionTreeElementPointer &sel,
+ yyscan_t scanner)
{
- t_selelem *child;
- int rc;
bool bUseChildType=false;
bool bOnlySingleChildren;
/* Return if the flags have already been set */
if (sel->flags & SEL_FLAGSSET)
{
- return 0;
+ return;
}
/* Set the flags based on the current element type */
switch (sel->type)
}
/* Loop through children to propagate their flags upwards */
bOnlySingleChildren = true;
- child = sel->child;
+ SelectionTreeElementPointer child = sel->child;
while (child)
{
/* Update the child */
- rc = _gmx_selelem_update_flags(child, scanner);
- if (rc != 0)
- {
- return rc;
- }
+ _gmx_selelem_update_flags(child, scanner);
/* Propagate the dynamic flag */
sel->flags |= (child->flags & SEL_DYNAMIC);
/* Propagate the type flag if necessary and check for problems */
&& !(sel->flags & child->flags & SEL_VALTYPEMASK))
{
_gmx_selparser_error(scanner, "invalid combination of selection expressions");
- return gmx::eeInvalidInput;
+ // FIXME: Use an exception.
+ return;
}
sel->flags |= (child->flags & SEL_VALTYPEMASK);
}
}
/* Mark that the flags are set */
sel->flags |= SEL_FLAGSSET;
- return 0;
}
/*!
* Calls sel_datafunc() if one is specified for the method.
*/
void
-_gmx_selelem_init_method_params(t_selelem *sel, yyscan_t scanner)
+_gmx_selelem_init_method_params(const SelectionTreeElementPointer &sel,
+ yyscan_t scanner)
{
int nparams;
gmx_ana_selparam_t *orgparam;
* and calls _gmx_selelem_init_method_params();
*/
void
-_gmx_selelem_set_method(t_selelem *sel, gmx_ana_selmethod_t *method,
+_gmx_selelem_set_method(const SelectionTreeElementPointer &sel,
+ gmx_ana_selmethod_t *method,
yyscan_t scanner)
{
_gmx_selelem_set_vtype(sel, method->type);
* \returns 0 on success, a non-zero error code on error.
*/
static void
-set_refpos_type(gmx::PositionCalculationCollection *pcc, t_selelem *sel,
+set_refpos_type(gmx::PositionCalculationCollection *pcc,
+ const SelectionTreeElementPointer &sel,
const char *rpost, yyscan_t scanner)
{
if (!rpost)
* \param[in] scanner Scanner data structure.
* \returns The created selection element.
*
- * This function handles the creation of a \c t_selelem object for
+ * This function handles the creation of a gmx::SelectionTreeElement object for
* arithmetic expressions.
*/
-t_selelem *
-_gmx_sel_init_arithmetic(t_selelem *left, t_selelem *right, char op,
- yyscan_t scanner)
+SelectionTreeElementPointer
+_gmx_sel_init_arithmetic(const SelectionTreeElementPointer &left,
+ const SelectionTreeElementPointer &right,
+ char op, yyscan_t scanner)
{
- t_selelem *sel;
- char buf[2];
-
- buf[0] = op;
- buf[1] = 0;
- sel = _gmx_selelem_create(SEL_ARITHMETIC);
+ SelectionTreeElementPointer sel(new SelectionTreeElement(SEL_ARITHMETIC));
sel->v.type = REAL_VALUE;
switch(op)
{
case '/': sel->u.arith.type = ARITH_DIV; break;
case '^': sel->u.arith.type = ARITH_EXP; break;
}
+ char buf[2];
+ buf[0] = op;
+ buf[1] = 0;
sel->u.arith.opstr = strdup(buf);
sel->name = sel->u.arith.opstr;
sel->child = left;
* \param[in] scanner Scanner data structure.
* \returns The created selection element.
*
- * This function handles the creation of a \c t_selelem object for
+ * This function handles the creation of a gmx::SelectionTreeElement object for
* comparison expressions.
*/
-t_selelem *
-_gmx_sel_init_comparison(t_selelem *left, t_selelem *right, char *cmpop,
- yyscan_t scanner)
+SelectionTreeElementPointer
+_gmx_sel_init_comparison(const SelectionTreeElementPointer &left,
+ const SelectionTreeElementPointer &right,
+ char *cmpop, yyscan_t scanner)
{
- t_selelem *sel;
t_selexpr_param *params, *param;
const char *name;
gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
gmx::MessageStringContext context(errors, "In comparison initialization");
- sel = _gmx_selelem_create(SEL_EXPRESSION);
+ SelectionTreeElementPointer sel(new SelectionTreeElement(SEL_EXPRESSION));
_gmx_selelem_set_method(sel, &sm_compare, scanner);
/* Create the parameter for the left expression */
name = left->v.type == INT_VALUE ? "int1" : "real1";
if (!_gmx_sel_parse_params(params, sel->u.expr.method->nparams,
sel->u.expr.method->param, sel, scanner))
{
- _gmx_selelem_free(sel);
- return NULL;
+ return SelectionTreeElementPointer();
}
return sel;
* \param[in] scanner Scanner data structure.
* \returns The created selection element.
*
- * This function handles the creation of a \c t_selelem object for
+ * This function handles the creation of a gmx::SelectionTreeElement object for
* selection methods that do not take parameters.
*/
-t_selelem *
+SelectionTreeElementPointer
_gmx_sel_init_keyword(gmx_ana_selmethod_t *method, t_selexpr_value *args,
const char *rpost, yyscan_t scanner)
{
gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
- t_selelem *root, *child;
t_selexpr_param *params, *param;
t_selexpr_value *arg;
int nargs;
if (method->nparams > 0)
{
- GMX_ERROR_NORET(gmx::eeInternalError,
- "Keyword initialization called with non-keyword method");
- return NULL;
+ // TODO: Would assert be better?
+ GMX_THROW(gmx::InternalError(
+ "Keyword initialization called with non-keyword method"));
}
- root = _gmx_selelem_create(SEL_EXPRESSION);
- child = root;
+ SelectionTreeElementPointer root(new SelectionTreeElement(SEL_EXPRESSION));
+ SelectionTreeElementPointer child = root;
_gmx_selelem_set_method(child, method, scanner);
/* Initialize the evaluation of keyword matching if values are provided */
case REAL_VALUE: kwmethod = &sm_keyword_real; break;
case STR_VALUE: kwmethod = &sm_keyword_str; break;
default:
- GMX_ERROR_NORET(gmx::eeInternalError,
- "Unknown type for keyword selection");
_gmx_selexpr_free_values(args);
- goto on_error;
+ GMX_THROW(gmx::InternalError(
+ "Unknown type for keyword selection"));
}
/* Count the arguments */
nargs = 0;
arg = arg->next;
}
/* Initialize the selection element */
- root = _gmx_selelem_create(SEL_EXPRESSION);
+ root.reset(new SelectionTreeElement(SEL_EXPRESSION));
_gmx_selelem_set_method(root, kwmethod, scanner);
params = param = _gmx_selexpr_create_param(NULL);
param->nval = 1;
if (!_gmx_sel_parse_params(params, root->u.expr.method->nparams,
root->u.expr.method->param, root, scanner))
{
- goto on_error;
+ return SelectionTreeElementPointer();
}
}
- try
- {
- set_refpos_type(&sc->pcc, child, rpost, scanner);
- }
- catch (const std::exception &)
- {
- _gmx_selelem_free(root);
- throw;
- }
+ set_refpos_type(&sc->pcc, child, rpost, scanner);
return root;
-
-/* On error, free all memory and return NULL. */
-on_error:
- _gmx_selelem_free(root);
- return NULL;
}
/*!
* \param[in] scanner Scanner data structure.
* \returns The created selection element.
*
- * This function handles the creation of a \c t_selelem object for
+ * This function handles the creation of a gmx::SelectionTreeElement object for
* selection methods that take parameters.
*
* Part of the behavior of the \c same selection keyword is hardcoded into
* use of any keyword in \c "same KEYWORD as" without requiring special
* handling somewhere else (or sacrificing the simple syntax).
*/
-t_selelem *
+SelectionTreeElementPointer
_gmx_sel_init_method(gmx_ana_selmethod_t *method, t_selexpr_param *params,
const char *rpost, yyscan_t scanner)
{
gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
- t_selelem *root;
int rc;
gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
if (rc != 0)
{
_gmx_selexpr_free_params(params);
- return NULL;
+ return SelectionTreeElementPointer();
}
- root = _gmx_selelem_create(SEL_EXPRESSION);
+ SelectionTreeElementPointer root(new SelectionTreeElement(SEL_EXPRESSION));
_gmx_selelem_set_method(root, method, scanner);
/* Process the parameters */
if (!_gmx_sel_parse_params(params, root->u.expr.method->nparams,
root->u.expr.method->param, root, scanner))
{
- _gmx_selelem_free(root);
- return NULL;
- }
- try
- {
- set_refpos_type(&sc->pcc, root, rpost, scanner);
- }
- catch (const std::exception &)
- {
- _gmx_selelem_free(root);
- throw;
+ return SelectionTreeElementPointer();
}
+ set_refpos_type(&sc->pcc, root, rpost, scanner);
return root;
}
* \param[in] scanner Scanner data structure.
* \returns The created selection element.
*
- * This function handles the creation of a \c t_selelem object for
+ * This function handles the creation of a gmx::SelectionTreeElement object for
* selection modifiers.
*/
-t_selelem *
+SelectionTreeElementPointer
_gmx_sel_init_modifier(gmx_ana_selmethod_t *method, t_selexpr_param *params,
- t_selelem *sel, yyscan_t scanner)
+ const SelectionTreeElementPointer &sel, yyscan_t scanner)
{
- t_selelem *root;
- t_selelem *mod;
- t_selexpr_param *vparam;
-
gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
char buf[128];
sprintf(buf, "In keyword '%s'", method->name);
gmx::MessageStringContext context(errors, buf);
_gmx_sel_finish_method(scanner);
- mod = _gmx_selelem_create(SEL_MODIFIER);
+ SelectionTreeElementPointer mod(new SelectionTreeElement(SEL_MODIFIER));
_gmx_selelem_set_method(mod, method, scanner);
+ SelectionTreeElementPointer root;
if (method->type == NO_VALUE)
{
- t_selelem *child;
-
- child = sel;
+ SelectionTreeElementPointer child = sel;
while (child->next)
{
child = child->next;
}
else
{
+ t_selexpr_param *vparam;
+
vparam = _gmx_selexpr_create_param(NULL);
vparam->nval = 1;
vparam->value = _gmx_selexpr_create_value_expr(sel);
if (!_gmx_sel_parse_params(params, mod->u.expr.method->nparams,
mod->u.expr.method->param, mod, scanner))
{
- _gmx_selelem_free(mod);
- return NULL;
+ return SelectionTreeElementPointer();
}
return root;
* \param[in] scanner Scanner data structure.
* \returns The created selection element.
*
- * This function handles the creation of a \c t_selelem object for
+ * This function handles the creation of a gmx::SelectionTreeElement object for
* evaluation of reference positions.
*/
-t_selelem *
-_gmx_sel_init_position(t_selelem *expr, const char *type, yyscan_t scanner)
+SelectionTreeElementPointer
+_gmx_sel_init_position(const SelectionTreeElementPointer &expr,
+ const char *type, yyscan_t scanner)
{
- t_selelem *root;
t_selexpr_param *params;
gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
sprintf(buf, "In position evaluation");
gmx::MessageStringContext context(errors, buf);
- root = _gmx_selelem_create(SEL_EXPRESSION);
+ SelectionTreeElementPointer root(new SelectionTreeElement(SEL_EXPRESSION));
_gmx_selelem_set_method(root, &sm_keyword_pos, scanner);
- _gmx_selelem_set_kwpos_type(root, type);
+ _gmx_selelem_set_kwpos_type(root.get(), type);
/* Create the parameters for the parameter parser. */
params = _gmx_selexpr_create_param(NULL);
params->nval = 1;
if (!_gmx_sel_parse_params(params, root->u.expr.method->nparams,
root->u.expr.method->param, root, scanner))
{
- _gmx_selelem_free(root);
- return NULL;
+ return SelectionTreeElementPointer();
}
return root;
* \param[in] x,y,z Coordinates for the position.
* \returns The creates selection element.
*/
-t_selelem *
+SelectionTreeElementPointer
_gmx_sel_init_const_position(real x, real y, real z)
{
- t_selelem *sel;
rvec pos;
- sel = _gmx_selelem_create(SEL_CONST);
+ SelectionTreeElementPointer sel(new SelectionTreeElement(SEL_CONST));
_gmx_selelem_set_vtype(sel, POS_VALUE);
_gmx_selvalue_reserve(&sel->v, 1);
pos[XX] = x;
* See gmx_ana_indexgrps_find() for information on how \p name is matched
* against the index groups.
*/
-t_selelem *
+SelectionTreeElementPointer
_gmx_sel_init_group_by_name(const char *name, yyscan_t scanner)
{
gmx_ana_indexgrps_t *grps = _gmx_sel_lexer_indexgrps(scanner);
- t_selelem *sel;
if (!_gmx_sel_lexer_has_groups_set(scanner))
{
- sel = _gmx_selelem_create(SEL_GROUPREF);
+ SelectionTreeElementPointer sel(new SelectionTreeElement(SEL_GROUPREF));
_gmx_selelem_set_vtype(sel, GROUP_VALUE);
sel->u.gref.name = strdup(name);
sel->u.gref.id = -1;
- sel->name = name;
+ sel->name = sel->u.gref.name;
return sel;
}
if (!grps)
{
_gmx_selparser_error(scanner, "No index groups set; cannot match 'group %s'", name);
- return NULL;
+ return SelectionTreeElementPointer();
}
- sel = _gmx_selelem_create(SEL_CONST);
- _gmx_selelem_set_vtype(sel, GROUP_VALUE);
+ SelectionTreeElementPointer sel(new SelectionTreeElement(SEL_CONST));
+ _gmx_selelem_set_vtype(sel, GROUP_VALUE);
/* FIXME: The constness should not be cast away */
if (!gmx_ana_indexgrps_find(&sel->u.cgrp, grps, (char *)name))
{
_gmx_selparser_error(scanner, "Cannot match 'group %s'", name);
- _gmx_selelem_free(sel);
- return NULL;
+ return SelectionTreeElementPointer();
}
sel->name = sel->u.cgrp.name;
return sel;
* \returns The created constant selection element, or NULL if no matching
* index group found.
*/
-t_selelem *
+SelectionTreeElementPointer
_gmx_sel_init_group_by_id(int id, yyscan_t scanner)
{
gmx_ana_indexgrps_t *grps = _gmx_sel_lexer_indexgrps(scanner);
- t_selelem *sel;
if (!_gmx_sel_lexer_has_groups_set(scanner))
{
- sel = _gmx_selelem_create(SEL_GROUPREF);
+ SelectionTreeElementPointer sel(new SelectionTreeElement(SEL_GROUPREF));
_gmx_selelem_set_vtype(sel, GROUP_VALUE);
sel->u.gref.name = NULL;
sel->u.gref.id = id;
if (!grps)
{
_gmx_selparser_error(scanner, "No index groups set; cannot match 'group %d'", id);
- return NULL;
+ return SelectionTreeElementPointer();
}
- sel = _gmx_selelem_create(SEL_CONST);
+ SelectionTreeElementPointer sel(new SelectionTreeElement(SEL_CONST));
_gmx_selelem_set_vtype(sel, GROUP_VALUE);
if (!gmx_ana_indexgrps_extract(&sel->u.cgrp, grps, id))
{
_gmx_selparser_error(scanner, "Cannot match 'group %d'", id);
- _gmx_selelem_free(sel);
- return NULL;
+ return SelectionTreeElementPointer();
}
sel->name = sel->u.cgrp.name;
return sel;
* The reference count of \p sel is updated, but no other modifications are
* made.
*/
-t_selelem *
-_gmx_sel_init_variable_ref(t_selelem *sel)
+SelectionTreeElementPointer
+_gmx_sel_init_variable_ref(const SelectionTreeElementPointer &sel)
{
- t_selelem *ref;
+ SelectionTreeElementPointer ref;
if (sel->v.type == POS_VALUE && sel->type == SEL_CONST)
{
}
else
{
- ref = _gmx_selelem_create(SEL_SUBEXPRREF);
+ ref.reset(new SelectionTreeElement(SEL_SUBEXPRREF));
_gmx_selelem_set_vtype(ref, sel->v.type);
ref->name = sel->name;
ref->child = sel;
}
- sel->refcount++;
return ref;
}
* \param scanner Scanner data structure.
* \returns The created root selection element.
*
- * This function handles the creation of root (\ref SEL_ROOT) \c t_selelem
- * objects for selections.
+ * This function handles the creation of root (\ref SEL_ROOT)
+ * gmx::SelectionTreeElement objects for selections.
*/
-t_selelem *
-_gmx_sel_init_selection(char *name, t_selelem *sel, yyscan_t scanner)
+SelectionTreeElementPointer
+_gmx_sel_init_selection(const char *name,
+ const SelectionTreeElementPointer &sel,
+ yyscan_t scanner)
{
- t_selelem *root;
- int rc;
-
gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
char buf[1024];
sprintf(buf, "In selection '%s'", _gmx_sel_lexer_pselstr(scanner));
if (sel->v.type != POS_VALUE)
{
- GMX_ERROR_NORET(gmx::eeInternalError,
- "Each selection must evaluate to a position");
/* FIXME: Better handling of this error */
- sfree(name);
- return NULL;
+ GMX_THROW(gmx::InternalError(
+ "Each selection must evaluate to a position"));
}
- root = _gmx_selelem_create(SEL_ROOT);
+ SelectionTreeElementPointer root(new SelectionTreeElement(SEL_ROOT));
root->child = sel;
- /* Assign the name (this is done here to free it automatically in the case
- * of an error below). */
if (name)
{
- root->name = root->u.cgrp.name = name;
+ root->name = root->u.cgrp.name = strdup(name);
}
/* Update the flags */
- rc = _gmx_selelem_update_flags(root, scanner);
- if (rc != 0)
- {
- _gmx_selelem_free(root);
- return NULL;
- }
+ _gmx_selelem_update_flags(root, scanner);
/* If there is no name provided by the user, check whether the actual
* selection given was from an external group, and if so, use the name
* of the external group. */
if (!root->name)
{
- t_selelem *child = root->child;
+ SelectionTreeElementPointer child = root->child;
while (child->type == SEL_MODIFIER)
{
if (!child->child || child->child->type != SEL_SUBEXPRREF
/*!
- * \param[in] name Name of the variable (should not be freed after this
- * function).
+ * \param[in] name Name of the variable.
* \param[in] expr The selection element that evaluates the variable.
* \param scanner Scanner data structure.
* \returns The created root selection element.
*
- * This function handles the creation of root \c t_selelem objects for
- * variable assignments. A \ref SEL_ROOT element and a \ref SEL_SUBEXPR
+ * This function handles the creation of root gmx::SelectionTreeElement objects
+ * for variable assignments. A \ref SEL_ROOT element and a \ref SEL_SUBEXPR
* element are both created.
*/
-t_selelem *
-_gmx_sel_assign_variable(char *name, t_selelem *expr, yyscan_t scanner)
+SelectionTreeElementPointer
+_gmx_sel_assign_variable(const char *name,
+ const SelectionTreeElementPointer &expr,
+ yyscan_t scanner)
{
gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
const char *pselstr = _gmx_sel_lexer_pselstr(scanner);
- t_selelem *root = NULL;
- int rc;
+ SelectionTreeElementPointer root;
gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
char buf[1024];
sprintf(buf, "In selection '%s'", pselstr);
gmx::MessageStringContext context(errors, buf);
- rc = _gmx_selelem_update_flags(expr, scanner);
- if (rc != 0)
- {
- sfree(name);
- _gmx_selelem_free(expr);
- return NULL;
- }
+ _gmx_selelem_update_flags(expr, scanner);
/* Check if this is a constant non-group value */
if (expr->type == SEL_CONST && expr->v.type != GROUP_VALUE)
{
/* If so, just assign the constant value to the variable */
if (!_gmx_sel_add_var_symbol(sc->symtab, name, expr))
{
- _gmx_selelem_free(expr);
- sfree(name);
- return NULL;
+ return SelectionTreeElementPointer();
}
- _gmx_selelem_free(expr);
- sfree(name);
goto finish;
}
/* Check if we are assigning a variable to another variable */
/* If so, make a simple alias */
if (!_gmx_sel_add_var_symbol(sc->symtab, name, expr->child))
{
- _gmx_selelem_free(expr);
- sfree(name);
- return NULL;
+ return SelectionTreeElementPointer();
}
- _gmx_selelem_free(expr);
- sfree(name);
goto finish;
}
/* Create the root element */
- root = _gmx_selelem_create(SEL_ROOT);
- root->name = name;
- root->u.cgrp.name = name;
+ root.reset(new SelectionTreeElement(SEL_ROOT));
/* Create the subexpression element */
- root->child = _gmx_selelem_create(SEL_SUBEXPR);
+ root->child.reset(new SelectionTreeElement(SEL_SUBEXPR));
_gmx_selelem_set_vtype(root->child, expr->v.type);
- root->child->name = name;
- root->child->child = expr;
- /* Update flags */
- rc = _gmx_selelem_update_flags(root, scanner);
- if (rc != 0)
{
- _gmx_selelem_free(root);
- return NULL;
+ char *newName = strdup(name);
+ root->name = newName;
+ root->u.cgrp.name = newName;
+ root->child->name = newName;
}
+ root->child->child = expr;
+ /* Update flags */
+ _gmx_selelem_update_flags(root, scanner);
/* Add the variable to the symbol table */
if (!_gmx_sel_add_var_symbol(sc->symtab, name, root->child))
{
- _gmx_selelem_free(root);
- return NULL;
+ return SelectionTreeElementPointer();
}
finish:
srenew(sc->varstrs, sc->nvars + 1);
* Appends \p sel after the last root element, and returns either \p sel
* (if it was non-NULL) or the last element (if \p sel was NULL).
*/
-t_selelem *
-_gmx_sel_append_selection(t_selelem *sel, t_selelem *last, yyscan_t scanner)
+SelectionTreeElementPointer
+_gmx_sel_append_selection(const SelectionTreeElementPointer &sel,
+ SelectionTreeElementPointer last,
+ yyscan_t scanner)
{
gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
{
gmx::SelectionDataPointer selPtr(
new gmx::internal::SelectionData(
- sel, _gmx_sel_lexer_pselstr(scanner)));
+ sel.get(), _gmx_sel_lexer_pselstr(scanner)));
sc->sel.push_back(gmx::move(selPtr));
}
}
* The data types declared in this header are used by the parser to store
* intermediate data when constructing method expressions.
* In particular, the parameters for the method are stored.
- * The intermediate data is freed once a \c t_selelem object can be
- * constructed.
+ * The intermediate data is freed once a gmx::SelectionTreeElement object can
+ * be constructed.
*
* This is an implementation header: there should be no need to use it outside
* this directory.
* \author Teemu Murtola <teemu.murtola@cbr.su.se>
* \ingroup module_selection
*/
-#ifndef SELECTION_PARSETREE_H
-#define SELECTION_PARSETREE_H
+#ifndef GMX_SELECTION_PARSETREE_H
+#define GMX_SELECTION_PARSETREE_H
#include <exception>
-#include <types/simple.h>
+#include "gromacs/legacyheaders/types/simple.h"
-#include "gromacs/selection/selvalue.h"
+#include "selelem.h"
+#include "selvalue.h"
-struct t_selelem;
struct gmx_ana_indexgrps_t;
struct gmx_ana_selmethod_t;
struct gmx_ana_selparam_t;
/*! \internal \brief
* Describes a parsed value, possibly resulting from expression evaluation.
+ *
+ * \todo
+ * Make this a proper class.
*/
typedef struct t_selexpr_value
{
- /** Type of the value. */
+ //! Returns true if the value comes from expression evaluation.
+ bool hasExpressionValue() const { return expr; }
+
+ //! Type of the value.
e_selvalue_t type;
- /** true if the value is the result of an expression. */
- bool bExpr;
- /** The actual value. */
+ //! Expression pointer if the value is the result of an expression.
+ gmx::SelectionTreeElementPointer expr;
+ //! The actual value if \p expr is NULL.
union {
/** The integer value/range (\p type INT_VALUE); */
struct {
char *s;
/** The position value (\p type POS_VALUE); */
rvec x;
- /** The expression if \p bExpr is true. */
- struct t_selelem *expr;
} u;
/** Pointer to the next value. */
struct t_selexpr_value *next;
_gmx_selexpr_create_value(e_selvalue_t type);
/** Allocates and initializes an expression \c t_selexpr_value. */
t_selexpr_value *
-_gmx_selexpr_create_value_expr(struct t_selelem *expr);
+_gmx_selexpr_create_value_expr(const gmx::SelectionTreeElementPointer &expr);
/** Allocates and initializes a \c t_selexpr_param. */
t_selexpr_param *
_gmx_selexpr_create_param(char *name);
_gmx_selexpr_free_params(t_selexpr_param *param);
/** Propagates the flags for selection elements. */
-int
-_gmx_selelem_update_flags(struct t_selelem *sel, void *scanner);
+void
+_gmx_selelem_update_flags(const gmx::SelectionTreeElementPointer &sel,
+ void *scanner);
/** Initializes the method parameter data of \ref SEL_EXPRESSION and
* \ref SEL_MODIFIER elements. */
void
-_gmx_selelem_init_method_params(struct t_selelem *sel, void *scanner);
+_gmx_selelem_init_method_params(const gmx::SelectionTreeElementPointer &sel,
+ void *scanner);
/** Initializes the method for a \ref SEL_EXPRESSION selection element. */
void
-_gmx_selelem_set_method(struct t_selelem *sel,
+_gmx_selelem_set_method(const gmx::SelectionTreeElementPointer &sel,
struct gmx_ana_selmethod_t *method, void *scanner);
-/** Creates a \c t_selelem for arithmetic expression evaluation. */
-struct t_selelem *
-_gmx_sel_init_arithmetic(struct t_selelem *left, struct t_selelem *right,
+/** Creates a gmx::SelectionTreeElement for arithmetic expression evaluation. */
+gmx::SelectionTreeElementPointer
+_gmx_sel_init_arithmetic(const gmx::SelectionTreeElementPointer &left,
+ const gmx::SelectionTreeElementPointer &right,
char op, void *scanner);
-/** Creates a \c t_selelem for comparsion expression evaluation. */
-struct t_selelem *
-_gmx_sel_init_comparison(struct t_selelem *left, struct t_selelem *right,
+/** Creates a gmx::SelectionTreeElement for comparsion expression evaluation. */
+gmx::SelectionTreeElementPointer
+_gmx_sel_init_comparison(const gmx::SelectionTreeElementPointer &left,
+ const gmx::SelectionTreeElementPointer &right,
char *cmpop, void *scanner);
-/** Creates a \c t_selelem for a keyword expression from the parsed data. */
-struct t_selelem *
+/** Creates a gmx::SelectionTreeElement for a keyword expression from the parsed data. */
+gmx::SelectionTreeElementPointer
_gmx_sel_init_keyword(struct gmx_ana_selmethod_t *method,
t_selexpr_value *args, const char *rpost, void *scanner);
-/** Creates a \c t_selelem for a method expression from the parsed data. */
-struct t_selelem *
+/** Creates a gmx::SelectionTreeElement for a method expression from the parsed data. */
+gmx::SelectionTreeElementPointer
_gmx_sel_init_method(struct gmx_ana_selmethod_t *method,
t_selexpr_param *params, const char *rpost,
void *scanner);
-/** Creates a \c t_selelem for a modifier expression from the parsed data. */
-struct t_selelem *
+/** Creates a gmx::SelectionTreeElement for a modifier expression from the parsed data. */
+gmx::SelectionTreeElementPointer
_gmx_sel_init_modifier(struct gmx_ana_selmethod_t *mod, t_selexpr_param *params,
- struct t_selelem *sel, void *scanner);
-/** Creates a \c t_selelem for evaluation of reference positions. */
-struct t_selelem *
-_gmx_sel_init_position(struct t_selelem *expr, const char *type, void *scanner);
-
-/** Creates a \c t_selelem for a constant position. */
-struct t_selelem *
+ const gmx::SelectionTreeElementPointer &sel,
+ void *scanner);
+/** Creates a gmx::SelectionTreeElement for evaluation of reference positions. */
+gmx::SelectionTreeElementPointer
+_gmx_sel_init_position(const gmx::SelectionTreeElementPointer &expr,
+ const char *type, void *scanner);
+
+/** Creates a gmx::SelectionTreeElement for a constant position. */
+gmx::SelectionTreeElementPointer
_gmx_sel_init_const_position(real x, real y, real z);
-/** Creates a \c t_selelem for a index group expression using group name. */
-struct t_selelem *
+/** Creates a gmx::SelectionTreeElement for a index group expression using group name. */
+gmx::SelectionTreeElementPointer
_gmx_sel_init_group_by_name(const char *name, void *scanner);
-/** Creates a \c t_selelem for a index group expression using group index. */
-struct t_selelem *
+/** Creates a gmx::SelectionTreeElement for a index group expression using group index. */
+gmx::SelectionTreeElementPointer
_gmx_sel_init_group_by_id(int id, void *scanner);
-/** Creates a \c t_selelem for a variable reference */
-struct t_selelem *
-_gmx_sel_init_variable_ref(struct t_selelem *sel);
-
-/** Creates a root \c t_selelem for a selection. */
-struct t_selelem *
-_gmx_sel_init_selection(char *name, struct t_selelem *sel, void *scanner);
-/** Creates a root \c t_selelem elements for a variable assignment. */
-struct t_selelem *
-_gmx_sel_assign_variable(char *name, struct t_selelem *expr, void *scanner);
-/** Appends a root \c t_selelem to a selection collection. */
-struct t_selelem *
-_gmx_sel_append_selection(struct t_selelem *sel, struct t_selelem *last,
+/** Creates a gmx::SelectionTreeElement for a variable reference */
+gmx::SelectionTreeElementPointer
+_gmx_sel_init_variable_ref(const gmx::SelectionTreeElementPointer &sel);
+
+/** Creates a root gmx::SelectionTreeElement for a selection. */
+gmx::SelectionTreeElementPointer
+_gmx_sel_init_selection(const char *name,
+ const gmx::SelectionTreeElementPointer &sel,
+ void *scanner);
+/** Creates a root gmx::SelectionTreeElement elements for a variable assignment. */
+gmx::SelectionTreeElementPointer
+_gmx_sel_assign_variable(const char *name,
+ const gmx::SelectionTreeElementPointer &expr,
+ void *scanner);
+/** Appends a root gmx::SelectionTreeElement to a selection collection. */
+gmx::SelectionTreeElementPointer
+_gmx_sel_append_selection(const gmx::SelectionTreeElementPointer &sel,
+ gmx::SelectionTreeElementPointer last,
void *scanner);
/** Check whether the parser should finish. */
bool
/** Initializes an array of parameters based on input from the selection parser. */
bool
_gmx_sel_parse_params(t_selexpr_param *pparams, int nparam,
- struct gmx_ana_selparam_t *param, struct t_selelem *root,
+ struct gmx_ana_selparam_t *param,
+ const gmx::SelectionTreeElementPointer &root,
void *scanner);
#endif
/* For variable symbols, return the type of the variable value */
if (symtype == SYMBOL_VARIABLE)
{
- t_selelem *var;
-
- var = _gmx_sel_sym_value_var(symbol);
+ gmx::SelectionTreeElementPointer var = _gmx_sel_sym_value_var(symbol);
/* Return simple tokens for constant variables */
if (var->type == SEL_CONST)
{
return INVALID;
}
}
- yylval->sel = var;
+ yylval->sel = new gmx::SelectionTreeElementPointer(var);
switch (var->v.type)
{
case INT_VALUE: return VARIABLE_NUMERIC;
case POS_VALUE: return VARIABLE_POS;
case GROUP_VALUE: return VARIABLE_GROUP;
default:
+ delete yylval->sel;
GMX_ERROR_NORET(gmx::eeInternalError,
"Unsupported variable type");
return INVALID;
}
+ delete yylval->sel;
return INVALID; /* Should not be reached. */
}
/* For method symbols, return the correct type */
namespace internal
{
-SelectionData::SelectionData(t_selelem *elem, const char *selstr)
+SelectionData::SelectionData(SelectionTreeElement *elem,
+ const char *selstr)
: name_(elem->name), selectionText_(selstr),
- rootElement_(elem), coveredFractionType_(CFRAC_NONE),
+ rootElement_(*elem), coveredFractionType_(CFRAC_NONE),
coveredFraction_(1.0), averageCoveredFraction_(1.0),
bDynamic_(false), bDynamicCoveredFraction_(false)
{
}
else
{
- t_selelem *child;
-
- child = elem->child;
+ SelectionTreeElementPointer child = elem->child;
child->flags &= ~SEL_ALLOCVAL;
_gmx_selvalue_setstore(&child->v, &rawPositions_);
/* We should also skip any modifiers to determine the dynamic
SelectionData::initCoveredFraction(e_coverfrac_t type)
{
coveredFractionType_ = type;
- if (type == CFRAC_NONE || rootElement_ == NULL)
+ if (type == CFRAC_NONE)
{
bDynamicCoveredFraction_ = false;
}
- else if (!_gmx_selelem_can_estimate_cover(rootElement_))
+ else if (!_gmx_selelem_can_estimate_cover(rootElement()))
{
coveredFractionType_ = CFRAC_NONE;
bDynamicCoveredFraction_ = false;
if (isDynamic())
{
gmx_ana_pos_t &p = rawPositions_;
- gmx_ana_index_copy(p.g, rootElement_->v.u.g, false);
+ gmx_ana_index_copy(p.g, rootElement().v.u.g, false);
p.g->name = NULL;
gmx_ana_indexmap_update(&p.m, p.g, hasFlag(gmx::efSelection_DynamicMask));
p.nr = p.m.nr;
#include "indexutil.h"
#include "selectionenums.h"
-struct t_selelem;
-
namespace gmx
{
class SelectionOptionStorage;
+class SelectionTreeElement;
class Selection;
class SelectionPosition;
* \param[in] selstr String that was parsed to produce this selection.
* \throws std::bad_alloc if out of memory.
*/
- SelectionData(t_selelem *elem, const char *selstr);
+ SelectionData(SelectionTreeElement *elem, const char *selstr);
~SelectionData();
//! Returns the string that was parsed to produce this selection.
//! Number of positions in the selection.
int posCount() const { return rawPositions_.nr; }
//! Returns the root of the evaluation tree for this selection.
- t_selelem *rootElement() { return rootElement_; }
+ SelectionTreeElement &rootElement() { return rootElement_; }
//! Returns whether the covered fraction can change between frames.
bool isCoveredFractionDynamic() const { return bDynamicCoveredFraction_; }
//! Information for all possible positions.
std::vector<PositionInfo> originalPosInfo_;
SelectionFlags flags_;
- //! Pointer to the root of the selection evaluation tree.
- t_selelem *rootElement_;
+ //! Root of the selection evaluation tree.
+ SelectionTreeElement &rootElement_;
//! Type of the covered fraction.
e_coverfrac_t coveredFractionType_;
//! Covered fraction of the selection for the current frame.
#include "poscalc.h"
#include "selection.h" // For gmx::SelectionList
#include "selectioncollection.h"
+#include "selelem.h"
namespace gmx
{
*/
struct gmx_ana_selcollection_t
{
- /** Root of the selection element tree. */
- struct t_selelem *root;
+ //! Position calculation collection used for selection position evaluation.
+ gmx::PositionCalculationCollection pcc;
+ //! Root of the selection element tree.
+ gmx::SelectionTreeElementPointer root;
/*! \brief
* Array of compiled selections.
*
t_topology *top;
/** Index group that contains all the atoms. */
struct gmx_ana_index_t gall;
- /** Position calculation collection used for selection position evaluation. */
- gmx::PositionCalculationCollection pcc;
/** Memory pool used for selection evaluation. */
struct gmx_sel_mempool_t *mempool;
/** Parser symbol table. */
* Does not throw currently, but this is subject to change when more
* underlying code is converted to C++.
*/
- void resolveExternalGroups(struct t_selelem *root,
+ void resolveExternalGroups(const gmx::SelectionTreeElementPointer &root,
MessageStringCollector *errors);
//! Internal data, used for interfacing with old C code.
SelectionCollection::Impl::Impl()
: debugLevel_(0), bExternalGroupsSet_(false), grps_(NULL)
{
- sc_.root = NULL;
sc_.nvars = 0;
sc_.varstrs = NULL;
sc_.top = NULL;
SelectionCollection::Impl::~Impl()
{
- _gmx_selelem_free_chain(sc_.root);
sc_.sel.clear();
+ sc_.root.reset();
for (int i = 0; i < sc_.nvars; ++i)
{
sfree(sc_.varstrs[i]);
void SelectionCollection::Impl::resolveExternalGroups(
- t_selelem *root, MessageStringCollector *errors)
+ const SelectionTreeElementPointer &root,
+ MessageStringCollector *errors)
{
if (root->type == SEL_GROUPREF)
}
}
- t_selelem *child = root->child;
- while (child != NULL)
+ SelectionTreeElementPointer child = root->child;
+ while (child)
{
resolveExternalGroups(child, errors);
child = child->next;
impl_->bExternalGroupsSet_ = true;
MessageStringCollector errors;
- t_selelem *root = impl_->sc_.root;
- while (root != NULL)
+ SelectionTreeElementPointer root = impl_->sc_.root;
+ while (root)
{
impl_->resolveExternalGroups(root, &errors);
root = root->next;
bool
SelectionCollection::requiresTopology() const
{
- t_selelem *sel;
e_poscalc_t type;
int flags;
}
}
- sel = impl_->sc_.root;
+ SelectionTreeElementPointer sel = impl_->sc_.root;
while (sel)
{
- if (_gmx_selelem_requires_top(sel))
+ if (_gmx_selelem_requires_top(*sel))
{
return true;
}
void
SelectionCollection::printTree(FILE *fp, bool bValues) const
{
- t_selelem *sel;
-
- sel = impl_->sc_.root;
+ SelectionTreeElementPointer sel = impl_->sc_.root;
while (sel)
{
- _gmx_selelem_print_tree(fp, sel, bValues, 0);
+ _gmx_selelem_print_tree(fp, *sel, bValues, 0);
sel = sel->next;
}
}
* \author Teemu Murtola <teemu.murtola@cbr.su.se>
* \ingroup module_selection
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include <cstring>
-#include "gmx_fatal.h"
-#include "smalloc.h"
+#include "gromacs/legacyheaders/smalloc.h"
#include "gromacs/selection/indexutil.h"
#include "gromacs/selection/poscalc.h"
#include "gromacs/selection/position.h"
#include "gromacs/selection/selmethod.h"
#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/gmxassert.h"
#include "keywords.h"
#include "mempool.h"
* The function returns NULL if \p sel->type is not one of the valid values.
*/
const char *
-_gmx_selelem_type_str(t_selelem *sel)
+_gmx_selelem_type_str(const gmx::SelectionTreeElement &sel)
{
- switch (sel->type)
+ switch (sel.type)
{
case SEL_CONST: return "CONST";
case SEL_EXPRESSION: return "EXPR";
* The return value points to a string constant and should not be \p free'd.
*/
const char *
-_gmx_sel_value_type_str(gmx_ana_selvalue_t *val)
+_gmx_sel_value_type_str(const gmx_ana_selvalue_t *val)
{
switch (val->type)
{
/*! \copydoc _gmx_selelem_type_str() */
const char *
-_gmx_selelem_boolean_type_str(t_selelem *sel)
+_gmx_selelem_boolean_type_str(const gmx::SelectionTreeElement &sel)
{
- switch (sel->u.boolt)
+ switch (sel.u.boolt)
{
case BOOL_NOT: return "NOT"; break;
case BOOL_AND: return "AND"; break;
return NULL;
}
-/*!
- * \param[in] type Type of selection element to allocate.
- * \returns Pointer to the newly allocated and initialized element.
- *
- * \c t_selelem::type is set to \p type,
- * \c t_selelem::v::type is set to \ref GROUP_VALUE for boolean and comparison
- * expressions and \ref NO_VALUE for others,
- * \ref SEL_ALLOCVAL is set for non-root elements (\ref SEL_ALLOCDATA is also
- * set for \ref SEL_BOOLEAN elements),
- * and \c t_selelem::refcount is set to one.
- * All the pointers are set to NULL.
- */
-t_selelem *
-_gmx_selelem_create(e_selelem_t type)
+
+namespace gmx
{
- t_selelem *sel;
- snew(sel, 1);
- sel->name = NULL;
- sel->type = type;
- sel->flags = (type != SEL_ROOT) ? SEL_ALLOCVAL : 0;
+SelectionTreeElement::SelectionTreeElement(e_selelem_t type)
+{
+ this->name = NULL;
+ this->type = type;
+ this->flags = (type != SEL_ROOT) ? SEL_ALLOCVAL : 0;
if (type == SEL_BOOLEAN)
{
- sel->v.type = GROUP_VALUE;
- sel->flags |= SEL_ALLOCDATA;
+ this->v.type = GROUP_VALUE;
+ this->flags |= SEL_ALLOCDATA;
}
else
{
- sel->v.type = NO_VALUE;
+ this->v.type = NO_VALUE;
}
- _gmx_selvalue_clear(&sel->v);
- sel->evaluate = NULL;
- sel->mempool = NULL;
- sel->child = NULL;
- sel->next = NULL;
- sel->refcount = 1;
+ _gmx_selvalue_clear(&this->v);
+ std::memset(&this->u, 0, sizeof(this->u));
+ this->evaluate = NULL;
+ this->mempool = NULL;
+ this->cdata = NULL;
+}
- return sel;
+SelectionTreeElement::~SelectionTreeElement()
+{
+ /* Free the children.
+ * Must be done before freeing other data, because the children may hold
+ * references to data in this element. */
+ child.reset();
+
+ freeValues();
+ freeExpressionData();
+ freeCompilerData();
}
-/*!
- * \param[in,out] sel Selection element to set the type for.
- * \param[in] vtype Value type for the selection element.
- * \returns 0 on success, EINVAL if the value type is invalid.
- *
- * If the new type is \ref GROUP_VALUE or \ref POS_VALUE, the
- * \ref SEL_ALLOCDATA flag is also set.
- *
- * This function should only be called at most once for each element,
- * preferably right after calling _gmx_selelem_create().
- */
-int
-_gmx_selelem_set_vtype(t_selelem *sel, e_selvalue_t vtype)
+void SelectionTreeElement::freeValues()
{
- if (sel->type == SEL_BOOLEAN && vtype != GROUP_VALUE)
+ mempoolRelease();
+ if ((flags & SEL_ALLOCDATA) && v.u.ptr)
{
- gmx_bug("internal error");
- return EINVAL;
+ /* The number of position/group structures is constant, so the
+ * backup of using sel->v.nr should work for them.
+ * For strings, we report an error if we don't know the allocation
+ * size here. */
+ int n = (v.nalloc > 0) ? v.nalloc : v.nr;
+ switch (v.type)
+ {
+ case STR_VALUE:
+ GMX_RELEASE_ASSERT(v.nalloc != 0,
+ "SEL_ALLOCDATA should only be set for allocated "
+ "STR_VALUE values");
+ for (int i = 0; i < n; ++i)
+ {
+ sfree(v.u.s[i]);
+ }
+ break;
+ case POS_VALUE:
+ for (int i = 0; i < n; ++i)
+ {
+ gmx_ana_pos_deinit(&v.u.p[i]);
+ }
+ break;
+ case GROUP_VALUE:
+ for (int i = 0; i < n; ++i)
+ {
+ gmx_ana_index_deinit(&v.u.g[i]);
+ }
+ break;
+ default: /* No special handling for other types */
+ break;
+ }
}
- if (sel->v.type != NO_VALUE && vtype != sel->v.type)
+ if (flags & SEL_ALLOCVAL)
{
- gmx_call("_gmx_selelem_set_vtype() called more than once");
- return EINVAL;
+ sfree(v.u.ptr);
}
- sel->v.type = vtype;
- if (vtype == GROUP_VALUE || vtype == POS_VALUE)
+ _gmx_selvalue_setstore(&v, NULL);
+ if (type == SEL_SUBEXPRREF && u.param)
{
- sel->flags |= SEL_ALLOCDATA;
+ u.param->val.u.ptr = NULL;
}
- return 0;
}
-/*!
- * \param[in,out] sel Selection element to reserve.
- * \param[in] count Number of values to reserve memory for.
- * \returns 0 on success or if no memory pool, non-zero on error.
- *
- * Reserves memory for the values of \p sel from the \p sel->mempool
- * memory pool. If no memory pool is set, nothing is done.
- */
void
-_gmx_selelem_mempool_reserve(t_selelem *sel, int count)
+SelectionTreeElement::freeExpressionData()
+{
+ if (type == SEL_EXPRESSION || type == SEL_MODIFIER)
+ {
+ _gmx_selelem_free_method(u.expr.method, u.expr.mdata);
+ u.expr.mdata = NULL;
+ u.expr.method = NULL;
+ /* Free position data */
+ if (u.expr.pos)
+ {
+ gmx_ana_pos_free(u.expr.pos);
+ u.expr.pos = NULL;
+ }
+ /* Free position calculation data */
+ if (u.expr.pc)
+ {
+ gmx_ana_poscalc_free(u.expr.pc);
+ u.expr.pc = NULL;
+ }
+ }
+ if (type == SEL_ARITHMETIC)
+ {
+ sfree(u.arith.opstr);
+ u.arith.opstr = NULL;
+ }
+ if (type == SEL_SUBEXPR || type == SEL_ROOT
+ || (type == SEL_CONST && v.type == GROUP_VALUE))
+ {
+ gmx_ana_index_deinit(&u.cgrp);
+ }
+ if (type == SEL_GROUPREF)
+ {
+ sfree(u.gref.name);
+ }
+}
+
+void SelectionTreeElement::mempoolReserve(int count)
{
- if (!sel->mempool)
+ if (!mempool)
{
return;
}
- switch (sel->v.type)
+ switch (v.type)
{
case INT_VALUE:
- sel->v.u.i = static_cast<int *>(
- _gmx_sel_mempool_alloc(sel->mempool, sizeof(*sel->v.u.i)*count));
+ v.u.i = static_cast<int *>(
+ _gmx_sel_mempool_alloc(mempool, sizeof(*v.u.i)*count));
break;
case REAL_VALUE:
- sel->v.u.r = static_cast<real *>(
- _gmx_sel_mempool_alloc(sel->mempool, sizeof(*sel->v.u.r)*count));
+ v.u.r = static_cast<real *>(
+ _gmx_sel_mempool_alloc(mempool, sizeof(*v.u.r)*count));
break;
case GROUP_VALUE:
- _gmx_sel_mempool_alloc_group(sel->mempool, sel->v.u.g, count);
+ _gmx_sel_mempool_alloc_group(mempool, v.u.g, count);
break;
default:
}
}
-/*!
- * \param[in,out] sel Selection element to release.
- *
- * Releases the memory allocated for the values of \p sel from the
- * \p sel->mempool memory pool. If no memory pool is set, nothing is done.
- */
-void
-_gmx_selelem_mempool_release(t_selelem *sel)
+void SelectionTreeElement::mempoolRelease()
{
- if (!sel->mempool)
+ if (!mempool)
{
return;
}
- switch (sel->v.type)
+ switch (v.type)
{
case INT_VALUE:
case REAL_VALUE:
- _gmx_sel_mempool_free(sel->mempool, sel->v.u.ptr);
- _gmx_selvalue_setstore(&sel->v, NULL);
+ _gmx_sel_mempool_free(mempool, v.u.ptr);
+ _gmx_selvalue_setstore(&v, NULL);
break;
case GROUP_VALUE:
- if (sel->v.u.g)
+ if (v.u.g)
{
- _gmx_sel_mempool_free_group(sel->mempool, sel->v.u.g);
+ _gmx_sel_mempool_free_group(mempool, v.u.g);
}
break;
}
}
+} // namespace gmx
+
/*!
- * \param[in] sel Selection to free.
+ * \param[in,out] sel Selection element to set the type for.
+ * \param[in] vtype Value type for the selection element.
+ *
+ * If the new type is \ref GROUP_VALUE or \ref POS_VALUE, the
+ * \ref SEL_ALLOCDATA flag is also set.
+ *
+ * This function should only be called at most once for each element,
+ * preferably right after calling _gmx_selelem_create().
*/
void
-_gmx_selelem_free_values(t_selelem *sel)
+_gmx_selelem_set_vtype(const gmx::SelectionTreeElementPointer &sel,
+ e_selvalue_t vtype)
{
- int i, n;
-
- _gmx_selelem_mempool_release(sel);
- if ((sel->flags & SEL_ALLOCDATA) && sel->v.u.ptr)
- {
- /* The number of position/group structures is constant, so the
- * backup of using sel->v.nr should work for them.
- * For strings, we report an error if we don't know the allocation
- * size here. */
- n = (sel->v.nalloc > 0) ? sel->v.nalloc : sel->v.nr;
- switch (sel->v.type)
- {
- case STR_VALUE:
- if (sel->v.nalloc == 0)
- {
- gmx_bug("SEL_ALLOCDATA should only be set for allocated STR_VALUE values");
- break;
- }
- for (i = 0; i < n; ++i)
- {
- sfree(sel->v.u.s[i]);
- }
- break;
- case POS_VALUE:
- for (i = 0; i < n; ++i)
- {
- gmx_ana_pos_deinit(&sel->v.u.p[i]);
- }
- break;
- case GROUP_VALUE:
- for (i = 0; i < n; ++i)
- {
- gmx_ana_index_deinit(&sel->v.u.g[i]);
- }
- break;
- default: /* No special handling for other types */
- break;
- }
- }
- if (sel->flags & SEL_ALLOCVAL)
- {
- sfree(sel->v.u.ptr);
- }
- _gmx_selvalue_setstore(&sel->v, NULL);
- if (sel->type == SEL_SUBEXPRREF && sel->u.param)
+ GMX_RELEASE_ASSERT(sel->type != SEL_BOOLEAN || vtype == GROUP_VALUE,
+ "Boolean elements must have a group value");
+ GMX_RELEASE_ASSERT(sel->v.type == NO_VALUE || vtype == sel->v.type,
+ "_gmx_selelem_set_vtype() called more than once");
+ sel->v.type = vtype;
+ if (vtype == GROUP_VALUE || vtype == POS_VALUE)
{
- sel->u.param->val.u.ptr = NULL;
+ sel->flags |= SEL_ALLOCDATA;
}
}
}
}
-/*!
- * \param[in] sel Selection to free.
- */
-void
-_gmx_selelem_free_exprdata(t_selelem *sel)
-{
- if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
- {
- _gmx_selelem_free_method(sel->u.expr.method, sel->u.expr.mdata);
- sel->u.expr.mdata = NULL;
- sel->u.expr.method = NULL;
- /* Free position data */
- if (sel->u.expr.pos)
- {
- gmx_ana_pos_free(sel->u.expr.pos);
- sel->u.expr.pos = NULL;
- }
- /* Free position calculation data */
- if (sel->u.expr.pc)
- {
- gmx_ana_poscalc_free(sel->u.expr.pc);
- sel->u.expr.pc = NULL;
- }
- }
- if (sel->type == SEL_ARITHMETIC)
- {
- sfree(sel->u.arith.opstr);
- sel->u.arith.opstr = NULL;
- }
- if (sel->type == SEL_SUBEXPR || sel->type == SEL_ROOT
- || (sel->type == SEL_CONST && sel->v.type == GROUP_VALUE))
- {
- gmx_ana_index_deinit(&sel->u.cgrp);
- }
- if (sel->type == SEL_GROUPREF)
- {
- sfree(sel->u.gref.name);
- }
-}
-
-/*!
- * \param[in] sel Selection to free.
- *
- * Decrements \ref t_selelem::refcount "sel->refcount" and frees the
- * memory allocated for \p sel and all its children if the reference count
- * reaches zero.
- */
-void
-_gmx_selelem_free(t_selelem *sel)
-{
- /* Decrement the reference counter and do nothing if references remain */
- sel->refcount--;
- if (sel->refcount > 0)
- {
- return;
- }
-
- /* Free the children.
- * Must be done before freeing other data, because the children may hold
- * references to data in this element. */
- _gmx_selelem_free_chain(sel->child);
-
- /* Free value storage */
- _gmx_selelem_free_values(sel);
-
- /* Free other storage */
- _gmx_selelem_free_exprdata(sel);
-
- /* Free temporary compiler data if present */
- _gmx_selelem_free_compiler_data(sel);
-
- sfree(sel);
-}
-
-/*!
- * \param[in] first First selection to free.
- *
- * Frees \p first and all selections accessible through the
- * \ref t_selelem::next "first->next" pointer.
- */
-void
-_gmx_selelem_free_chain(t_selelem *first)
-{
- t_selelem *child, *prev;
-
- child = first;
- while (child)
- {
- prev = child;
- child = child->next;
- _gmx_selelem_free(prev);
- }
-}
-
/*!
* \param[in] fp File handle to receive the output.
* \param[in] sel Root of the selection subtree to print.
* \param[in] level Indentation level, starting from zero.
*/
void
-_gmx_selelem_print_tree(FILE *fp, t_selelem *sel, bool bValues, int level)
+_gmx_selelem_print_tree(FILE *fp, const gmx::SelectionTreeElement &sel,
+ bool bValues, int level)
{
- t_selelem *child;
int i;
fprintf(fp, "%*c %s %s", level*2+1, '*',
- _gmx_selelem_type_str(sel), _gmx_sel_value_type_str(&sel->v));
- if (sel->name)
+ _gmx_selelem_type_str(sel), _gmx_sel_value_type_str(&sel.v));
+ if (sel.name)
{
- fprintf(fp, " \"%s\"", sel->name);
+ fprintf(fp, " \"%s\"", sel.name);
}
fprintf(fp, " flg=");
- if (sel->flags & SEL_FLAGSSET)
+ if (sel.flags & SEL_FLAGSSET)
{
fprintf(fp, "s");
}
- if (sel->flags & SEL_SINGLEVAL)
+ if (sel.flags & SEL_SINGLEVAL)
{
fprintf(fp, "S");
}
- if (sel->flags & SEL_ATOMVAL)
+ if (sel.flags & SEL_ATOMVAL)
{
fprintf(fp, "A");
}
- if (sel->flags & SEL_VARNUMVAL)
+ if (sel.flags & SEL_VARNUMVAL)
{
fprintf(fp, "V");
}
- if (sel->flags & SEL_DYNAMIC)
+ if (sel.flags & SEL_DYNAMIC)
{
fprintf(fp, "D");
}
- if (!(sel->flags & SEL_VALFLAGMASK))
+ if (!(sel.flags & SEL_VALFLAGMASK))
{
fprintf(fp, "0");
}
- if (sel->mempool)
+ if (sel.mempool)
{
fprintf(fp, "P");
}
- if (sel->type == SEL_CONST)
+ if (sel.type == SEL_CONST)
{
- if (sel->v.type == INT_VALUE)
+ if (sel.v.type == INT_VALUE)
{
- fprintf(fp, " %d", sel->v.u.i[0]);
+ fprintf(fp, " %d", sel.v.u.i[0]);
}
- else if (sel->v.type == REAL_VALUE)
+ else if (sel.v.type == REAL_VALUE)
{
- fprintf(fp, " %f", sel->v.u.r[0]);
+ fprintf(fp, " %f", sel.v.u.r[0]);
}
- else if (sel->v.type == GROUP_VALUE)
+ else if (sel.v.type == GROUP_VALUE)
{
- gmx_ana_index_t *g = sel->v.u.g;
+ const gmx_ana_index_t *g = sel.v.u.g;
if (!g || g->isize == 0)
- g = &sel->u.cgrp;
+ g = &sel.u.cgrp;
fprintf(fp, " (%d atoms)", g->isize);
}
}
- else if (sel->type == SEL_BOOLEAN)
+ else if (sel.type == SEL_BOOLEAN)
{
fprintf(fp, " %s", _gmx_selelem_boolean_type_str(sel));
}
- else if (sel->type == SEL_EXPRESSION
- && sel->u.expr.method->name == sm_compare.name)
+ else if (sel.type == SEL_EXPRESSION
+ && sel.u.expr.method->name == sm_compare.name)
{
- _gmx_selelem_print_compare_info(fp, sel->u.expr.mdata);
+ _gmx_selelem_print_compare_info(fp, sel.u.expr.mdata);
}
- if (sel->evaluate)
+ if (sel.evaluate)
{
fprintf(fp, " eval=");
- _gmx_sel_print_evalfunc_name(fp, sel->evaluate);
+ _gmx_sel_print_evalfunc_name(fp, sel.evaluate);
}
- if (sel->refcount > 1)
- {
- fprintf(fp, " refc=%d", sel->refcount);
- }
- if (!(sel->flags & SEL_ALLOCVAL))
+ if (!(sel.flags & SEL_ALLOCVAL))
{
fprintf(fp, " (ext. output)");
}
fprintf(fp, "\n");
- if ((sel->type == SEL_CONST && sel->v.type == GROUP_VALUE) || sel->type == SEL_ROOT)
+ if ((sel.type == SEL_CONST && sel.v.type == GROUP_VALUE) || sel.type == SEL_ROOT)
{
- gmx_ana_index_t *g = sel->v.u.g;
- if (!g || g->isize == 0 || sel->evaluate != NULL)
+ const gmx_ana_index_t *g = sel.v.u.g;
+ if (!g || g->isize == 0 || sel.evaluate != NULL)
{
- g = &sel->u.cgrp;
+ g = &sel.u.cgrp;
}
if (g->isize < 0)
{
fprintf(fp, "\n");
}
}
- else if (sel->type == SEL_EXPRESSION)
+ else if (sel.type == SEL_EXPRESSION)
{
- if (sel->u.expr.pc)
+ if (sel.u.expr.pc)
{
fprintf(fp, "%*c COM", level*2+3, '*');
fprintf(fp, "\n");
}
}
- if (sel->cdata)
+ if (sel.cdata)
{
_gmx_selelem_print_compiler_info(fp, sel, level);
}
- if (bValues && sel->type != SEL_CONST && sel->type != SEL_ROOT && sel->v.u.ptr)
+ if (bValues && sel.type != SEL_CONST && sel.type != SEL_ROOT && sel.v.u.ptr)
{
fprintf(fp, "%*c value: ", level*2+1, ' ');
- switch (sel->v.type)
+ switch (sel.v.type)
{
case POS_VALUE:
/* In normal use, the pointer should never be NULL, but it's
* useful to have the check for debugging to avoid accidental
* segfaults when printing the selection tree. */
- if (sel->v.u.p->x)
+ if (sel.v.u.p->x)
{
fprintf(fp, "(%f, %f, %f)",
- sel->v.u.p->x[0][XX], sel->v.u.p->x[0][YY],
- sel->v.u.p->x[0][ZZ]);
+ sel.v.u.p->x[0][XX], sel.v.u.p->x[0][YY],
+ sel.v.u.p->x[0][ZZ]);
}
else
{
}
break;
case GROUP_VALUE:
- fprintf(fp, "%d atoms", sel->v.u.g->isize);
- if (sel->v.u.g->isize < 20)
+ fprintf(fp, "%d atoms", sel.v.u.g->isize);
+ if (sel.v.u.g->isize < 20)
{
- if (sel->v.u.g->isize > 0)
+ if (sel.v.u.g->isize > 0)
{
fprintf(fp, ":");
}
- for (i = 0; i < sel->v.u.g->isize; ++i)
+ for (i = 0; i < sel.v.u.g->isize; ++i)
{
- fprintf(fp, " %d", sel->v.u.g->index[i] + 1);
+ fprintf(fp, " %d", sel.v.u.g->index[i] + 1);
}
}
break;
}
/* Print the subexpressions with one more level of indentation */
- child = sel->child;
+ gmx::SelectionTreeElementPointer child = sel.child;
while (child)
{
- if (!(sel->type == SEL_SUBEXPRREF && child->type == SEL_SUBEXPR))
+ if (!(sel.type == SEL_SUBEXPRREF && child->type == SEL_SUBEXPR))
{
- _gmx_selelem_print_tree(fp, child, bValues, level+1);
+ _gmx_selelem_print_tree(fp, *child, bValues, level+1);
}
child = child->next;
}
* information, false otherwise.
*/
bool
-_gmx_selelem_requires_top(t_selelem *root)
+_gmx_selelem_requires_top(const gmx::SelectionTreeElement &root)
{
- t_selelem *child;
-
- if (root->type == SEL_EXPRESSION || root->type == SEL_MODIFIER)
+ if (root.type == SEL_EXPRESSION || root.type == SEL_MODIFIER)
{
- if (root->u.expr.method && (root->u.expr.method->flags & SMETH_REQTOP))
+ if (root.u.expr.method && (root.u.expr.method->flags & SMETH_REQTOP))
{
return true;
}
- if (root->u.expr.pc && gmx_ana_poscalc_requires_top(root->u.expr.pc))
+ if (root.u.expr.pc && gmx_ana_poscalc_requires_top(root.u.expr.pc))
{
return true;
}
}
- child = root->child;
+ gmx::SelectionTreeElementPointer child = root.child;
while (child)
{
- if (_gmx_selelem_requires_top(child))
+ if (_gmx_selelem_requires_top(*child))
{
return true;
}
*/
/*! \internal \file
* \brief
- * Declares ::t_selelem and related things.
+ * Declares gmx::SelectionTreeElement and related things.
*
* The selection element trees constructed by the parser and the compiler
* are described on the respective pages:
* \author Teemu Murtola <teemu.murtola@cbr.su.se>
* \ingroup module_selection
*/
-#ifndef SELECTION_ELEMENT_H
-#define SELECTION_ELEMENT_H
+#ifndef GMX_SELECTION_SELELEM_H
+#define GMX_SELECTION_SELELEM_H
-#include <types/simple.h>
+#include <boost/shared_ptr.hpp>
-#include "gromacs/selection/indexutil.h"
-#include "gromacs/selection/selvalue.h"
+#include "gromacs/legacyheaders/types/simple.h"
+#include "gromacs/utility/common.h"
+
+#include "indexutil.h"
+#include "selvalue.h"
struct gmx_ana_poscalc_t;
struct gmx_ana_selparam_t;
struct gmx_sel_evaluate_t;
struct gmx_sel_mempool_t;
-struct t_selelem;
+
+struct t_compiler_data;
+
+namespace gmx
+{
+class SelectionTreeElement;
+
+//! Smart pointer type for selection tree element pointers.
+typedef boost::shared_ptr<SelectionTreeElement> SelectionTreeElementPointer;
+} // namespace gmx
/********************************************************************/
/*! \name Enumerations for expression types
********************************************************************/
-/*@{*/
+//!\{
-/** Defines the type of a \c t_selelem object. */
+/** Defines the type of a gmx::SelectionTreeElement object. */
typedef enum
{
/** Constant-valued expression. */
SEL_MODIFIER
} e_selelem_t;
-/** Defines the boolean operation of \c t_selelem objects with type \ref SEL_BOOLEAN. */
+/** Defines the boolean operation of gmx::SelectionTreeElement objects with type \ref SEL_BOOLEAN. */
typedef enum
{
BOOL_NOT, /**< Not */
BOOL_XOR /**< Xor (not implemented). */
} e_boolean_t;
-/** Defines the arithmetic operation of \c t_selelem objects with type \ref SEL_ARITHMETIC. */
+/** Defines the arithmetic operation of gmx::SelectionTreeElement objects with type \ref SEL_ARITHMETIC. */
typedef enum
{
ARITH_PLUS, /**< + */
ARITH_EXP /**< ^ (to power) */
} e_arithmetic_t;
-/** Returns a string representation of the type of a \c t_selelem. */
+/** Returns a string representation of the type of a gmx::SelectionTreeElement. */
extern const char *
-_gmx_selelem_type_str(struct t_selelem *sel);
-/** Returns a string representation of the boolean type of a \ref SEL_BOOLEAN \c t_selelem. */
+_gmx_selelem_type_str(const gmx::SelectionTreeElement &sel);
+/** Returns a string representation of the boolean type of a \ref SEL_BOOLEAN gmx::SelectionTreeElement. */
extern const char *
-_gmx_selelem_boolean_type_str(struct t_selelem *sel);
+_gmx_selelem_boolean_type_str(const gmx::SelectionTreeElement &sel);
/** Returns a string representation of the type of a \c gmx_ana_selvalue_t. */
extern const char *
-_gmx_sel_value_type_str(gmx_ana_selvalue_t *val);
+_gmx_sel_value_type_str(const gmx_ana_selvalue_t *val);
-/*@}*/
+//!\}
/********************************************************************/
/*! \name Selection expression flags
* \anchor selelem_flags
********************************************************************/
-/*@{*/
+//!\{
/*! \brief
* Selection value flags are set.
*
* This flag is also used for \ref SEL_SUBEXPRREF elements.
*/
#define SEL_OUTINIT (1<<13)
-/*@}*/
+//!\}
-/********************************************************************/
-/*! \name Selection expression data structures and functions
- ********************************************************************/
-/*@{*/
-
-struct t_selelem;
+namespace gmx
+{
/*! \brief
- * Function pointer for evaluating a \c t_selelem.
+ * Function pointer for evaluating a gmx::SelectionTreeElement.
*/
typedef void (*sel_evalfunc)(struct gmx_sel_evaluate_t *data,
- struct t_selelem *sel, gmx_ana_index_t *g);
+ const SelectionTreeElementPointer &sel,
+ gmx_ana_index_t *g);
/*! \internal \brief
* Represents an element of a selection expression.
*/
-typedef struct t_selelem
+class SelectionTreeElement
{
- /*! \brief Name of the element.
- *
- * This field is only used for informative purposes.
- * It is always either NULL or a pointer to a string.
- * Memory is never allocated for it directly.
- */
- const char *name;
- /** Type of the element. */
- e_selelem_t type;
- /*! \brief
- * Value storage of the element.
- *
- * This field contains the evaluated value of the element, as well as
- * the output value type.
- */
- gmx_ana_selvalue_t v;
- /*! \brief
- * Evaluation function for the element.
- *
- * Can be either NULL (if the expression is a constant and does not require
- * evaluation) or point to one of the functions defined in evaluate.h.
- */
- sel_evalfunc evaluate;
- /*! \brief
- * Information flags about the element.
- *
- * Allowed flags are listed here:
- * \ref selelem_flags "flags for \c t_selelem".
- */
- int flags;
- /** Data required by the evaluation function. */
- union {
- /*! \brief Index group data for several element types.
+ public:
+ /*! \brief
+ * Allocates memory and performs common initialization.
+ *
+ * \param[in] type Type of selection element to create.
+ *
+ * \a type is set to \p type,
+ * \a v::type is set to \ref GROUP_VALUE for boolean and comparison
+ * expressions and \ref NO_VALUE for others, and
+ * \ref SEL_ALLOCVAL is set for non-root elements (\ref SEL_ALLOCDATA
+ * is also set for \ref SEL_BOOLEAN elements).
+ * All the pointers are set to NULL.
+ */
+ explicit SelectionTreeElement(e_selelem_t type);
+ ~SelectionTreeElement();
+
+ //! Frees the memory allocated for the \a v union.
+ void freeValues();
+ //! Frees the memory allocated for the \a u union.
+ void freeExpressionData();
+ /* In compiler.cpp */
+ /*! \brief
+ * Frees the memory allocated for the selection compiler.
+ *
+ * This function only frees the data for the given selection, not its
+ * children. It is safe to call the function when compiler data has
+ * not been allocated or has already been freed; in such a case,
+ * nothing is done.
+ */
+ void freeCompilerData();
+
+ /*! \brief
+ * Reserves memory for value from a memory pool.
+ *
+ * \param[in] count Number of values to reserve memory for.
+ *
+ * Reserves memory for the values of this element from the \a mempool
+ * memory pool.
+ * If no memory pool is set, nothing is done.
+ */
+ void mempoolReserve(int count);
+ /*! \brief
+ * Releases memory pool used for value.
+ *
+ * Releases the memory allocated for the values of this element from the
+ * \a mempool memory pool.
+ * If no memory pool is set, nothing is done.
+ */
+ void mempoolRelease();
+
+ /*! \brief Name of the element.
+ *
+ * This field is only used for informative purposes.
+ * It is always either NULL or a pointer to a string.
+ * Memory is never allocated for it directly.
+ */
+ const char *name;
+ //! Type of the element.
+ e_selelem_t type;
+ /*! \brief
+ * Value storage of the element.
+ *
+ * This field contains the evaluated value of the element, as well as
+ * the output value type.
+ */
+ gmx_ana_selvalue_t v;
+ /*! \brief
+ * Evaluation function for the element.
+ *
+ * Can be either NULL (if the expression is a constant and does not
+ * require evaluation) or point to one of the functions defined in
+ * evaluate.h.
+ */
+ sel_evalfunc evaluate;
+ /*! \brief
+ * Information flags about the element.
+ *
+ * Allowed flags are listed here:
+ * \ref selelem_flags "flags for gmx::SelectionTreeElement".
+ */
+ int flags;
+ //! Data required by the evaluation function.
+ union {
+ /*! \brief Index group data for several element types.
+ *
+ * - \ref SEL_CONST : if the value type is \ref GROUP_VALUE,
+ * this field holds the unprocessed group value.
+ * - \ref SEL_ROOT : holds the group value for which the
+ * selection subtree should be evaluated.
+ * - \ref SEL_SUBEXPR : holds the group for which the subexpression
+ * has been evaluated.
+ */
+ gmx_ana_index_t cgrp;
+ //! Data for \ref SEL_EXPRESSION and \ref SEL_MODIFIER elements.
+ struct {
+ //! Pointer the the method used in this expression.
+ struct gmx_ana_selmethod_t *method;
+ //! Pointer to the data allocated by the method's \p init_data (see sel_datafunc()).
+ void *mdata;
+ //! Pointer to the position data passed to the method.
+ struct gmx_ana_pos_t *pos;
+ //! Pointer to the evaluation data for \p pos.
+ struct gmx_ana_poscalc_t *pc;
+ } expr;
+ //! Operation type for \ref SEL_BOOLEAN elements.
+ e_boolean_t boolt;
+ //! Operation type for \ref SEL_ARITHMETIC elements.
+ struct {
+ //! Operation type.
+ e_arithmetic_t type;
+ //! String representation.
+ char *opstr;
+ } arith;
+ //! Associated selection parameter for \ref SEL_SUBEXPRREF elements.
+ struct gmx_ana_selparam_t *param;
+ //! The string/number used to reference the group.
+ struct {
+ //! Name of the referenced external group.
+ char *name;
+ //! If \a name is NULL, the index number of the referenced group.
+ int id;
+ } gref;
+ } u;
+ //! Memory pool to use for values, or NULL if standard memory handling.
+ struct gmx_sel_mempool_t *mempool;
+ //! Internal data for the selection compiler.
+ t_compiler_data *cdata;
+
+ /*! \brief The first child element.
*
- * - \ref SEL_CONST : if the value type is \ref GROUP_VALUE,
- * this field holds the unprocessed group value.
- * - \ref SEL_ROOT : holds the group value for which the
- * selection subtree should be evaluated.
- * - \ref SEL_SUBEXPR : holds the group for which the subexpression
- * has been evaluated.
+ * Other children can be accessed through the \p next field of \p child.
*/
- gmx_ana_index_t cgrp;
- /** Data for \ref SEL_EXPRESSION and \ref SEL_MODIFIER elements. */
- struct {
- /** Pointer the the method used in this expression. */
- struct gmx_ana_selmethod_t *method;
- /** Pointer to the data allocated by the method's \p init_data (see sel_datafunc()). */
- void *mdata;
- /** Pointer to the position data passed to the method. */
- struct gmx_ana_pos_t *pos;
- /** Pointer to the evaluation data for \p pos. */
- struct gmx_ana_poscalc_t *pc;
- } expr;
- /** Operation type for \ref SEL_BOOLEAN elements. */
- e_boolean_t boolt;
- /** Operation type for \ref SEL_ARITHMETIC elements. */
- struct {
- /** Operation type. */
- e_arithmetic_t type;
- /** String representation. */
- char *opstr;
- } arith;
- /** Associated selection parameter for \ref SEL_SUBEXPRREF elements. */
- struct gmx_ana_selparam_t *param;
- /** The string/number used to reference the group. */
- struct {
- /** Name of the referenced external group. */
- char *name;
- /** If \a name is NULL, the index number of the referenced group. */
- int id;
- } gref;
- } u;
- /** Memory pool to use for values, or NULL if standard memory handling. */
- struct gmx_sel_mempool_t *mempool;
- /** Internal data for the selection compiler. */
- struct t_compiler_data *cdata;
-
- /*! \brief The first child element.
- *
- * Other children can be accessed through the \p next field of \p child.
- */
- struct t_selelem *child;
- /** The next sibling element. */
- struct t_selelem *next;
- /*! \brief Number of references to this element.
- *
- * Should be larger than one only for \ref SEL_SUBEXPR elements.
- */
- int refcount;
-} t_selelem;
+ SelectionTreeElementPointer child;
+ //! The next sibling element.
+ SelectionTreeElementPointer next;
+
+ private:
+ GMX_DISALLOW_COPY_AND_ASSIGN(SelectionTreeElement);
+};
+
+} // namespace gmx
+
+/********************************************************************/
+/*! \name Selection expression functions
+ */
+//!\{
/* In evaluate.c */
/** Writes out a human-readable name for an evaluation function. */
-extern void
-_gmx_sel_print_evalfunc_name(FILE *fp, sel_evalfunc evalfunc);
-
-/** Allocates memory and performs some common initialization for a \c t_selelem. */
-extern t_selelem *
-_gmx_selelem_create(e_selelem_t type);
-/** Sets the value type of a \c t_selelem. */
-extern int
-_gmx_selelem_set_vtype(t_selelem *sel, e_selvalue_t vtype);
-/** Reserves memory for value of a \c t_selelem from a memory pool. */
-extern void
-_gmx_selelem_mempool_reserve(t_selelem *sel, int count);
-/** Releases memory pool used for value of a \c t_selelem. */
-extern void
-_gmx_selelem_mempool_release(t_selelem *sel);
-/** Frees the memory allocated for a \c t_selelem structure and all its children. */
-extern void
-_gmx_selelem_free(t_selelem *sel);
-/** Frees the memory allocated for a \c t_selelem structure, all its children, and also all structures referenced through t_selelem::next fields. */
-extern void
-_gmx_selelem_free_chain(t_selelem *first);
-
-/** Frees the memory allocated for the \c t_selelem::d union. */
-extern void
-_gmx_selelem_free_values(t_selelem *sel);
+void
+_gmx_sel_print_evalfunc_name(FILE *fp, gmx::sel_evalfunc evalfunc);
+
+/** Sets the value type of a gmx::SelectionTreeElement. */
+void
+_gmx_selelem_set_vtype(const gmx::SelectionTreeElementPointer &sel,
+ e_selvalue_t vtype);
+
/** Frees the memory allocated for a selection method. */
-extern void
+void
_gmx_selelem_free_method(struct gmx_ana_selmethod_t *method, void *mdata);
-/** Frees the memory allocated for the \c t_selelem::u field. */
-extern void
-_gmx_selelem_free_exprdata(t_selelem *sel);
-/* In compiler.c */
-/** Frees the memory allocated for the selection compiler. */
-extern void
-_gmx_selelem_free_compiler_data(t_selelem *sel);
/** Prints a human-readable version of a selection element subtree. */
-extern void
-_gmx_selelem_print_tree(FILE *fp, t_selelem *root, bool bValues, int level);
-/* In compile.c */
+void
+_gmx_selelem_print_tree(FILE *fp, const gmx::SelectionTreeElement &sel,
+ bool bValues, int level);
+/* In compiler.c */
/** Prints a human-readable version of the internal compiler data structure. */
-extern void
-_gmx_selelem_print_compiler_info(FILE *fp, t_selelem *sel, int level);
+void
+_gmx_selelem_print_compiler_info(FILE *fp, const gmx::SelectionTreeElement &sel,
+ int level);
/** Returns true if the selection element subtree requires topology information for evaluation. */
-extern bool
-_gmx_selelem_requires_top(t_selelem *root);
+bool
+_gmx_selelem_requires_top(const gmx::SelectionTreeElement &root);
/* In sm_insolidangle.c */
/** Returns true if the covered fraction of the selection can be calculated. */
-extern bool
-_gmx_selelem_can_estimate_cover(t_selelem *sel);
+bool
+_gmx_selelem_can_estimate_cover(const gmx::SelectionTreeElement &sel);
/** Returns the covered fraction of the selection for the current frame. */
-extern real
-_gmx_selelem_estimate_coverfrac(t_selelem *sel);
+real
+_gmx_selelem_estimate_coverfrac(const gmx::SelectionTreeElement &sel);
-/*@}*/
+//!\}
#endif
* _gmx_selelem_estimate_coverfrac(), false otherwise.
*/
bool
-_gmx_selelem_can_estimate_cover(t_selelem *sel)
+_gmx_selelem_can_estimate_cover(const gmx::SelectionTreeElement &sel)
{
- t_selelem *child;
- bool bFound;
- bool bDynFound;
-
- if (sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_OR)
+ if (sel.type == SEL_BOOLEAN && sel.u.boolt == BOOL_OR)
{
return false;
}
- bFound = false;
- bDynFound = false;
- child = sel->child;
+ bool bFound = false;
+ bool bDynFound = false;
+ gmx::SelectionTreeElementPointer child = sel.child;
while (child)
{
if (child->type == SEL_EXPRESSION)
bDynFound = true;
}
}
- else if (!_gmx_selelem_can_estimate_cover(child))
+ else if (!_gmx_selelem_can_estimate_cover(*child))
{
return false;
}
* frame.
*/
real
-_gmx_selelem_estimate_coverfrac(t_selelem *sel)
+_gmx_selelem_estimate_coverfrac(const gmx::SelectionTreeElement &sel)
{
- t_selelem *child;
real cfrac;
- if (sel->type == SEL_EXPRESSION && sel->u.expr.method->name == sm_insolidangle.name)
+ if (sel.type == SEL_EXPRESSION && sel.u.expr.method->name == sm_insolidangle.name)
{
- t_methoddata_insolidangle *d = (t_methoddata_insolidangle *)sel->u.expr.mdata;
+ t_methoddata_insolidangle *d = (t_methoddata_insolidangle *)sel.u.expr.mdata;
if (d->cfrac < 0)
{
- d->cfrac = estimate_covered_fraction(d);
+ d->cfrac = estimate_covered_fraction(d);
}
return d->cfrac;
}
- if (sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_NOT)
+ if (sel.type == SEL_BOOLEAN && sel.u.boolt == BOOL_NOT)
{
- cfrac = _gmx_selelem_estimate_coverfrac(sel->child);
+ cfrac = _gmx_selelem_estimate_coverfrac(*sel.child);
if (cfrac < 1.0)
{
return 1 - cfrac;
}
/* Here, we assume that the selection is simple enough */
- child = sel->child;
+ gmx::SelectionTreeElementPointer child = sel.child;
while (child)
{
- cfrac = _gmx_selelem_estimate_coverfrac(child);
+ cfrac = _gmx_selelem_estimate_coverfrac(*child);
if (cfrac < 1.0)
{
return cfrac;
#define USE_REGEX
#endif
-#include "macros.h"
-#include "smalloc.h"
-#include "string2.h"
+#include "gromacs/legacyheaders/macros.h"
+#include "gromacs/legacyheaders/smalloc.h"
+#include "gromacs/legacyheaders/string2.h"
#include "gromacs/selection/selmethod.h"
-#include "gromacs/utility/errorcodes.h"
+#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/messagestringcollector.h"
#include "keywords.h"
}
/*!
- * \param[out] selp Pointer to receive a pointer to the created selection
- * element (set to NULL on error).
* \param[in] method Keyword selection method to evaluate.
* \param[in] param Parameter that gives the group to evaluate \p method in.
* \param[in] scanner Scanner data structure.
- * \returns 0 on success, non-zero error code on error.
+ * \returns Pointer to the created selection element (NULL on error).
*
- * Creates a \ref SEL_EXPRESSION selection element (pointer put in \c *selp)
- * that evaluates the keyword method given by \p method in the group given by
- * \p param.
+ * Creates a \ref SEL_EXPRESSION selection element that evaluates the keyword
+ * method given by \p method in the group given by \p param.
*/
-int
-_gmx_sel_init_keyword_evaluator(t_selelem **selp, gmx_ana_selmethod_t *method,
+gmx::SelectionTreeElementPointer
+_gmx_sel_init_keyword_evaluator(gmx_ana_selmethod_t *method,
t_selexpr_param *param, void *scanner)
{
- t_selelem *sel;
- t_methoddata_kweval *data;
-
gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
char buf[1024];
sprintf(buf, "In evaluation of '%s'", method->name);
|| method->outinit || method->pupdate)
{
_gmx_selexpr_free_params(param);
- GMX_ERROR(gmx::eeInternalError,
- "Unsupported keyword method for arbitrary group evaluation");
+ GMX_THROW(gmx::InternalError(
+ "Unsupported keyword method for arbitrary group evaluation"));
}
- *selp = NULL;
- sel = _gmx_selelem_create(SEL_EXPRESSION);
+ gmx::SelectionTreeElementPointer sel(
+ new gmx::SelectionTreeElement(SEL_EXPRESSION));
_gmx_selelem_set_method(sel, method, scanner);
+ t_methoddata_kweval *data;
snew(data, 1);
data->kwmethod = sel->u.expr.method;
data->kwmdata = sel->u.expr.mdata;
if (!_gmx_sel_parse_params(param, sel->u.expr.method->nparams,
sel->u.expr.method->param, sel, scanner))
{
- _gmx_selelem_free(sel);
- return -1;
+ return gmx::SelectionTreeElementPointer();
}
- *selp = sel;
- return 0;
+ return sel;
}
* are neglected.
*/
void
-_gmx_selelem_set_kwpos_type(t_selelem *sel, const char *type)
+_gmx_selelem_set_kwpos_type(gmx::SelectionTreeElement *sel, const char *type)
{
t_methoddata_pos *d = (t_methoddata_pos *)sel->u.expr.mdata;
* are neglected.
*/
void
-_gmx_selelem_set_kwpos_flags(t_selelem *sel, int flags)
+_gmx_selelem_set_kwpos_flags(gmx::SelectionTreeElement *sel, int flags)
{
t_methoddata_pos *d = (t_methoddata_pos *)sel->u.expr.mdata;
void *scanner)
{
gmx_ana_selmethod_t *kwmethod;
- t_selelem *kwelem;
t_selexpr_param *param;
char *pname;
- int rc;
/* Do nothing if this is not a same method. */
if (!*method || (*method)->name != sm_same.name)
return 0;
}
- if (params->nval != 1 || !params->value->bExpr
- || params->value->u.expr->type != SEL_EXPRESSION)
+ if (params->nval != 1 || !params->value->hasExpressionValue()
+ || params->value->expr->type != SEL_EXPRESSION)
{
_gmx_selparser_error(scanner, "'same' should be followed by a single keyword");
return -1;
}
- kwmethod = params->value->u.expr->u.expr.method;
+ kwmethod = params->value->expr->u.expr.method;
if (kwmethod->type == STR_VALUE)
{
params->next = NULL;
pname = param->name;
param->name = NULL;
+ gmx::scoped_ptr_sfree pnameGuard(pname);
/* Create a second keyword evaluation element for the keyword given as
* the first parameter, evaluating the keyword in the group given by the
* second parameter. */
- rc = _gmx_sel_init_keyword_evaluator(&kwelem, kwmethod, param, scanner);
- if (rc != 0)
+ gmx::SelectionTreeElementPointer kwelem
+ = _gmx_sel_init_keyword_evaluator(kwmethod, param, scanner);
+ // FIXME: Use exceptions.
+ if (!kwelem)
{
- sfree(pname);
- return rc;
+ return -1;
}
/* Replace the second parameter with one with a value from \p kwelem. */
- param = _gmx_selexpr_create_param(pname);
+ param = _gmx_selexpr_create_param(strdup(pname));
param->nval = 1;
param->value = _gmx_selexpr_create_value_expr(kwelem);
params->next = param;
#include <config.h>
#endif
-#include <macros.h>
-#include <smalloc.h>
-#include <string2.h>
-#include <typedefs.h>
-#include <gmx_fatal.h>
+#include "gromacs/legacyheaders/macros.h"
+#include "gromacs/legacyheaders/smalloc.h"
+#include "gromacs/legacyheaders/string2.h"
#include "gromacs/selection/poscalc.h"
+#include "gromacs/utility/gmxassert.h"
#include "selelem.h"
#include "symrec.h"
/*! \internal \brief
* Single symbol for the selection parser.
+ *
+ * \todo
+ * Make this a proper class.
*/
struct gmx_sel_symrec_t
{
char *name;
/** Type of the symbol. */
e_symbol_t type;
- /** Value of the symbol. */
- union {
- /** Pointer to the method structure (\ref SYMBOL_METHOD). */
- struct gmx_ana_selmethod_t *meth;
- /** Pointer to the variable value (\ref SYMBOL_VARIABLE). */
- struct t_selelem *var;
- } u;
+ /** Pointer to the method structure (\ref SYMBOL_METHOD). */
+ struct gmx_ana_selmethod_t *meth;
+ /** Pointer to the variable value (\ref SYMBOL_VARIABLE). */
+ gmx::SelectionTreeElementPointer var;
/** Pointer to the next symbol. */
struct gmx_sel_symrec_t *next;
};
struct gmx_ana_selmethod_t *
_gmx_sel_sym_value_method(gmx_sel_symrec_t *sym)
{
- if (sym->type != SYMBOL_METHOD)
- {
- gmx_call("symbol is not a method symbol");
- return NULL;
- }
- return sym->u.meth;
+ GMX_RELEASE_ASSERT(sym->type == SYMBOL_METHOD,
+ "Attempting to get method handle for a non-method symbol");
+ return sym->meth;
}
/*!
* \returns The variable expression associated with \p sym, or NULL if
* \p sym is not a \ref SYMBOL_VARIABLE symbol.
*/
-struct t_selelem *
+const gmx::SelectionTreeElementPointer &
_gmx_sel_sym_value_var(gmx_sel_symrec_t *sym)
{
- if (sym->type != SYMBOL_VARIABLE)
- {
- gmx_call("symbol is not a variable symbol");
- return NULL;
- }
- return sym->u.var;
+ GMX_RELEASE_ASSERT(sym->type == SYMBOL_VARIABLE,
+ "Attempting to get variable value for a non-variable symbol");
+ return sym->var;
}
/*! \brief
static void
add_reserved_symbols(gmx_sel_symtab_t *tab)
{
- gmx_sel_symrec_t *sym;
gmx_sel_symrec_t *last;
size_t i;
last = NULL;
for (i = 0; i < asize(sym_reserved); ++i)
{
- snew(sym, 1);
+ gmx_sel_symrec_t *sym = new gmx_sel_symrec_t();
sym->name = strdup(sym_reserved[i]);
sym->type = SYMBOL_RESERVED;
+ sym->meth = NULL;
sym->next = NULL;
if (last)
{
static void
add_position_symbols(gmx_sel_symtab_t *tab)
{
- gmx_sel_symrec_t *sym;
gmx_sel_symrec_t *last;
int i;
}
for (i = 0; postypes[i] != NULL; ++i)
{
- snew(sym, 1);
+ gmx_sel_symrec_t *sym = new gmx_sel_symrec_t();
sym->name = strdup(postypes[i]);
sym->type = SYMBOL_POS;
+ sym->meth = NULL;
sym->next = NULL;
if (last)
{
{
sym = tab->first;
tab->first = sym->next;
- if (sym->type == SYMBOL_VARIABLE)
- {
- _gmx_selelem_free(sym->u.var);
- }
sfree(sym->name);
- sfree(sym);
+ delete sym;
}
sfree(tab);
}
/* Create a new symbol record */
if (psym == NULL)
{
- snew(tab->first, 1);
+ tab->first = new gmx_sel_symrec_t();
sym = tab->first;
}
else
{
- snew(psym->next, 1);
+ psym->next = new gmx_sel_symrec_t();
sym = psym->next;
}
sym->name = strdup(name);
+ sym->meth = NULL;
+ sym->next = NULL;
return sym;
}
*/
gmx_sel_symrec_t *
_gmx_sel_add_var_symbol(gmx_sel_symtab_t *tab, const char *name,
- struct t_selelem *sel)
+ const gmx::SelectionTreeElementPointer &sel)
{
gmx_sel_symrec_t *sym;
e_symbol_t ctype;
}
sym->type = SYMBOL_VARIABLE;
- sym->u.var = sel;
- sel->refcount++;
+ sym->var = sel;
return sym;
}
}
sym->type = SYMBOL_METHOD;
- sym->u.meth = method;
+ sym->meth = method;
return sym;
}
* \author Teemu Murtola <teemu.murtola@cbr.su.se>
* \ingroup module_selection
*/
-#ifndef SELECTION_SYMREC_H
-#define SELECTION_SYMREC_H
+#ifndef GMX_SELECTION_SYMREC_H
+#define GMX_SELECTION_SYMREC_H
+
+#include "selelem.h"
-struct t_selelem;
struct gmx_ana_selmethod_t;
/** Defines the type of the symbol. */
/** Returns the method associated with a \ref SYMBOL_METHOD symbol. */
struct gmx_ana_selmethod_t *
_gmx_sel_sym_value_method(gmx_sel_symrec_t *sym);
-/** Returns the method associated with a \ref SYMBOL_VARIABLE symbol. */
-struct t_selelem *
+/** Returns the selection tree associated with a \ref SYMBOL_VARIABLE symbol. */
+const gmx::SelectionTreeElementPointer &
_gmx_sel_sym_value_var(gmx_sel_symrec_t *sym);
/** Creates a new symbol table. */
/** Adds a new variable symbol. */
gmx_sel_symrec_t *
_gmx_sel_add_var_symbol(gmx_sel_symtab_t *tab, const char *name,
- struct t_selelem *sel);
+ const gmx::SelectionTreeElementPointer &sel);
/** Adds a new method symbol. */
gmx_sel_symrec_t *
_gmx_sel_add_method_symbol(gmx_sel_symtab_t *tab, const char *name,