C语言实现轻量级表达式

本文介绍开源C语言库Melon表达式组件,该组件实现了一个轻量级表达式,允许开发者定制化属于自己的专属变量和函数解析器。该模块可以用于文本模板内容替换以及一些简单的指令模式编程场景。

下面是该组件支持的语法:

abc   --这是一个变量
"abc" --这是一个字符串常量
'abc' --这也是字符串常量
1     --整数
1.2   --浮点数
0xa   --十六进制整数
0311  --八进制整数

concat(abc, bcd) --这是一个函数,参数有两个,都是变量
concat(abc, "bcd") --这是一个函数,参数有两个,一个是变量,一个是常量
concat(1, "bcd") --两个参数都是常量
concat("abc", concat(bcd, "efg")) --这个例子展示了函数嵌套调用
concat("abc", concat(bcd, "efg")) aaa concat("bcd", concat(efg, "hij")) --这个例子展示运行多个表达式

简单来说,表达式语法支持三种类型内容:

  • 常量
  • 变量
  • 函数

并且函数支持嵌套调用。

此外,可以一次执行多个表达式,所有表达式的执行结果为最后一个表达式的结果。

我们分别对着三种类型分别说明:

常量

这个比较好理解,就是字面量,主要支持:字符串、整数和浮点数。其中,整数支持十进制写法、八进制写法和十六进制写法。

变量

变量顾名思义,就是其值可变。但由于表达式比较简单,且应用场景与常规编程语言不同,因此不是通过=来进行赋值的,而是通过回调函数,由使用者决定该返回何值作为该变量的值。

函数

与变量一样,函数的行为完全由回调函数决定,也就是说由使用者自行定制。

例子

我们看一个示例

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

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, 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 func_exp = mln_string("concat('abc', concat(aaa, 'bbb')) ccc concat('eee', concat(bbb, 'fff'))");

    mln_expr_val_t *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;
}

这是一个综合一点的例子,这个例子中包含了函数嵌套调用、变量、多表达式执行。

表达式中的变量和函数都由func_expr_handler这个回调函数来解析。对于变量,回调函数直接返回变量的名字作为变量的值。而对于函数,回调函数则是将函数参数拼接成一个字符串作为函数的返回值。

由于本例中存在三个表达式:

  • concat('abc', concat(aaa, 'bbb'))
  • ccc
  • concat('eee', concat(bbb, 'fff'))

前面我们说到过,mln_expr_run的返回值是最后一个表达式的值,所以最终终端的输出就是:

eeebbbfff

也正如这个例子所示,表达式组件只是提供了一种对文本格式的规范,而具体有哪些函数和变量都完全交给回调函数来决定,也就是交给了使用者决定。并且这个组件并不像完整的编程语言那样功能繁重,因此比较适合一些小型功能整合或者模板替换之类的场景。

模板替换可以参考web前端的那些模板,例如:twig、mustache等。

小功能整合举个例子,例如在对某种网络通信中,我们需要对报文提取某些字段,然后对字段处理,然后再做验证。那么提取、处理、验证就可以被封装成三个函数。这三个函数是三种行为,而不是策略。我们可以将这三种行为应设成表达式组件中的三个函数,然后我们就可以通过对这三个函数的组合应用来实现策略。对于策略的改变,我们并不需要修改C代码,只需要将策略的文本内容(也就是这些表达式)做一些修改即可。

感谢阅读!

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码哥比特

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值