美文网首页
Go语言解析文本表达式,自制编程语言

Go语言解析文本表达式,自制编程语言

作者: 城_d073 | 来源:发表于2022-11-02 17:21 被阅读0次

    其实我的目标是将这个库变成一个解释型编程语言,而不单纯只是做算术表达式运算,那样子用途其实不大。现在我已经实现了很多特性了,比如变量赋值,函数,比较运算符、算术表达式等等。

    网络上有个别关于go语言动态解析一些表达式的库,我之前用过,但感觉功能很少,比如没有支持 && 和 || 这类符号,也没有支持比较运算符(> < >= <= )这一类, 所以我自己写了一个。

    如果是使用go语言并且有这方面需要的话,完全可以直接引入这个库用于算术表达式。

    https://github.com/pywee/lit
    有兴趣的朋友记得 star 我一下

    使用方法,直接引入就能用:

    import "github.com/pywee/lit"
    exprs := []byte(`
            a = (2 + 100 ^ 2 - (10*1.1 - 22 + (22 | 11))) / 10 * 2;
            b = 12 / 333 + 31 + (5 / 10) - 6 | 100;
            print(a); 
            print(b); 
        `)
        _, err = lit.NewExpr(exprs)
        
    // 最终输出 16 和 125 与 原生go语言是一样的
    

    支持弱类型处理,这方面我参考了 php 和 js

    src := []byte(`
            a = true - 1;
            b = isInt(1);
            c = isFloat(1);
            d = false == 0.0;
            e = "false" == 0.0;
            print(a); // 0
            print(b); // true
            print(c); // true
            print(d); // true
            print(e); // true
        `)
        _, err := lit.NewExpr(src)
    

    当前已支持的特性

    一、变量 (声明、赋值、拼接、参与算术计算)
    二、算术表达式
    三、弱类型
    四、关系运算符 [> < >= <= != == ===]
    五、逻辑运算符 [&& ||]
    六、内置函数 (试验阶段)
    七、自定义函数 (试验阶段)


    将在后期支持的特性

    一、if 句子
    二、数组
    三、for 循环
    四、对象或结构体
    五、递归


    使用方法

    go get github.com/pywee/lit
    

    一、变量声明

    import "github.com/pywee/lit"
    
    func main() {
        // 执行以下句子,最终会输出
        src := []byte(`
            a = 123;
            b = a + 456;
            print(b); // 579
        `)
        _, err := lit.NewExpr(src)
    }
    
    

    二、算术表达式的计算。算术符号的优先级保持与 Go 语言相同。请看示例:

        // 不同的语言符号优先级是不完全一样的,Lit 的算术符号优先级保持与 Golang 一致
        // 首先我们执行 Go 语言原生函数进行数学表达式计算
        // 以下句子最终会输出 
        // +1.600000e+001
        // 125
        println((2 + 100 ^ 2 - (10*1.1 - 22 + (22 | 11))) / 10 * 2)
        println(12/333+31+(5/10)-6|100)
    
        // 使用 Lit 计算文本中的数据
        // 表达式文本
        // 执行下面的句子 最终会输出
        exprs := []byte(`
            a = (2 + 100 ^ 2 - (10*1.1 - 22 + (22 | 11))) / 10 * 2;
            b = 12 / 333 + 31 + (5 / 10) - 6 | 100;
            print(a); // 16
            print(b); // 125
        `)
        _, err = lit.NewExpr(exprs)
    
        // *** 同样的表达式放在 PHP 中,会输出 -24 ***
    
    

    三、当前已支持部分常用内置函数(测试阶段),更多的内置函数将在接下来继续完成

    
        // 下面的句子调用了两个函数 
        // IsInt(arg) 用来检查 arg 是否为整型 
        // Replace(arg1, arg2, arg3, arg4) 用来做字符串替换
    
        // 执行下面语句 最终会输出
         exprs := []byte(`
            a = replace("hello word111", "1", "", 2-isInt((1+(1 + isInt(123+(1+2)))-1)+2)-2);
            varDump(a); // STRING hello word
        `)
        _, err = lit.NewExpr(exprs)
    
    

    四、弱类型转换。弱类型的特性我把它设计为与 PHP 基本一样

        // 当布尔值参与运算时,底层会将 true 转为 1, false 转为 0
        // 执行下面句子 将输出
        src := []byte(`
            a = true - 1;
            b = isInt(1);
            c = isFloat(1);
            d = false == 0.0;
            e = "false" == 0.0;
            print(a); // 0
            print(b); // true
            print(c); // true
            print(d); // true
            print(e); // true
        `)
        _, err := lit.NewExpr(src)
    
    
        // 与其他弱类型语言一样
        // 字符串数字与整型相操作,在 Lit 的底层会将字符串数字转换为整型
        // 执行下面句子 将输出
        src := []byte(`
            a = "1" - 1;
            b =  0.0 >= false+1 || (1<=21 && 1==1);
            print(a); // 0
            print(b); // true
        `)
        _, err := lit.NewExpr(src)
    
    
        // 与其他弱类型语言一样
        // 字符串数字与整型相操作,在 Lit 的底层会将字符串数字转换为整型
        // 执行下面句子 将输出
        src := []byte(`
            a = "1" - 1;
            print(a); // 0
        `)
        _, err := lit.NewExpr(src)
    
    
        // 字符串与字符串相加时 将进行字符串的拼接
        // 执行以下句子,将会输出
        src := []byte(`
            a = "abc" + "def";
            print(a); // abcdef
        `)
        _, err := lit.NewExpr(src)
    
    
        // 但如果当两个字符串都为数字时 对他们进行相加 则会被底层转换为数字
        // 执行如下句子,将会输出
         src := []byte(`
            a = "123" + "456";
            print(a); // 579
        `)
        _, err := lit.NewExpr(src)
    
    
        // 其他字符串+整型将会报错
        // 执行如下句子
        src := []byte(`
            a = "abcwwww1230"+0.01;
            print(a); // 报错
        `)
        _, err := lit.NewExpr(src)
    

    五、"并且" 与 "或者" 符号处理

        // 执行如下句子,将会输出
        src := []byte(`
            a = isInt(1) && 72+(11-2) || 1-false;
            varDump(a); // BOOL true
        `)
        _, err := lit.NewExpr(src)
    
    

    六、自定义函数处理 (迭代中)

        // 执行如下句子,将会输出
        // 8 123
        src := []byte(`
            a = "123";
            func demo(b = 10, m = "2") {
                print(b - m, a);
            }
            demo(); // 8 123
        `)
        _, err := lit.NewExpr(src)
    
    
        // 执行如下句子,将会输出
        src := []byte(`
            func demo(a) {
                b = 10;
                return a+1+b;
            }
    
            a = demo(9);
            print(a); // 20
            print(b); // 找不到变量
        `)
        _, err := lit.NewExpr(src)
    
        // 指定形参默认数据
        // 执行如下句子,将会输出
        src := []byte(`
            func demo(a, b = 10) {
                return a+1+b;
            }
    
            a = demo(9);
            print(a); // 20
            print(b); // 找不到变量
        `)
        _, err := lit.NewExpr(src)
    
    

    请注意,Lit 的算术符号优先级向 Golang 看齐。每个语言对算术符号的优先级处理都有一定区别,如,针对以下表达式进行计算时:

    // 2 + 100 ^ 2 - (10*1.1 - 22 + (22 | 11)) / 10 * 2
    // PHP 输出 -104
    // Node.js 输出 -104
    // Golang 输出 96
    // Lit 输出 96
    

    Lit 算术符号优先级

    第一级 () && ||

    第二级 > < >= <= == != ===

    第三级 * / %

    第四级 | &

    第五级 + - ^


    当前支持的内置函数有如下,更多函数将会在逐步补充 (当前仍然存在bug)

        // 通用处理函数
        print
        varDump
    
        // 字符串处理函数
        // 函数的命名基本参考了 Go 语言
        // 除了个别函数有差别,如 
        // utf8Len 用于检测字符串字数的函数
        // isNumeric 用于判断当前输入是否为数字
        trim
        trimLeft
        trimRight
        trimSpace
        len
        utf8Len
        md5
        replace
        contains
        index
        lastIndex
        toLower
        toUpper
        toTitle
        repeat
    
        // 其他函数
        isNumeric
        isBool
        isInt
        isFloat
    

    相关文章

      网友评论

          本文标题:Go语言解析文本表达式,自制编程语言

          本文链接:https://www.haomeiwen.com/subject/skijtdtx.html