Skip to content

Commit

Permalink
feat(expr): add a lightweight expression component
Browse files Browse the repository at this point in the history
Given an expression in string format and a callback function for handling variables and functions, it should return the value of the string expression.
  • Loading branch information
Water-Melon committed Mar 18, 2024
1 parent a221cad commit e3eaffa
Show file tree
Hide file tree
Showing 12 changed files with 871 additions and 39 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Melon is a generic cross-platform C library. It contains many algorithms, data s
- Spin Lock
- Prime Generator
- Span
- Expression
- Data Structures
- Doubly Linked List
- Fibonacci Heap
Expand Down
13 changes: 13 additions & 0 deletions docs/Melon Developer Guide.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3236,6 +3236,19 @@ Their definitions can be found in melon/include/mln_types.h.
c) delete(o, ...);
Uninitialize and release a class instance. `...` is the rest arguments to be passed to destructor.

49) Expression
a) mln_expr_val_t *mln_expr_val_new(mln_expr_typ_t type, void *data);
Create an expression value object.

b) void mln_expr_val_free(mln_expr_val_t *ev);
Free an expression value object.

c) void mln_expr_val_dup(mln_expr_val_t *dest, mln_expr_val_t *src);
Duplicate an expression object from `src` to `dest`.

d) mln_expr_val_t *mln_expr_run(mln_string_t *exp, mln_expr_cb_t cb, void *data);
Run a simple expression `exp`. `cb` will be called with user-data `data` when parsing variables and functions.

5. Framework Usage
It is very easy to use this framework. Before we use it, we have to initialize it.
1) include header file.
Expand Down
1 change: 1 addition & 0 deletions docs/book/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Melon currently provides the following components:
- Spin Lock
- Prime Generator
- Span
- Expression
- Data Structures
- Doubly Linked List
- Fibonacci Heap
Expand Down
2 changes: 2 additions & 0 deletions docs/book/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
- [Spin Lock](en/spinlock.md)
- [Prime Generator](en/prime.md)
- [Span](en/span.md)
- [Expression](en/expr.md)
- [Data Structures](en/datastruct.md)
- [Doubly Linked List](en/double_linked_list.md)
- [Fibonacci Heap](en/fheap.md)
Expand Down Expand Up @@ -85,6 +86,7 @@
- [自旋锁](cn/spinlock.md)
- [素数生成器](cn/prime.md)
- [资源开销](cn/span.md)
- [表达式](cn/expr.md)
- [数据结构](cn/datastruct.md)
- [双向链表](cn/double_linked_list.md)
- [斐波那契堆](cn/fheap.md)
Expand Down
199 changes: 199 additions & 0 deletions docs/book/cn/expr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
## 表达式



这个组件实现了对一种简单的表达式进行解析的功能。表达式所支持的仅有:**变量****常量****函数**

写法如下:

```
abc --这是一个变量
"abc" --这是一个字符串常量
'abc' --这也是字符串常量
1 --整数
1.2 --浮点数
0xa --十六进制整数
0311 --八进制整数
concat(abc, bcd) --这是一个函数,参数有两个,都是变量
concat(abc, "bcd") --这是一个函数,参数有两个,一个是变量,一个是常量
concat(1, "bcd") --两个参数都是常量
concat("abc", concat(bcd, "efg")) --这个例子展示了函数嵌套调用
```



### 头文件

```c
#include "mln_expr.h"
```



### 模块名

`expr`



### 函数

#### mln_expr_val_new

```c
mln_expr_val_t *mln_expr_val_new(mln_expr_typ_t type, void *data);

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_typ_t;

typedef struct {
mln_expr_typ_t type;
struct {
mln_u8_t b;
mln_s64_t i;
double r;
mln_string_t *s;
} data;
} mln_expr_val_t;
```
描述:创建一个表达式值对象。`mln_expr_typ_t`是表达式的类型,`mln_expr_val_t`是值对象的结构。函数`mln_expr_val_new`的第二个参数的类型根据第一个参数不同,会有如下几种:
- `mln_u8_t *`
- `mln_s64_t *`
- `double *`
- `mln_string_t *` 字符串会在函数内使用函数`mln_string_ref`引用该字符串。
返回值:
- 成功:`mln_expr_val_t`指针
- 失败:`NULL`
#### mln_expr_val_free
```c
void mln_expr_val_free(mln_expr_val_t *ev);
```

描述:释放一个表达式值对象。

返回值:无



#### mln_expr_val_dup

```c
void mln_expr_val_dup(mln_expr_val_t *dest, mln_expr_val_t *src);
```
描述:拷贝一个表达式值对象。将`src`的内容拷贝到`dest`中。如果是字符串类型,则会使用函数`mln_string_ref`引用字符串。
返回值:无
#### mln_expr_run
```c
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 *name, int is_func, mln_array_t *args, void *data);
```

描述:运行表达式`exp`。表达式中的变量以及函数(和函数的参数)还有用户自定义数据`data`,都会被传递到回调函数`cb`中进行解析。开发者可以根据需求,定制化这些函数和变量的值。

返回值:

- 成功:`mln_expr_val_t`指针,存放运行结果。
- 失败:`NULL`



### 示例

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

static mln_expr_val_t *var_expr_handler(mln_string_t *name, int is_func, mln_array_t *args, void *data)
{
printf("%p %p %p\n", name, args, data);
if (is_func)
mln_log(none, "%S %d %U %X\n", name, is_func, args->nelts, data);
else
mln_log(none, "%S %d %X\n", name, is_func, data);
return mln_expr_val_new(mln_expr_type_string, name);
}

static mln_expr_val_t *func_expr_handler(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;

if (!is_func)
return mln_expr_val_new(mln_expr_type_string, name);

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);
mln_string_free(s1);

return v;
}

int main(void)
{
mln_string_t var_exp = mln_string("aaa");
mln_string_t func_exp = mln_string("concat('abc', aaa, concat(bcd, 'eee'))");

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;
}
```
执行结果:
```
0xaaaae8d9a210 (nil) (nil)
aaa 0 0
03/18/2024 03:34:58 UTC DEBUG: a.c:main:53: PID:2293415 4 aaa
03/18/2024 03:34:58 UTC DEBUG: a.c:main:61: PID:2293415 4 abcaaabcdeee
```
1 change: 1 addition & 0 deletions docs/book/cn/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Melon当前提供了如下功能:
- 自旋锁
- 素数生成器
- 资源开销
- 表达式
- 数据结构
- 双向链表
- 斐波那契堆
Expand Down
Loading

0 comments on commit e3eaffa

Please sign in to comment.