Exemplo n.º 1
0
/*!
 * \param      scanner  Scanner data structure.
 * \param[in]  sel      The selection element that evaluates the selection.
 * \returns    The created root selection element.
 *
 * This function handles the creation of root (\ref SEL_ROOT) \c t_selelem
 * objects for selections.
 */
t_selelem *
_gmx_sel_init_selection(gmx_sel_lexer_t *scanner, t_selelem *sel)
{
    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
    t_selelem               *root;
    int                      rc;

    if (sel->v.type != POS_VALUE)
    {
        gmx_bug("each selection must evaluate to a position");
        /* FIXME: Better handling of this error */
        return NULL;
    }

    root = _gmx_selelem_create(SEL_ROOT);
    root->child = sel;
    /* Update the flags */
    rc = _gmx_selelem_update_flags(root);
    if (rc != 0)
    {
        _gmx_selelem_free(root);
        return NULL;
    }

    /* Print out some information if the parser is interactive */
    if (_gmx_sel_is_lexer_interactive(scanner))
    {
        /* TODO: It would be nice to print the whole selection here */
        fprintf(stderr, "Selection parsed\n");
    }

    return root;
}
Exemplo n.º 2
0
/*!
 * \param      scanner  Scanner data structure.
 * \param[in]  name     Name of the variable (should not be freed after this
 *   function).
 * \param[in]  expr     The selection element that evaluates the variable.
 * \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
 * element are both created.
 */
t_selelem *
_gmx_sel_assign_variable(gmx_sel_lexer_t *scanner, char *name, t_selelem *expr)
{
    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
    t_selelem               *root;
    int                      rc;

    rc = _gmx_selelem_update_flags(expr);
    if (rc != 0)
    {
        sfree(name);
        _gmx_selelem_free(expr);
        return NULL;
    }
    /* 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;
        }
        _gmx_selelem_free(expr);
        if (_gmx_sel_is_lexer_interactive(scanner))
        {
            fprintf(stderr, "Variable '%s' parsed\n", name);
        }
        sfree(name);
        return NULL;
    }
    /* Check if we are assigning a variable to another variable */
    if (expr->type == SEL_SUBEXPRREF)
    {
        /* 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;
        }
        _gmx_selelem_free(expr);
        if (_gmx_sel_is_lexer_interactive(scanner))
        {
            fprintf(stderr, "Variable '%s' parsed\n", name);
        }
        sfree(name);
        return NULL;
    }
    /* Create the root element */
    root = _gmx_selelem_create(SEL_ROOT);
    root->name          = name;
    root->u.cgrp.name   = name;
    /* Create the subexpression element */
    root->child = _gmx_selelem_create(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);
    if (rc != 0)
    {
        _gmx_selelem_free(root);
        return NULL;
    }
    /* Add the variable to the symbol table */
    if (!_gmx_sel_add_var_symbol(sc->symtab, name, root->child))
    {
        _gmx_selelem_free(root);
        return NULL;
    }
    if (_gmx_sel_is_lexer_interactive(scanner))
    {
        fprintf(stderr, "Variable '%s' parsed\n", name);
    }
    return root;
}
Exemplo n.º 3
0
/*!
 * \param[in,out] sel  Root of the selection element tree to initialize.
 * \returns       0 on success, an error code on error.
 *
 * Propagates the \ref SEL_DYNAMIC flag from the children of \p sel to \p sel
 * (if any child of \p sel is dynamic, \p sel is also marked as such).
 * The \ref SEL_DYNAMIC flag is also set for \ref SEL_EXPRESSION elements with
 * a dynamic method.
 * Also, sets one of the \ref SEL_SINGLEVAL, \ref SEL_ATOMVAL, or
 * \ref SEL_VARNUMVAL flags, either based on the children or on the type of
 * the selection method.
 * If the types of the children conflict, an error is returned.
 *
 * The flags of the children of \p sel are also updated if not done earlier.
 * The flags are initialized only once for any element; if \ref SEL_FLAGSSET
 * 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)
{
    t_selelem          *child;
    int                 rc;
    bool                bUseChildType;

    /* Return if the flags have already been set */
    if (sel->flags & SEL_FLAGSSET)
    {
        return 0;
    }
    /* Set the flags based on the current element type */
    switch (sel->type)
    {
        case SEL_CONST:
            sel->flags |= SEL_SINGLEVAL;
            bUseChildType = FALSE;
            break;

        case SEL_EXPRESSION:
            if (sel->u.expr.method->flags & SMETH_DYNAMIC)
            {
                sel->flags |= SEL_DYNAMIC;
            }
            if (sel->u.expr.method->flags & SMETH_SINGLEVAL)
            {
                sel->flags |= SEL_SINGLEVAL;
            }
            else if (sel->u.expr.method->flags & SMETH_VARNUMVAL)
            {
                sel->flags |= SEL_VARNUMVAL;
            }
            else
            {
                sel->flags |= SEL_ATOMVAL;
            }
            bUseChildType = FALSE;
            break;

        case SEL_MODIFIER:
            if (sel->v.type != NO_VALUE)
            {
                sel->flags |= SEL_VARNUMVAL;
            }
            bUseChildType = FALSE;
            break;

        case SEL_ROOT:
            bUseChildType = FALSE;
            break;

        default:
            bUseChildType = TRUE;
            break;
    }
    /* Loop through children to propagate their flags upwards */
    child = sel->child;
    while (child)
    {
        /* Update the child */
        rc = _gmx_selelem_update_flags(child);
        if (rc != 0)
        {
            return rc;
        }
        /* Propagate the dynamic flag */
        sel->flags |= (child->flags & SEL_DYNAMIC);
        /* Propagate the type flag if necessary and check for problems */
        if (bUseChildType)
        {
            if ((sel->flags & SEL_VALTYPEMASK)
                && !(sel->flags & child->flags & SEL_VALTYPEMASK))
            {
                _gmx_selparser_error("invalid combination of selection expressions");
                return EINVAL;
            }
            sel->flags |= (child->flags & SEL_VALTYPEMASK);
        }

        child = child->next;
    }
    /* Mark that the flags are set */
    sel->flags |= SEL_FLAGSSET;
    /* For root elements, the type should be propagated here, after the
     * children have been updated. */
    if (sel->type == SEL_ROOT)
    {
        sel->flags |= (sel->child->flags & SEL_VALTYPEMASK);
    }
    return 0;
}
Exemplo n.º 4
0
/*! \brief
 * Adds a new subexpression reference to a selection element.
 *
 * \param[in,out] root  Root element to which the subexpression is added.
 * \param[in]     param Parameter for which this expression is a value.
 * \param[in]     expr  Expression to add.
 * \returns       The created child element.
 *
 * Creates a new \ref SEL_SUBEXPRREF element and adds it into the child
 * list of \p root.
 * 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)
{
    t_selelem          *child;
    int                 rc;

    if (root->type != SEL_EXPRESSION && root->type != SEL_MODIFIER)
    {
        gmx_bug("unsupported root element for selection parameter parser");
        return NULL;
    }
    /* Create a subexpression reference element if necessary */
    if (expr->type == SEL_SUBEXPRREF)
    {
        child = expr;
    }
    else
    {
        child = _gmx_selelem_create(SEL_SUBEXPRREF);
        if (!child)
        {
            return NULL;
        }
        _gmx_selelem_set_vtype(child, expr->v.type);
        child->child  = expr;
    }
    /* Setup the child element */
    child->flags &= ~SEL_ALLOCVAL;
    child->u.param = param;
    if (child->v.type != param->val.type)
    {
        _gmx_selparser_error("invalid expression value for parameter '%s'",
                             param->name);
        goto on_error;
    }
    rc = _gmx_selelem_update_flags(child);
    if (rc != 0)
    {
        goto on_error;
    }
    if ((child->flags & SEL_DYNAMIC) && !(param->flags & SPAR_DYNAMIC))
    {
        _gmx_selparser_error("parameter '%s' does not support dynamic values",
                             param->name);
        goto on_error;
    }
    if (!(child->flags & SEL_DYNAMIC))
    {
        param->flags &= ~SPAR_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;
}