소스 검색

更新部分描述

myuan 3 년 전
부모
커밋
fe1f061f8a
1개의 변경된 파일39개의 추가작업 그리고 2개의 파일을 삭제
  1. 39 2
      2. 词法分析科学计算器/readme.md

+ 39 - 2
2. 词法分析科学计算器/readme.md

@@ -149,9 +149,46 @@ a + b -> +(a, b)
 ```
 ```
 光写出来构造还是蛮简洁的, 匹配表达式时可以沿着`表达式->加后表达式->因子->函数->表达式`走, 这就是递归下降里的递归含义, 而下降则是指自顶向下慢慢解析. 如果你足够敏锐, 一定能意识到这个流程可能出现无限循环, 这就是左递归问题, 好在上面所提到的数学表达式是LL(1)文法(从左往右每次多看1个词就可以确定究竟是什么), 脑子不糊涂一般不会写出来无限循环. 对于更复杂的情况, 可以上LL(k)解析器, 尽量多看几个. 不过还有一些其他处理方法, 后面再提. 
 光写出来构造还是蛮简洁的, 匹配表达式时可以沿着`表达式->加后表达式->因子->函数->表达式`走, 这就是递归下降里的递归含义, 而下降则是指自顶向下慢慢解析. 如果你足够敏锐, 一定能意识到这个流程可能出现无限循环, 这就是左递归问题, 好在上面所提到的数学表达式是LL(1)文法(从左往右每次多看1个词就可以确定究竟是什么), 脑子不糊涂一般不会写出来无限循环. 对于更复杂的情况, 可以上LL(k)解析器, 尽量多看几个. 不过还有一些其他处理方法, 后面再提. 
 
 
+### 加减乘除分析
+
+将 git 历史切换到 `8259cc94337f4409d6a6fe6e4d17eedcd7685fc4 完成加减的词法分析`, 可以看到我当时的中间过程, 至此程序可以使用递归下降方法来区分加减乘除的优先级, 而不需要像第一节一样手动给出一个表来指定优先级
+
+```
+> 语法分析 1*2*3-4*5*6-7*8/9+10*11*12
+用时 0ms
+根 | 基地址: 7f5250 | 参数数量: 1 | 参数容量: 8 | 参数数组地址: 7f3af0
+  + | 基地址: 7f7e88 | 参数数量: 2 | 参数容量: 8 | 参数数组地址: 7f85c0
+    - | 基地址: 7f76f8 | 参数数量: 2 | 参数容量: 8 | 参数数组地址: 7f7ee0
+      - | 基地址: 7f6f68 | 参数数量: 2 | 参数容量: 8 | 参数数组地址: 7f7750
+        * | 基地址: 7f6ca8 | 参数数量: 2 | 参数容量: 8 | 参数数组地址: 7f6e60
+          * | 基地址: 7f6a98 | 参数数量: 2 | 参数容量: 8 | 参数数组地址: 7f6d00
+            1 | 基地址: 7f6938 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 7f6990
+            2 | 基地址: 7f6b48 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 7f6ba0
+          3 | 基地址: 7f6d58 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 7f6db0
+        * | 基地址: 7f7438 | 参数数量: 2 | 参数容量: 8 | 参数数组地址: 7f75f0
+          * | 基地址: 7f7228 | 参数数量: 2 | 参数容量: 8 | 参数数组地址: 7f7490
+            4 | 基地址: 7f70c8 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 7f7120
+            5 | 基地址: 7f72d8 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 7f7330
+          6 | 基地址: 7f74e8 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 7f7540
+      / | 基地址: 7f7bc8 | 参数数量: 2 | 参数容量: 8 | 参数数组地址: 7f7d80
+        * | 基地址: 7f79b8 | 参数数量: 2 | 参数容量: 8 | 参数数组地址: 7f7c20
+          7 | 基地址: 7f7858 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 7f78b0
+          8 | 基地址: 7f7a68 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 7f7ac0
+        9 | 基地址: 7f7c78 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 7f7cd0
+    * | 基地址: 7f8358 | 参数数量: 2 | 参数容量: 8 | 参数数组地址: 7f8510
+      * | 基地址: 7f8148 | 参数数量: 2 | 参数容量: 8 | 参数数组地址: 7f83b0
+        10 | 基地址: 7f7fe8 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 7f8040
+        11 | 基地址: 7f81f8 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 7f8250
+      12 | 基地址: 7f8408 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 7f8460
+> 
+```
+
+这个输出的阅读方式为: 找到两个相邻的叶结点, 其共同父节点即算符, 如此组成的新节点可以与其相邻节点加上父节点组合. 有没有一点正经语言的感觉了? 
+
+
 ## 其他
 ## 其他
 
 
-细微之处的东西在代码的注释里. 
+细微之处的东西在代码的注释或者调试输出里. 
 
 
 本节代码使用 git 组织, 每一个里程碑我都会创建一个 commit, 你可以通过 git 回溯来分步查看我的编码过程. 如果你不会 git, 可以下载一个 github desktop, 可以直接在 GUI 上看到各个 commit 的内容. 
 本节代码使用 git 组织, 每一个里程碑我都会创建一个 commit, 你可以通过 git 回溯来分步查看我的编码过程. 如果你不会 git, 可以下载一个 github desktop, 可以直接在 GUI 上看到各个 commit 的内容. 
 
 
@@ -163,6 +200,6 @@ a + b -> +(a, b)
 
 
 ## 下节预告
 ## 下节预告
 
 
-本节代码仍然使用纯的易语言做文本分析, 但是如果你详细读了这份代码, 会发现大量的重复, 之后我将使用 JavaScript 的 [peggyjs](https://peggyjs.org/online) 库来重新做这件事, 同时, 如果你认真读了本节代码, 你也可以轻松读懂 peggyjs 的大部分东西. 
+本节代码仍然使用纯的易语言做文本分析, 但是如果你详细读了这份代码, 会发现大量的重复, 之后我将使用 JavaScript 的 [peggyjs](https://peggyjs.org/online) 库来重新做这件事, 同时, 如果你认真读了本节代码, 你也可以轻松读懂 peggyjs 的大部分东西. 为什么用 JavaScript 的库? 因为易语言没人做这种DSL. 另外就是 JavaScript 的话可以放到浏览器上去分析易语言语法啦, 也就有机会运行到浏览器里去了. 那么我现在写的命令行上的分析程序也能上浏览器了. 
 
 
 > *不过严格来说, 正则表达式也是 DSL, 因此用了正则表达式就不算是纯易语言了.*
 > *不过严格来说, 正则表达式也是 DSL, 因此用了正则表达式就不算是纯易语言了.*