前言
最近又在重新学习编译原理了,其实两年前也温习过,当初是为了能实现通过 MySQL
的 DDL
生成 Python
中 sqlalchemy
的 model
。
相干文章在这里:手写一个词法分析器
尽管实现了相干性能,但当初看来其实实现的比拟糙的,而且也只使用到了词法剖析;所以这次我的目标是能够通过词法剖析 -> 语法分析 -> 语义剖析 最终能实现一个功能完善的脚本 ” 语言 ”。
成果
当初也有了一些阶段性的成绩,如下图所示:
目前具备以下基本功能:
- 变量申明与赋值(只反对 int)
- 二次运算(优先级反对)
- 语法查看
- debug 模式,能够打印 AST
感兴趣的敌人能够在这里查看源码:
https://github.com/crossoverJie/gscript
本地有 go 环境的话也能够装置运行。
go get github.com/crossoverJie/gscript
gscript -h
或者间接下载二进制文件运行:https://github.com/crossoverJie/gscript/releases
实现
以后版本是应用 go 编写的,的确也如题目所说,外围代码还不到 1k 行代码,当然这也和目前性能简陋无关。
不过麻雀虽小五脏俱全,从以后版本还是使用到了编译原理中的局部常识:词法、语法分析。
根本实现流程如上图:
- 通过词法分析器将源码中解析出 token
-
再通过对 token 推导生成出形象语法树(AST)
- 如果语法语法呈现谬误,这一步骤便会抛出编译失败,比方
2*(1+
少了一个括号。
- 如果语法语法呈现谬误,这一步骤便会抛出编译失败,比方
因为没有应用相似于 ANTLR
这样工具来辅助生成代码(不然性能也不会只有这么点),所以其中的词法、语法分析都是手写的,代码量并不大,对于想要调试的敌人能够间接查看源码。
词法分析器:token/token.go:39
语法分析器:syntax/syntax.go
其中会波及到一些概念,比方无限状态机、递归降落算法等知识点就没在本文探讨了,后续这个我的项目性能更加欠缺后也会重头整顿。
布局
最初是画饼阶段了,不出意外后续会持续新增如下性能:
- 更多的根底类型,string/long 之类的。
- 变量作用域、函数。
- 甚至是闭包。
- OOP 必定也少不了。
这些个性都实现后那也算是一个 ” 古代 ” 的脚本语言了,后续我也会持续更新学习和实现过程中的乏味内容。
源码地址:
https://github.com/crossoverJie/gscript