## GwyExpr

GwyExpr — Arithmetic expression parser and evaluator

## Synopsis

    #include <libgwyddion/gwyddion.h>

    #define             GWY_EXPR_ERROR
    enum                GwyExprError;
                        GwyExpr;
    GQuark              gwy_expr_error_quark                (void);
    GwyExpr*            gwy_expr_new                        (void);
    void                gwy_expr_free                       (GwyExpr *expr);
    gboolean            gwy_expr_evaluate                   (GwyExpr *expr,
                                                             const gchar *text,
                                                             gdouble *result,
                                                             GError **err);
    gboolean            gwy_expr_compile                    (GwyExpr *expr,
                                                             const gchar *text,
                                                             GError **err);
    guint               gwy_expr_resolve_variables          (GwyExpr *expr,
                                                             guint n,
                                                             const gchar * const *names,
                                                             guint *indices);
    gint                gwy_expr_get_variables              (GwyExpr *expr,
                                                             gchar ***names);
    gdouble             gwy_expr_execute                    (GwyExpr *expr,
                                                             const gdouble *values);
    void                gwy_expr_vector_execute             (GwyExpr *expr,
                                                             guint n,
                                                             const gdouble **data,
                                                             gdouble *result);
    gboolean            gwy_expr_define_constant            (GwyExpr *expr,
                                                             const gchar *name,
                                                             gdouble value,
                                                             GError **err);
    gboolean            gwy_expr_undefine_constant          (GwyExpr *expr,
                                                             const gchar *name);
    const gchar*        gwy_expr_get_expression             (GwyExpr *expr);

## Description

GwyExpr is an expression evaluator, more precisely parser, compiler, and evaluator. A new GwyExpr can be created with `gwy_expr_new()`, then it can be used to evaluate any number of expressions; when it's no longer needed, it should be destroyed with `gwy_expr_free()`.

Expression syntax is described in Gwyddion user guide.

Simple arithmetic expressions without variables can be directly evaluated with `gwy_expr_evaluate()`.

Expression with variables have to be compiled first with `gwy_expr_compile()`. Then either `gwy_expr_resolve_variables()` or `gwy_expr_get_variables()` can be used to obtain information what variables are present in the expression and at which positions (variables are referenced by position, not name during final evaluation because of effieiency reasons). Subsequent evaluation with variable substitution is performed by `gwy_expr_execute()`. It is also possible to evaluate expression on each item of value arrays with `gwy_expr_vector_execute()`.

One-shot evaluation of expressions without variables is easy:

    GwyExpr *expr;
    GError *err = NULL;
    gdouble result;

    expr = gwy_expr_new();
    if (!gwy_expr_evaluate(expr, "1+2", &result, &err)) {
        /* Handle compilation error */
    }
    g_print("The result: %g\n", result);
    gwy_expr_free(expr);

One-shot evaluation of expressions with known variables can be performed by defining them as constants beforehand:

    GwyExpr *expr;
    GError *err = NULL;
    gdouble result;

    /* Create expression and define variables as constants */
    expr = gwy_expr_new();
    gwy_expr_define_constant(expr, "x", 3.0, NULL);
    gwy_expr_define_constant(expr, "y", 4.0, NULL);

    /* Evaluate expression */
    if (!gwy_expr_evaluate(expr, "hypot x,y", &result, &err)) {
        /* Handle compilation error */
    }
    g_print("The result: %g\n", result);

    gwy_expr_free(expr);

When the same expression is evaluated multiple times with different variable values and the variables are again from some known set, the `gwy_expr_resolve_variables()` should be used (if the repeated evaluation happens over items of some arrays, `gwy_expr_vector_execute()` is more efficient and usually simplier to use too):

    GwyExpr *expr;
    GError *err = NULL;
    const gchar *const var_names[] = { "lambda", "theta", "psi", "d", "k" };
    const gdouble var_values1[] = { 300.0, 0.09, 2.0, 52.3, 1.43 };
    const gdouble var_values2[] = { 400.0, 0.12, 2.0, 54.1, 1.44 };
    guint var_positions[G_N_ELEMENTS(var_names)];
    gdouble vars[G_N_ELEMENTS(var_names) + 1];
    guint i;

    /* Create expression and define constant pi */
    expr = gwy_expr_new();
    gwy_expr_define_constant(expr, "pi", G_PI, NULL);

    /* Compile expression */
    if (!gwy_expr_compile(expr, "2*pi/lambda*d*sin theta", &err)) {
        /* Handle compilation error */
    }

    /* Resolve variables */
    if (gwy_expr_resolve_variables(expr, G_N_ELEMENTS(var_names),
                                   var_names, var_positions)) {
        /* Expression contains unknown variables */
    }

    /* Evaluate first set */
    for (i = 0; i < G_N_ELEMENTS(var_names); i++) {
        vars[var_positions[i]] = var_values1[i];
    }
    g_print("First result: %g\n", gwy_expr_execute(expr, vars));

    /* Evaluate second set */
    for (i = 0; i < G_N_ELEMENTS(var_names); i++)
        vars[var_positions[i]] = var_values2[i];
    g_print("Second result: %g\n", gwy_expr_execute(expr, vars));

    gwy_expr_free(expr);

The most general case is when the variables are from a large set (or completely arbitrary). Then it is best to get the list of variables with `gwy_expr_get_variables()` and supply only values of variables that are actually present in the expression.

## Details

### GWY_EXPR_ERROR

    #define GWY_EXPR_ERROR gwy_expr_error_quark()

Error domain for expression parsing and evaluation. Errors in this domain will be from the GwyExprError enumeration. See GError for information on error domains.

### enum GwyExprError

    typedef enum {
        GWY_EXPR_ERROR_CLOSING_PARENTHESIS,
        GWY_EXPR_ERROR_EMPTY,
        GWY_EXPR_ERROR_EMPTY_PARENTHESES,
        GWY_EXPR_ERROR_GARBAGE,
        GWY_EXPR_ERROR_INVALID_ARGUMENT,
        GWY_EXPR_ERROR_INVALID_TOKEN,
        GWY_EXPR_ERROR_MISSING_ARGUMENT,
        GWY_EXPR_ERROR_NOT_EXECUTABLE,
        GWY_EXPR_ERROR_OPENING_PARENTHESIS,
        GWY_EXPR_ERROR_STRAY_COMMA,
        GWY_EXPR_ERROR_UNRESOLVED_IDENTIFIERS,
        GWY_EXPR_ERROR_CONSTANT_NAME
    } GwyExprError;

Error codes returned by expression parsing and execution.

`GWY_EXPR_ERROR_CLOSING_PARENTHESIS` | A closing parenthesis is missing.
`GWY_EXPR_ERROR_EMPTY` | Expression is empty.
`GWY_EXPR_ERROR_EMPTY_PARENTHESES` | A parentheses pair contain nothing inside.
`GWY_EXPR_ERROR_GARBAGE` | An symbol unexpectedly managed to survive.
`GWY_EXPR_ERROR_INVALID_ARGUMENT` | Function or operator argument is not a value.
`GWY_EXPR_ERROR_INVALID_TOKEN` | Expression contains an invalid token.
`GWY_EXPR_ERROR_MISSING_ARGUMENT` | Function or operator arguments is missing.
`GWY_EXPR_ERROR_NOT_EXECUTABLE` | Compiled stack is not executable.
`GWY_EXPR_ERROR_OPENING_PARENTHESIS` | An opening parenthesis is missing.
`GWY_EXPR_ERROR_STRAY_COMMA` | A comma at the start or end of list.
`GWY_EXPR_ERROR_UNRESOLVED_IDENTIFIERS` | Expression contains unresolved identifiers.
`GWY_EXPR_ERROR_CONSTANT_NAME` | Constant name is invalid.

### GwyExpr

    typedef struct _GwyExpr GwyExpr;

GwyExpr is an opaque data structure and should be only manipulated with the functions below.

### gwy_expr_error_quark ()

    GQuark              gwy_expr_error_quark                (void);

Returns error domain for expression parsin and evaluation.

See and use `GWY_EXPR_ERROR`.

Returns : | The error domain.

### gwy_expr_new ()

    GwyExpr*            gwy_expr_new                        (void);

Creates a new expression evaluator.

Returns : | A newly created expression evaluator.

### gwy_expr_free ()

    void                gwy_expr_free                       (GwyExpr *expr);

Frees all memory used by an expression evaluator.

`expr` : | An expression evaluator.

### gwy_expr_evaluate ()

    gboolean            gwy_expr_evaluate                   (GwyExpr *expr,
                                                             const gchar *text,
                                                             gdouble *result,
                                                             GError **err);

Evaulates an arithmetic expression.

`expr` : | An expression evaluator.
`text` : | String containing the expression to evaluate.
`result` : | Location to store result to.
`err` : | Location to store compilation or evaluation error to, or `NULL`. Errors from GwyExprError domain can occur.
Returns : | `TRUE` on success, `FALSE` if evaluation failed.

### gwy_expr_compile ()

    gboolean            gwy_expr_compile                    (GwyExpr *expr,
                                                             const gchar *text,
                                                             GError **err);

Compiles an expression for later execution.

This function is useful for expressions with variables. For normal arithmetic expressions it's easier to use `gwy_expr_evaluate()`.

`expr` : | An expression evaluator.
`text` : | String containing the expression to compile.
`err` : | Location to store compilation or evaluation error to, or `NULL`. Errors from GwyExprError domain can occur.
Returns : | `TRUE` on success, `FALSE` if compilation failed.

### gwy_expr_resolve_variables ()

    guint               gwy_expr_resolve_variables          (GwyExpr *expr,
                                                             guint n,
                                                             const gchar * const *names,
                                                             guint *indices);

Finds positions of variables in an expression.

`expr` : | An expression evaluator.
`n` : | The length of `names` and `indices` arrays.
`names` : | List of variable names to get positions of.
`indices` : | Array to store variable positions to. The positions are the same as in `gwy_expr_execute()`. Variables not present in the expression are assigned (reserved) position 0. This allows to safely substitute values of all variables before execution wthout caring which variables are actually present.
Returns : | The number of remaining, unresolved variables in `expr`.

### gwy_expr_get_variables ()

    gint                gwy_expr_get_variables              (GwyExpr *expr,
                                                             gchar ***names);

Get the number, names, and indices of unresolved identifiers in `expr`.

It is an error to call this function after an unsuccessful compilation.

If you only care about variables from a prefedined set, that is if any unknown variable is an error, it's easier to use `gwy_expr_resolve_variables()`.

The position of each variable in `names` corresponds to the position of its value in `values` array in `gwy_expr_execute()` call. Namely, the first item in the array is always reserved and do not correspond to any variable.

`expr` : | An expression evaluator.
`names` : | Location to store pointer to array of variable names to (may be `NULL` to get just number of variables). The string array returned in this argument in owned by `expr` and is valid only until next `gwy_expr_compile()`, `gwy_expr_evaluate()`, or `gwy_expr_free()` call.
Returns : | The length of array stored to `names`. This is the number of variables plus one (for the first reserved item). On failure, 0 is returned.

### gwy_expr_execute ()

    gdouble             gwy_expr_execute                    (GwyExpr *expr,
                                                             const gdouble *values);

Executes a compiled expression with variables, substituting given values.

`expr` : | An expression evaluator.
`values` : | Array with variable values. Its zeroth item is always unused. Variable list can be obtained by `gwy_expr_get_variables()`.
Returns : | The result.

### gwy_expr_vector_execute ()

    void                gwy_expr_vector_execute             (GwyExpr *expr,
                                                             guint n,
                                                             const gdouble **data,
                                                             gdouble *result);

Executes a compiled expression on each item of data arrays.

`expr` : | An expression evaluator.
`n` : | The lenght of `result` and of `data` member arrays, that is vector length.
`data` : | An array of arrays of length `n`. The arrays correspond to expression variables in `gwy_expr_execute()`. Zeroth array can be `NULL`.
`result` : | An array of length `n` to store computation results to. It may be one of those in `data`.

### gwy_expr_define_constant ()

    gboolean            gwy_expr_define_constant            (GwyExpr *expr,
                                                             const gchar *name,
                                                             gdouble value,
                                                             GError **err);

Defines a symbolic constant.

Note the definition does not affect already compiled expression, you have to recompile it (and eventually re-resolve variables).

`expr` : | An expression evaluator.
`name` : | Name of constant to define.
`value` : | Constant numeric value.
`err` : | Location to store error to, or `NULL`. Only `GWY_EXPR_ERROR_CONSTANT_NAME` error from GwyExprError domain can occur.
Returns : | `TRUE` on success, `FALSE` if definition failed.

### gwy_expr_undefine_constant ()

    gboolean            gwy_expr_undefine_constant          (GwyExpr *expr,
                                                             const gchar *name);

Undefines a symbolic constant.

Note the definition removal does not affect already compiled expression, you have to recompile it (and eventually re-resolve variables).

`expr` : | An expression evaluator.
`name` : | Name of constant to undefine.
Returns : | `TRUE` if there was such a constant and was removed, `FALSE` otherwise.

### gwy_expr_get_expression ()

    const gchar*        gwy_expr_get_expression             (GwyExpr *expr);

Gets the expression string.

`expr` : | An expression evaluator.
Returns : | The last string passed to `gwy_expr_evaluate()` or `gwy_expr_compile()`. It is owned by `expr` and must not be modified or freed.