Browse Source

递归下降器完结

myuan 3 years ago
parent
commit
4a689e6e24

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

@@ -150,8 +150,7 @@ a + b -> +(a, b)
 ```
 内存结构如图: ![内存结构图](./static/memory-struct.png)
 
-
-终于可以开始写递归下降器了. 
+> 这部分大概花了我三四个小时去写和 debug, 跟写汇编有一拼了. 终于可以开始写递归下降器了. 
 
 ## 递归下降
 我不觉得我谈论递归下降能比网上的其他教程更好, 随便找了两个参考链接. 
@@ -217,12 +216,46 @@ a + b -> +(a, b)
 
 将 git 历史切换到 `55e0ea657e8b5f789574a1888415477901b32fdd 添加括号处理`, 可以发现只写了寥寥几新行, 就完成了括号的处理, 而且非常符合直觉. 
 
+### 递归下降器完结
+
+```
+> 语法分析 1 -( sin(2222, 4444, tan(5555) + arctan(6666)) - cos(3333) )* 4
+
+用时 1ms
+根 | 基地址: 62bf68 | 参数数量: 1 | 参数容量: 8 | 参数数组地址: 62c548
+  - | 基地址: 62d880 | 参数数量: 2 | 参数容量: 8 | 参数数组地址: 632e28
+    1 | 基地址: 62c480 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 62cf98
+    * | 基地址: 632bc0 | 参数数量: 2 | 参数容量: 8 | 参数数组地址: 632d78
+      括号 | 基地址: 62c3e8 | 参数数量: 1 | 参数容量: 8 | 参数数组地址: 632b68
+        - | 基地址: 6308d0 | 参数数量: 2 | 参数容量: 8 | 参数数组地址: 632ab8
+          sin | 基地址: 630ae0 | 参数数量: 3 | 参数容量: 8 | 参数数组地址: 630b38
+            2222 | 基地址: 630f90 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 630fe8
+            4444 | 基地址: 631320 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 631378
+            + | 基地址: 631610 | 参数数量: 2 | 参数容量: 8 | 参数数组地址: 631dd8
+              tan | 基地址: 631770 | 参数数量: 1 | 参数容量: 8 | 参数数组地址: 6317c8
+                5555 | 基地址: 631c20 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 631c78
+              arctan | 基地址: 631f30 | 参数数量: 1 | 参数容量: 8 | 参数数组地址: 631f88
+                6666 | 基地址: 6323e0 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 632438
+          cos | 基地址: 632540 | 参数数量: 1 | 参数容量: 8 | 参数数组地址: 632598
+            3333 | 基地址: 632900 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 632958
+      4 | 基地址: 632c70 | 参数数量: 0 | 参数容量: 8 | 参数数组地址: 632cc8
+
+```
+
+## 鸣谢
+
+感谢 e2txt 工具, 使得我可以按纯文本保存代码, 添入版本控制
+
 
 ## 其他
 
+本节代码使用 git 组织, 每一个里程碑我都会创建一个 commit, 你可以通过 git 回溯来分步查看我的编码过程. 如果你不会 git, 可以下载一个 github desktop, 可以直接在 GUI 上看到各个 commit 的内容. 
+
 细微之处的东西在代码的注释或者调试输出里. 
 
-本节代码使用 git 组织, 每一个里程碑我都会创建一个 commit, 你可以通过 git 回溯来分步查看我的编码过程. 如果你不会 git, 可以下载一个 github desktop, 可以直接在 GUI 上看到各个 commit 的内容. 
+在 e2txt 工具的关于里我发现了一段「易语言源码及内部关系极其复杂,代码的生成过程跟编译器类似。由于易语言不具备面向对象的特性,所以本项目开发过程中耗费了大量的精力处理语法树和对象关系的维护。」, 同是天涯沦落人, 为了表达语法树我也自己手动控制内存搞了一大堆事情. 
+
+本文是边写代码边写的, 中间可能有些地方改了代码但是并没有反应到文本里, 如果你发现了问题, 请指出. 
 
 ### 额外阅读
 - 正则表达式 

BIN
2. 词法分析科学计算器/词法分析科学计算器.e


BIN
2. 词法分析科学计算器/词法分析科学计算器.代码/代码.e


+ 2 - 40
2. 词法分析科学计算器/词法分析科学计算器.代码/代码/程序集1.static.e.txt

@@ -2,46 +2,8 @@
 
 .程序集 程序集1
 .子程序 _启动子程序, 整数型, , 本子程序在程序启动后最先执行
-    .局部变量 a, 抽象语法树节点
-    .局部变量 b, 抽象语法树节点
-
-    .局部变量 迭代次数, 整数型
-    .局部变量 i, 整数型
-
-    .局部变量 词, 词, , "0"
-
-    .计次循环首 (0, )
-        
-        a.初始化内存 (“sincos67890123456”)
-        
-        ' 调试输出 (“a初始生成展示文本”, a.生成展示文本 ())
-        
-        迭代次数 = 17
-        .计次循环首 (迭代次数, i)
-            ' 调试输出 (“准备初始化”)
-            b.初始化内存 (到文本 (i) + 到文本 (i) + 到文本 (i) + 到文本 (i) + 到文本 (i) + 到文本 (i) + 到文本 (i))
-            ' 调试输出 (“准备把b添加到a子节点”, b.生成展示文本 ())
-            ' 调试输出 (“准备把b添加到a子节点”)
-            a.插入参数节点 (b)
-            ' 调试输出 (“添加到a子节点”)
-            
-        .计次循环尾 ()
-        
-        ' 调试输出 (“a添加节点展示文本”, a.生成展示文本 ())
-        .计次循环首 (迭代次数, i)
-            a.获取参数节点 (i).生成展示文本 ()
-            ' 调试输出 (“a的子节点展示文本”, i, a.获取参数节点 (i).生成展示文本 ())
-        .计次循环尾 ()
-        .计次循环首 (迭代次数, i)
-            a.获取参数节点 (i).释放结构内存 ()
-        .计次循环尾 ()
-        a.释放结构内存 ()
-        
-    .计次循环尾 ()
-    
-    语法分析并输出 (“1 -( sin(2222) - cos(3333) )* 4”)
-    
-    语法分析并输出 (“2*3-1*4+5/6-7”)
+    语法分析并输出 (“1 -( sin(2222, 4444, tan(5555) + arctan(6666)) - cos(3333) )* 4”)
+    语法分析并输出 (“2*3-1*4+5/6-7*time()”)
     
     .判断循环首 (真)
         标准输出 (, “> ”)

+ 29 - 3
2. 词法分析科学计算器/词法分析科学计算器.代码/代码/语法分析程序集.static.e.txt

@@ -224,6 +224,8 @@
     .局部变量 当前节点, 抽象语法树节点
     .局部变量 标识符, 抽象语法树节点
     .局部变量 参数, 抽象语法树节点
+    .局部变量 右侧无穷, 抽象语法树节点
+    .局部变量 括号内下一表达式, 抽象语法树节点
 
     .如果真 (下个词 ().类型 ≠ #词类_标识符)
         返回 (父节点.生成匹配失败节点 ())
@@ -234,15 +236,39 @@
         返回 (父节点.生成匹配失败节点 ())
     .如果真结束
     词游标自增 ()
+    .如果真 (下个词 ().内容 = “)”)
+        词游标自增 ()
+        返回 (标识符)
+    .如果真结束
     
-    参数 = 匹配数字 ()
+    参数 = 匹配表达式 (当前节点)
     
-    .如果真 (下个词 ().内容 ≠ “)”)
+    .如果真 (下个词 ().内容 = “)”)
+        标识符.添加参数节点 (参数)
+        词游标自增 ()
+        
+        返回 (标识符)
         返回 (父节点.生成匹配失败节点 ())
     .如果真结束
     标识符.添加参数节点 (参数)
-    词游标自增 ()
     
+    .判断循环首 (真)
+        .如果真 (下个词 ().类型 ≠ #词类_逗号)
+            返回 (父节点.生成匹配失败节点 ())
+        .如果真结束
+        词游标自增 ()
+        括号内下一表达式 = 匹配表达式 (当前节点)
+        .如果真 (括号内下一表达式.失败 ())
+            返回 (父节点.生成匹配失败节点 ())
+        .如果真结束
+        标识符.添加参数节点 (括号内下一表达式)
+        
+        .如果真 (下个词 ().内容 = “)”)
+            词游标自增 ()
+            跳出循环 ()
+        .如果真结束
+        
+    .判断循环尾 ()
     返回 (标识符)