Expression

This component implements the functionality to parse a simple expression. The expression supports only variables, constants, and functions.

The syntax is as follows:

abc   -- This is a variable
"abc" -- This is a string constant
'abc' -- This is also a string constant
1     -- Integer
1.2   -- Float
0xa   -- Hexadecimal integer
0311  -- Octal integer

concat(abc, bcd) -- This is a function with two parameters, both are variables
concat(abc, "bcd") -- This is a function with two parameters, one is a variable and the other is a constant
concat(1, "bcd") -- Both parameters are constants
concat("abc", concat(bcd, "efg")) -- This example demonstrates nested function calls
concat("abc", concat(bcd, "efg")) aaa concat("bcd", concat(efg, "hij")) -- This example demonstrates running multiple expressions

-- if else
if a then
  var1
else
  func2()
fi

if a then
  func1()
  if b then
  fi
else
  if c then
  else
  fi
fi

-- loop
loop condition do
  aaa
  func(func2())
  if a then
    bbb
  else
    ccc
  fi
end

Header file

#include "mln_expr.h"

Module

expr

Functions

mln_expr_val_new

mln_expr_val_t *mln_expr_val_new(mln_expr_typ_t type, void *data, mln_expr_udata_free free);

typedef void (*mln_expr_udata_free)(void *);

typedef enum {
    mln_expr_type_null = 0,
    mln_expr_type_bool,
    mln_expr_type_int,
    mln_expr_type_real,
    mln_expr_type_string,
    mln_expr_type_udata,
} mln_expr_typ_t;

typedef struct {
    mln_expr_typ_t       type;
    union {
        mln_u8_t         b;
        mln_s64_t        i;
        double           r;
        mln_string_t    *s;
        void            *u;
    } data;
    mln_expr_udata_free  free;
} mln_expr_val_t;

Description: Create an expression value object. mln_expr_typ_t is the type of the expression, and mln_expr_val_t is the structure of the value object. Depending on the first parameter, the second parameter of the function mln_expr_val_new can have the following types:

  • mln_u8_t *
  • mln_s64_t *
  • double *
  • mln_string_t * Strings will be referenced using the mln_string_ref within the function.
  • void * User-defined data. It can be freed by the free function indicated by the third parameter of this function.

Return values:

  • On success: Pointer to mln_expr_val_t
  • On failure: NULL

mln_expr_val_free

void mln_expr_val_free(mln_expr_val_t *ev);

Description: Free an expression value object. If the value is of type string and the free callback is also set, then the string will be freed using free; otherwise, mln_string_free will be used for freeing.

Return value: None

mln_expr_val_copy

void mln_expr_val_copy(mln_expr_val_t *dest, mln_expr_val_t *src);

Description: duplicate an expression value object. Duplicate the content of src to dest. If the type is a string, the function mln_string_ref will be used to reference the string. If it is of type udata, simply copy the data pointer and set src's free to NULL, ensuring that the user-defined data is not freed when src is released.

Return value: None

mln_expr_val_dup

void mln_expr_val_dup(mln_expr_val_t *val);

Description: Copy an expression value object. Similar to mln_expr_val_copy, but allocates a completely new block of memory.

Return values:

  • On success: Pointer to mln_expr_val_t
  • On failure: NULL

mln_expr_run

mln_expr_val_t *mln_expr_run(mln_string_t *exp, mln_expr_cb_t cb, void *data);

typedef mln_expr_val_t *(*mln_expr_cb_t)(mln_string_t *namespace, mln_string_t *name, int is_func, mln_array_t *args, void *data);

Description: Run the expression exp. Variables and functions (along with their arguments) in the expression, as well as user-defined data data, will be passed to the callback function cb for evaluation. Developers can customize the values of these functions and variables as needed.

Return values:

  • On success: Pointer to mln_expr_val_t, containing the result of the evaluation
  • On failure: NULL

mln_expr_run_file

mln_expr_val_t *mln_expr_run_file(mln_string_t *path, mln_expr_cb_t cb, void *data);

typedef mln_expr_val_t *(*mln_expr_cb_t)(mln_string_t *namespace, mln_string_t *name, int is_func, mln_array_t *args, void *data);

Description: Run the expression specified in the file identified by path. Variables and functions (along with their arguments) in the expression, as well as user-defined data data, will be passed to the callback function cb for evaluation. Developers can customize the values of these functions and variables as needed.

Return values:

  • On success: Pointer to mln_expr_val_t, containing the result of the evaluation
  • On failure: NULL

Example

#include "mln_expr.h"
#include "mln_log.h"
#include <stdio.h>

static mln_expr_val_t *var_expr_handler(mln_string_t *namespace, mln_string_t *name, int is_func, mln_array_t *args, void *data)
{
    mln_string_t *s;
    mln_expr_val_t *ret;
    mln_string_t anon = mln_string("anonymous namespace");

    if (is_func)
        mln_log(none, "%S %S %d %U %X\n", namespace? namespace: &anon, name, is_func, args->nelts, data);
    else
        mln_log(none, "%S %S %d %X\n", namespace? namespace: &anon, name, is_func, data);
    if ((s = mln_string_dup(name)) == NULL) return NULL;
    ret = mln_expr_val_new(mln_expr_type_string, s, NULL);
    mln_string_free(s);
    return ret;
}

static mln_expr_val_t *func_expr_handler(mln_string_t *namespace, mln_string_t *name, int is_func, mln_array_t *args, void *data)
{
    mln_expr_val_t *v, *p;
    int i;
    mln_string_t *s1 = NULL, *s2, *s3;
    mln_string_t anon = mln_string("anonymous namespace");

    if (is_func) {
        mln_log(none, "%S %S %d %U %X\n", namespace? namespace: &anon, name, is_func, args->nelts, data);
    } else {
        mln_log(none, "%S %S %d %X\n", namespace? namespace: &anon, name, is_func, data);
        return mln_expr_val_new(mln_expr_type_string, name, NULL);
    }

    for (i = 0, v = p = mln_array_elts(args); i < mln_array_nelts(args); v = p + (++i)) {
        if (s1 == NULL) {
            s1 = mln_string_ref(v->data.s);
            continue;
        }
        s2 = v->data.s;
        s3 = mln_string_strcat(s1, s2);
        mln_string_free(s1);
        s1 = s3;
    }

    v = mln_expr_val_new(mln_expr_type_string, s1, NULL);
    mln_string_free(s1);

    return v;
}

int main(void)
{
    mln_string_t var_exp = mln_string(":aaa (a:b:c:bbb)");
    mln_string_t func_exp = mln_string("abc:def:concat('abc', concat(aaa, 'bbb')) ccc concat('eee', concat(bbb, 'fff'))");

    mln_expr_val_t *v;

    v = mln_expr_run(&var_exp, var_expr_handler, NULL);
    if (v == NULL) {
        mln_log(error, "run failed\n");
        return -1;
    }
    mln_log(debug, "%d %S\n", v->type, v->data.s);
    mln_expr_val_free(v);

    v = mln_expr_run(&func_exp, func_expr_handler, NULL);
    if (v == NULL) {
        mln_log(error, "run failed\n");
        return -1;
    }
    mln_log(debug, "%d %S\n", v->type, v->data.s);
    mln_expr_val_free(v);

    return 0;
}

Execution result:

a:b:c bbb 0 0
anonymous namespace aaa 1 1 0
08/16/2024 14:13:59 UTC DEBUG: a.c:main:64: PID:792687 4 aaa
anonymous namespace aaa 0 0
anonymous namespace concat 1 2 0
abc:def concat 1 2 0
anonymous namespace ccc 0 0
anonymous namespace bbb 0 0
anonymous namespace concat 1 2 0
anonymous namespace concat 1 2 0
08/16/2024 14:13:59 UTC DEBUG: a.c:main:72: PID:792687 4 eeebbbfff

results matching ""

    No results matching ""