|
@@ -0,0 +1,40 @@
|
|
|
+# 词法分析科学计算器
|
|
|
+
|
|
|
+> http://gogs.mkyr.fun:99/myuan/elang
|
|
|
+
|
|
|
+本节的目标是实现包含一些初等函数的计算器, 允许输入的例子如下:
|
|
|
+```
|
|
|
+# 允许以#开始写注释, #到行尾的将被忽略
|
|
|
+
|
|
|
+1 + sin(20°) # 角度制的20度
|
|
|
+2 - cos(π) / 10 # 默认为弧度制, 支持定义常量
|
|
|
+3 * log(10, 100) # 以10为底, 取100的对数
|
|
|
+4 / (2^3 / 4^2) # 当然仍然还有括号可以用
|
|
|
+```
|
|
|
+
|
|
|
+上一节中实现功能时边读入边解析和计算, 如果按照这样的逻辑完成本节的目标, 代码将会冗长又固执, 难以阅读和修改. 本节的代码清晰地分为了两个部分:
|
|
|
+
|
|
|
+1. 词法分析, 将文本拆成不同的词单元, 这里靠正则表达式拆
|
|
|
+2. 语法分析, 根据不同的模式分析语法生成语法树, 上文中语法大致可以分为
|
|
|
+2.1 a + b 中缀表达式
|
|
|
+2.2 f(a, b, c) 函数调用式
|
|
|
+2.3 a * (b + c) / (f(a) + 2) 带括号的前二者
|
|
|
+3. 解释执行语法树中的内容
|
|
|
+
|
|
|
+更详细的内容都在代码的注释里.
|
|
|
+
|
|
|
+本节代码仍然使用纯的易语言做文本分析, 但是如果你详细读了这份代码, 会发现大量的重复, 之后我将使用 JavaScript 的 [peggyjs](https://peggyjs.org/online) 库来重新做这件事, 同时, 如果你认真读了本节代码, 你也可以轻松读懂 peggyjs 的大部分东西.
|
|
|
+
|
|
|
+> *不过严格来说, 正则表达式也是 DSL, 因此用了正则表达式就不算是纯易语言了.*
|
|
|
+
|
|
|
+本节代码使用 git 组织, 每一个里程碑我都会创建一个 commit, 你可以通过 git 回溯来分步查看我的编码过程. 如果你不会 git, 可以下载一个 github desktop, 可以直接在 GUI 上看到各个 commit 的内容.
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+额外阅读:
|
|
|
+- 正则表达式
|
|
|
+- - https://regex101.com/
|
|
|
+- - https://www.runoob.com/regexp/regexp-syntax.html
|
|
|
+- 递归下降器
|
|
|
+- - https://zhuanlan.zhihu.com/p/31271879
|
|
|
+- - https://zh.wikipedia.org/wiki/%E9%80%92%E5%BD%92%E4%B8%8B%E9%99%8D%E8%A7%A3%E6%9E%90%E5%99%A8
|