Fast and lightweight math expression evaluator in C99
Expr is a mathematical expression evaluator written in C. It takes string as
input and returns floating-point number as a result.
#include "expr.h"
// Custom function that returns the sum of its two arguments
static float add(struct expr_func *f, vec_expr_t *args, void *c) {
float a = expr_eval(&vec_nth(args, 0));
float b = expr_eval(&vec_nth(args, 1));
return a + b;
}
static struct expr_func user_funcs[] = {
{"add", add, NULL, 0},
{NULL, NULL, NULL, 0},
};
int main() {
const char *s = "x = 5, add(2, x)";
struct expr_var_list vars = {0};
struct expr *e = expr_create(s, strlen(s), &vars, user_funcs);
if (e == NULL) {
printf("Syntax error");
return 1;
}
float result = expr_eval(e);
printf("result: %f\n", result);
expr_destroy(e, &vars);
return 0;
}
Output: result: 7.000000
struct expr *expr_create(const char *s, size_t len, struct expr_var_list *vars, struct expr_func *funcs)
- returns compiled expression from the given
string. If expression uses variables - they are bound to vars
, so you can
modify values before evaluation or check the results after the evaluation.
float expr_eval(struct expr *e)
- evaluates compiled expression.
void expr_destroy(struct expr *e, struct expr_var_list *vars)
- cleans up
memory. Parameters can be NULL (e.g. if you want to clean up expression, but
reuse variables for another expression).
struct expr_var *expr_var(struct expr_var *vars, const char *s, size_t len)
-
returns/creates variable of the given name in the given list. This can be used
to get variable references to get/set them manually.
+
, -
, *
, /
, %
(remainder), **
(power)<<
, >>
, &
, |
, ^
(xor or unary bitwise negation)<
, >
, ==
, !=
, <=
, >=
, &&
, ||
, !
(unary not)=
(assignment, e.g. x=y=5
), ,
(separates expressions or function parameters)Only the following functions from libc are used to reduce the footprint and
make it easier to use:
To run all the tests and benchmarks do make test
. This will be using your
default compiler and will do no code coverage.
To see the code coverage you may either do make llvm-cov
or make gcov
depending on whether you use GCC or LLVM/Clang.
Since people may have different compiler versions, one may specify a version
explicitly, e.g. make llvm-cov LLVM_VER=-3.8
or make gcov GCC_VER=-5
.
Code is distributed under MIT license, feel free to use it in your proprietary
projects as well.