手写编程语言-实现运算符重载
前言
先带来日常的 GScript 更新:新增了可变参数的特性,语法如下:
1 | int add(string s, int ...num){ |
先带来日常的 GScript 更新:新增了可变参数的特性,语法如下:
1 | int add(string s, int ...num){ |
在上一篇《终于实现了一门属于自己的编程语言》 介绍了自己写的编程语言 GScript ,在文中提到希望最终可以使用 GScript
开发一个网站。
到目前为止确实是做到了,首页地址:
https://gscript.crossoverjie.top/index
要称为一个网站确实有点勉强,不过也是一个动态网页,因为返回的是 HTML
,所以在当前阶段只要不嫌麻烦其实也能写一个“合格”的网站,有点像以前我们学习 Java
时的 servlet
。
都说程序员的三大浪漫是:操作系统、编译原理、图形学;最后的图形学确实是特定的专业领域,我们几乎接触不到,所以对我来说换成网络更合适一些,最后再加上一个数据库。
这四项技术如果都能掌握的话那岂不是在 IT 行业横着走了,加上这几年互联网行业越来越不景气,越底层的技术就越不可能被替代;所以为了给自己的 30+ 危机留点出路,从今年上半年开始我就逐渐开始从头学习编译原理。
功夫不负有心人,经过近一个月的挑灯夜战,每晚都在老婆的催促下才休息,克服了中途好几次想放弃的冲动,终于现在完成了 GScript 一个预览版。
预览版的意思是语法结构与整体设计基本完成,后续更新也不太会改动这部分内容、但还缺少一些易用功能。
上次利用 Antlr 重构一版 用 Antlr 重构脚本解释器 之后便着手新增其他功能,也就是现在看到的支持了作用域以及函数调用。
1 | int b= 10; |
在上一个版本实现的脚本解释器 GScript 中实现了基本的四则运算以及 AST
的生成。
当我准备再新增一个 %
取模的运算符时,会发现工作很繁琐而且几乎都是重复的;主要是两步:
%
符号的支持。%
token 实现具体逻辑。其中的词法解析和遍历 AST 完全是重复工作,所以我们可否能够简化这两步呢?
最近在持续优化之前编写的 JSON
解析库 xjson,主要是两个方面的优化。
第一个是支持将一个 JSONObject
对象输出为 JSON
字符串。
这点在上个版本中只是利用自带的 Print
函数打印数据:
1 | func TestJson4(t *testing.T) { |
Output:
1 | map[name:map[first:bob]] |
在日常使用 Goland
时,团队收集了一些可以帮助我们专注于创造的同时减少重复工作的小技巧。
如果你是在 IDEA
中使用的 Go
插件,或者其他 IntelliJ
的产品,同样也有这些特性。
在之前实现的 JSON
解析器中当时只实现了将一个 JSON 字符串转换为一个 JSONObject
,并没有将其映射为一个具体的 struct
;如果想要获取值就需要先做断言将其转换为 map
或者是切片再来获,会比较麻烦。
1 | decode, err := xjson.Decode(`{"glossary":{"title":"example glossary","age":1}}`) |
但其实转念一想,部分场景我们甚至我们只需要拿到 JSON
中的某个字段的值,这样还需要先声明一个 struct
会略显麻烦。
经过查询发现已经有了一个类似的库来解决该问题,https://github.com/tidwall/xjson 并且 star 数还很多(甚至名字都是一样的😂),说明这样的需求大家还是很强烈的。
于是我也打算增加类似的功能,使用方式如下:
之前在写 gscript时我就在想有没有利用编译原理实现一个更实际工具?毕竟真写一个语言的难度不低,并且也很难真的应用起来。
一次无意间看到有人提起 JSON
解析器,这类工具充斥着我们的日常开发,运用非常广泛。
以前我也有思考过它是如何实现的,过程中一旦和编译原理扯上关系就不由自主的劝退了;但经过这段时间的实践我发现实现一个 JSON
解析器似乎也不困难,只是运用到了编译原理前端的部分知识就完全足够了。
得益于 JSON
的轻量级,同时语法也很简单,所以核心代码大概只用了 800 行便实现了一个语法完善的 JSON
解析器。