基于 go 语言编写的编程语言 动态解析文本表达式

golangprm · · 1454 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

一直都想写一个解释型的编程语言,之前我用过几年 php,感觉比较杂乱。有些地方很不严谨。所以最近一个月,我在业余时间利用 go 语言写了一个我心目中比较理想的语言。 现在只是开端,不过已经完成了一部分特性,包括解析<b>算术表达式、变量声明、内置函数、自定义函数,弱类型处理</b>。下一步准备到 if 语句了,其中最难的还是算术表达式的实现,我原本只想写一个用来动态解析算术表达式的包,写着写着就慢慢扩展出更多东西了。 其实解析文本,把它以编程语言方式来处理的逻辑,归根结底就是要做各种递归,而且要非常准确地在递归中传递上下文。 这个项目目前我命名为 Lit,希望它能真正为我所用,也希望能真正让人们用起来。 --- #### 目前已经实现的功能 一、变量 (声明、赋值、拼接、参与算术计算) 二、完整的算术表达式 [+ - * / & | ^ %] 三、弱类型 四、关系运算符 [> < >= <= != == ===] 五、逻辑运算符 [&& ||] 六、内置函数 七、自定义函数 --- #### 下一步要实现的是 一、if else 语句 二、数组 三、for 四、对象或结构体 (从中选择其一实现 会参考golang) 五、递归 六、基础的动态库 (如 tcp/http/mysql等) 七、异常处理 我最近每天都在开发中,不知道最后能实现到哪一步,这是一个比较漫长的阶段。 https://github.com/pywee/lit 附上一些使用方法: --- ``` go get github.com/pywee/lit ``` **一、变量声明** ```golang import "github.com/pywee/lit" func main() { // 执行以下句子,最终会输出 src := []byte(` a = 123; b = a + 456; print(b + 1); // 580 `) _, err := lit.NewExpr(src) } ``` --- **二、算术表达式的计算。算术符号的优先级保持与 Go 语言相同。示例:** ```golang // 不同的语言符号优先级是不完全一样的,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 *** ``` --- **三、当前已支持部分常用内置函数(测试阶段),更多的内置函数将在接下来继续完成** ```golang // 下面的句子调用了两个函数 // 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 基本一样** ```golang // 当布尔值参与运算时,底层会将 true 转为 1, false 转为 0 // 执行下面句子 将输出 src := []byte(` a = true - 1; b = isInt(1); c = isFloat(1.0); 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) exprs := []byte(` a = false; b = true; c = "123"; d = 456; print(a + b); // 1 print(a >= b); // false print(a + b + c + d); // 580 `) _, 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) // 在 php 里面,执行上面的句子不但不会报错,还会将字符串 "abcwwww1230" 中的 1230 单独提取出来 // 并且还会将 1230 转换成整型与后面的 0.01 进行计算 // 我不太清楚支持这种操作的目的是什么,个人感觉,这显然没有一点点运用场景 // 所以在 Lit 里面 不允许这样操作 既损耗效率又没有一点点意义 ``` --- **五、"并且" 与 "或者" 符号处理** ```golang // 执行如下句子,将会输出 src := []byte(` a = isInt(1) && 72+(11-2) || 1-false; varDump(a); // BOOL true `) _, err := lit.NewExpr(src) ``` --- **六、自定义函数处理 (试验阶段)** ```golang // 执行如下句子,将会输出 // 8 123 src := []byte(` a = "123"; func demo(b = 10, m = "2") { print(b - m, a); } demo(); // 8 123 `) _, err := lit.NewExpr(src) // 执行如下句子,将会输出 6 src := []byte(` func a() { return 1; } func b() { return a() + 2; } print(b()+3); // 6 `) _, 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 语言原生的一些高级特性,例如 管道、协程 这些可轻松实现异步操作的特性,Lit 会有更多扩展空间,它会比 php 更灵活、更小巧。 ##### 敬请期待... https://github.com/pywee/lit

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1454 次点击  ∙  2 赞  
加入收藏 微博
1 回复  |  直到 2022-11-03 00:01:19
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传