myuan 2 years ago
parent
commit
f664095ea8
19 changed files with 1589 additions and 0 deletions
  1. 30 0
      4. 抽象语法树编译到 llvm/code-examples.ve
  2. 31 0
      4. 抽象语法树编译到 llvm/readme.md
  3. BIN
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.e
  4. 10 0
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/DLL.e.txt
  5. BIN
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/代码.e
  6. 322 0
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/代码/即时解释虚拟机.static.e.txt
  7. 377 0
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/代码/抽象语法树节点.class.e.txt
  8. 6 0
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/代码/排序.list.txt
  9. 32 0
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/代码/来自精易模块.static.e.txt
  10. 66 0
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/代码/程序集1.static.e.txt
  11. 103 0
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/代码/词法分析程序集.static.e.txt
  12. 442 0
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/代码/语法分析程序集.static.e.txt
  13. 45 0
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/常量.e.txt
  14. 11 0
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/自定义类型.e.txt
  15. 12 0
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/资源/命令行帮助.txt
  16. 50 0
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/配置/支持库.config.json
  17. 23 0
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/配置/用户.config.json
  18. 13 0
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/配置/系统.config.json
  19. 16 0
      4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/项目.etprj

+ 30 - 0
4. 抽象语法树编译到 llvm/code-examples.ve

@@ -0,0 +1,30 @@
+# 这是示例代码
+# 注释的长度受限, /笑
+
+output(output(1 + 2 * 3 / 4))     # 首先输出`1+2*3/4`为2.5, 之后再输出`2.5`作为输出的长度为3
+
+f(0) = 0             # 定义函数
+f(x) = x + f(x - 1)  # 函数可以同名, 之后会自动重载决议
+f(x, y) = x + y      # 多个参数也没问题
+
+output(f(10))        # f(10) = 10 + f(9) = 10 + 9 + f(8) = ... = 10+9+8+7+...+1+0 = 55
+output(f(1, 2))      # f(1, 2) = 1 + 2 = 3
+
+
+fib(1) = 1                        # 经典斐波那契数列定义
+fib(2) = 1                        # 经典斐波那契数列定义
+fib(x) = fib(x - 1) + fib(x - 2)  # 经典斐波那契数列定义
+output(fib(20))                   # 不用查表了, 这个值是正确的
+
+exp(x, 0) = 1                   # 递归求幂
+exp(x, y) = exp(x, y - 1) * x   # 递归求幂
+square(x) = exp(x, 2)           # 嵌套函数调用, 定义平方函数
+
+output(exp(2, square(2)))       # 2^(2^2)
+
+
+sqrt(x) = sqrt(x, x / 2, 1, 10) # 奇妙的递归求平方根方法, 精度超高, 收敛超快
+sqrt(x, s, y, 0) = s
+sqrt(x, s, y, n) = sqrt(x, (s + y) / 2, x / ((s + y) / 2), n - 1)
+
+output(sqrt(2), square(sqrt(2)))

+ 31 - 0
4. 抽象语法树编译到 llvm/readme.md

@@ -0,0 +1,31 @@
+# 抽象语法树编译到 llvm
+
+> 上一节: https://bbs.125.la/thread-14706398-1-1.html
+> 源代码 git: http://gogs.mkyr.fun:99/myuan/elang
+
+
+## 目标
+
+本节的目标是把上一节的「语言」编译到 llvm, 不过要想简单快捷地生成 llvm IR, 官方的方案是 C++, 也有一些其他语言的绑定, 比如 Python/Julia, 总而言之, 这一节把 AST 用易语言输出出去后, 就不得不远离易语言了. 
+
+另外还有一个选项是 binaryen, 如果是 binaryen IR 的话, 倒还可以用易语言手写生成, 但是 binaryen 最终是运行在 wasm 上的, 不直接原生运行的话, 就代表着无法简单使用操作系统 API, 以及与已有的易语言生态相容. 
+
+
+## 未来
+
+与其他方案对比后, 如果 llvm 的效果很好, 接下来就可以着手
+
+0. 使用 Antla 的易语言解析器
+1. 使用易语言编写的易语言语法扩展工具
+2. 使用扩展后的易语言书写语法扩展工具
+3. 交替使用流程1/2得到的新易语言, 这里称之为 nelang
+4. 使用 nelang, 书写生成 nelang 在 llvm IR 的工具
+5. 使用以 llvm 编译后的静态文件将 nelang AST 生成 llvm IR
+6. 使用 nelang 补全 nelang 的标准库
+7. 至此 nelang 可以脱离原版易语言, 实现自举, 得益于 llvm, 现在 nelang 可以运行在三大系统, 多种架构了. 
+
+这个科学计算器语言就告一段落了, 到现在我还没有给它起一个名字(
+
+### 可以从本节到达的其他方向
+
+读过这四篇之后, 你应该可以很简单地把易语言子集静态编译出去了, 如果你感兴趣的话, 不如来试试? 

BIN
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.e


+ 10 - 0
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/DLL.e.txt

@@ -0,0 +1,10 @@
+.版本 2
+
+.DLL命令 GetSystemTimeAsFileTime, 整数型, "kernel32.dll", "GetSystemTimeAsFileTime", , 获取当前系统时间
+    .参数 lpSystemTimeAsFileTime, 整数型, , 指向一个用于装载系统时间的 FILETIME 结构
+
+.DLL命令 lstrcpyn_长整数型, 整数型, "kernel32.dll", "lstrcpyn", 公开
+    .参数 目标, 长整数型, 传址
+    .参数 源, 长整数型, 传址
+    .参数 长度, 整数型
+

BIN
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/代码.e


+ 322 - 0
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/代码/即时解释虚拟机.static.e.txt

@@ -0,0 +1,322 @@
+.版本 2
+.支持库 spec
+.支持库 eAPI
+
+.程序集 即时解释虚拟机
+.程序集变量 词, 词, , "0"
+.程序集变量 函数列表, 抽象语法树节点, , "0"
+.程序集变量 上一运算结果, 双精度小数型
+
+.子程序 解释代码入口
+    .参数 代码, 文本型
+    .局部变量 行, 文本型, , "0"
+    .局部变量 i, 整数型
+    .局部变量 根, 抽象语法树节点
+
+    行 = 分割文本 (代码, #换行符, )
+    .计次循环首 (取数组成员数 (行), i)
+        词法分析 (行 [i], 词)
+        根 = 语法分析 (词)
+        ' 输出语法分析结果 (根, )
+        解释代码 (根)
+    .计次循环尾 ()
+    
+
+.子程序 交互运行
+    .局部变量 根, 抽象语法树节点
+    .局部变量 解释返回, 文本型
+
+    .判断循环首 (真)
+        标准输出 (, “>>> ”)
+        词法分析 (标准输入 (), 词)
+        根 = 语法分析 (词)
+        .如果真 (解释代码 (根) = “表达式求值”)
+            标准输出 (, 到文本 (上一运算结果) + #换行符)
+        .如果真结束
+        
+    .判断循环尾 ()
+
+.子程序 解释代码, 文本型
+    .参数 节点, 抽象语法树节点
+    .局部变量 节点语类, 整数型
+    .局部变量 节点词类, 整数型
+    .局部变量 节点参量, 整数型
+    .局部变量 节点名, 文本型
+
+    节点语类 = 节点.获取语类 ()
+    节点词类 = 节点.获取词类 ()
+    节点参量 = 节点.获取参数数量 ()
+    节点名 = 节点.获取函数名 ()
+    
+    .如果真 (节点语类 = #语类_根)
+        .如果 (节点参量 = 1)
+            返回 (解释代码 (节点.获取参数节点 (1)))
+        .否则
+            .如果真 (节点参量 > 1)
+                调试输出 (“警告 根节点有超过一个子节点”)
+            .如果真结束
+            
+        .如果结束
+        
+    .如果真结束
+    
+    .如果真 (节点.包含语类 (#语类_nop))
+        调试输出 (“警告 nop 泄露到了运行时”)
+    .如果真结束
+    
+    .如果真 (节点词类 = #词类_注释)
+        返回 (“注释”)
+    .如果真结束
+    
+    .如果真 (节点语类 = #语类_定义)
+        ' 现在所有的定义都是函数定义
+        添加函数 (节点)
+        返回 (“定义”)
+    .如果真结束
+    
+    .如果真 (节点.包含语类 (#语类_函数调用))
+        ' 这里的函数调用包含 f(x) 式的, 也包含 1+1 式的
+        上一运算结果 = 表达式求值 (节点, , )
+        返回 (“表达式求值”)
+    .如果真结束
+    返回 (“无匹配”)
+    
+
+.子程序 表达式求值, 双精度小数型
+    .参数 节点, 抽象语法树节点
+    .参数 可用上层参数名, 文本型, 可空 数组
+    .参数 可用上层参数值, 双精度小数型, 可空 数组
+    .局部变量 节点名, 文本型
+    .局部变量 i, 整数型
+    .局部变量 待输出文本组, 文本型, , "0"
+    .局部变量 待输出文本, 文本型
+    .局部变量 节点词类, 整数型
+
+    节点名 = 节点.获取函数名 ()
+    节点词类 = 节点.获取词类 ()
+    ' 调试输出 (“准备表达式求值”, 节点.生成展示文本 (), 可用上层参数名, 可用上层参数值)
+    .如果真 (节点名 = “output”)
+        清除数组 (待输出文本组)
+        .计次循环首 (节点.获取参数数量 (), i)
+            加入成员 (待输出文本组, 格式化文本 (“%s”, 到文本 (表达式求值 (节点.获取参数节点 (i)))))
+        .计次循环尾 ()
+        待输出文本 = 连接字符串 (待输出文本组, “, ”) + #换行符
+        标准输出 (, 待输出文本)
+        返回 (取文本长度 (待输出文本) - 2) ' #换行符长度为2
+    .如果真结束
+    .如果真 (节点名 = “dir”)
+        标准输出 (, “当前函数如下: ” + #换行符)
+        .计次循环首 (取数组成员数 (函数列表), i)
+            标准输出 (, 到文本 (i) + #换行符)
+            输出语法分析结果 (函数列表 [i], )
+        .计次循环尾 ()
+        返回 (取数组成员数 (函数列表))
+    .如果真结束
+    .如果真 (节点词类 = #词类_数字)
+        返回 (到数值 (节点名))
+    .如果真结束
+    .如果真 (节点词类 = #词类_算符)
+        返回 (处理算符 (节点, 可用上层参数名, 可用上层参数值))
+    .如果真结束
+    .如果真 (节点词类 = #词类_括号)
+        返回 (表达式求值 (节点.获取参数节点 (1), 可用上层参数名, 可用上层参数值))
+    .如果真结束
+    .如果真 (节点.获取参数数量 () = 0 且 节点词类 = #词类_标识符)
+        返回 (处理标识符 (节点, 可用上层参数名, 可用上层参数值))
+    .如果真结束
+    
+    ' 到这个地步 只有 f(x) 式的函数调用了
+    返回 (处理函数调用 (节点, 可用上层参数名, 可用上层参数值))
+    
+
+.子程序 处理标识符, 双精度小数型, , 如果要处理标识符值, 应当从当前函数参数值中找匹配的标识符
+    .参数 节点, 抽象语法树节点
+    .参数 可用上层参数名, 文本型, 可空 数组
+    .参数 可用上层参数值, 双精度小数型, 可空 数组
+    .局部变量 i, 整数型
+    .局部变量 节点名, 文本型
+
+    节点名 = 节点.获取函数名 ()
+    ' 调试输出 (可用上层参数名, 可用上层参数值)
+    .计次循环首 (取数组成员数 (可用上层参数名), i)
+        .如果真 (节点名 = 可用上层参数名 [i])
+            返回 (可用上层参数值 [i])
+        .如果真结束
+        
+    .计次循环尾 ()
+    
+    标准输出 (, “[错误] 找不到标识符: ” + 节点名 + #换行符)
+    标准输入 ()
+    结束 ()
+    返回 (0)
+
+.子程序 处理函数调用, 双精度小数型, , 只处理 f(x) 式的
+    .参数 节点, 抽象语法树节点
+    .参数 可用上层参数名, 文本型, 可空 数组
+    .参数 可用上层参数值, 双精度小数型, 可空 数组
+    .局部变量 节点名, 文本型
+    .局部变量 节点词类, 整数型
+    .局部变量 参数数量, 整数型
+    .局部变量 i, 整数型
+    .局部变量 函数原型, 抽象语法树节点
+    .局部变量 同参量函数, 抽象语法树节点, , "0"
+    .局部变量 同参量函数_匹配度, 整数型, , "0"
+    .局部变量 当前最大匹配度, 整数型
+    .局部变量 当前最大匹配度索引, 整数型
+
+    .局部变量 同名函数数, 整数型
+    .局部变量 参数求值结果, 双精度小数型, , "0"
+    .局部变量 参数值完全匹配数量, 整数型
+    .局部变量 函数参数索引, 整数型
+    .局部变量 待匹配参数节点, 抽象语法树节点
+    .局部变量 当前待匹配值, 双精度小数型
+    .局部变量 当前匹配度, 整数型
+
+    .局部变量 可用本层参数名, 文本型, 数组, "0"
+    .局部变量 可用本层参数值, 双精度小数型, 数组, "0"
+    .局部变量 待调用函数, 抽象语法树节点
+    .局部变量 当前结果, 双精度小数型
+
+    节点名 = 节点.获取函数名 ()
+    节点词类 = 节点.获取词类 ()
+    参数数量 = 节点.获取参数数量 ()
+    清除数组 (参数求值结果)
+    
+    .计次循环首 (参数数量, i)
+        当前结果 = 表达式求值 (节点.获取参数节点 (i), 可用上层参数名, 可用上层参数值)
+        加入成员 (参数求值结果, 当前结果)
+        ' 调试输出 (“参数求值结果”, 节点.获取参数节点 (i).获取函数名 (), 当前结果)
+    .计次循环尾 ()
+    
+    ' 找同名函数
+    清除数组 (同参量函数)
+    清除数组 (同参量函数_匹配度)
+    
+    清除数组 (可用本层参数名)
+    清除数组 (可用本层参数值)
+    
+    .计次循环首 (取数组成员数 (函数列表), i)
+        函数原型 = 函数列表 [i].获取参数节点 (1)
+        .如果真 (函数原型.获取函数名 () = 节点名)
+            同名函数数 = 同名函数数 + 1
+            .如果真 (函数原型.获取参数数量 () = 参数数量)
+                加入成员 (同参量函数, 函数列表 [i])
+                参数值完全匹配数量 = 0
+                .计次循环首 (参数数量, 函数参数索引)
+                    待匹配参数节点 = 函数原型.获取参数节点 (函数参数索引)
+                    ' 词类是标识符的是未知数  不论如何不会增加最佳匹配量, 之外的, 可以求值然后对比值
+                    ' 如果求值结果不同, 一定不能加入匹配, 直接打散到最小上
+                    .如果真 (待匹配参数节点.获取词类 () ≠ #词类_标识符)
+                        当前待匹配值 = 表达式求值 (待匹配参数节点)
+                        .如果 (当前待匹配值 = 参数求值结果 [函数参数索引])
+                            参数值完全匹配数量 = 参数值完全匹配数量 + 1
+                        .否则
+                            参数值完全匹配数量 = -9999
+                            跳出循环 ()
+                        .如果结束
+                        
+                    .如果真结束
+                    
+                .计次循环尾 ()
+                加入成员 (同参量函数_匹配度, 参数值完全匹配数量)
+            .如果真结束
+            
+        .如果真结束
+        
+    .计次循环尾 ()
+    ' 给出合适的报错
+    .如果真 (同名函数数 = 0)
+        标准输出 (, “[错误] 找不到函数 ” + 节点名 + “. 相关上下文如下: ” + #换行符 + #换行符)
+        输出语法分析结果 (节点, )
+        标准输入 ()
+        结束 ()
+    .如果真结束
+    
+    .如果真 (取数组成员数 (同参量函数) = 0)
+        标准输出 (, “[错误] 找不到可重载函数, 同名函数有: ” + #换行符)
+        .计次循环首 (取数组成员数 (同参量函数), i)
+            标准输出 (, 到文本 (i) + “:” + #换行符)
+            输出语法分析结果 (同参量函数 [i], )
+        .计次循环尾 ()
+        标准输入 ()
+        结束 ()
+    .如果真结束
+    
+    ' 找到最佳匹配度的那个函数
+    当前最大匹配度 = -99999
+    当前最大匹配度索引 = 0
+    .计次循环首 (取数组成员数 (同参量函数), i)
+        当前匹配度 = 同参量函数_匹配度 [i]
+        .如果真 (当前匹配度 > 当前最大匹配度)
+            当前最大匹配度索引 = i
+            当前最大匹配度 = 当前匹配度
+        .如果真结束
+        
+    .计次循环尾 ()
+    
+    ' 把标识符参数拿出来并给值
+    函数原型 = 同参量函数 [当前最大匹配度索引].获取参数节点 (1)
+    待调用函数 = 同参量函数 [当前最大匹配度索引].获取参数节点 (2)
+    ' 输出语法分析结果 (同参量函数 [当前最大匹配度索引], )
+    ' 输出语法分析结果 (函数原型, )
+    
+    .计次循环首 (参数数量, 函数参数索引)
+        
+        待匹配参数节点 = 函数原型.获取参数节点 (函数参数索引)
+        ' 输出语法分析结果 (待匹配参数节点, )
+        .如果真 (待匹配参数节点.获取词类 () = #词类_标识符)
+            加入成员 (可用本层参数名, 函数原型.获取参数节点 (函数参数索引).获取函数名 ())
+            加入成员 (可用本层参数值, 参数求值结果 [函数参数索引])
+            ' 调试输出 (“可用本层参数”, 函数原型.获取参数节点 (函数参数索引).获取函数名 (), 参数求值结果 [函数参数索引])
+        .如果真结束
+        
+    .计次循环尾 ()
+    
+    
+    ' 调试输出 (“调用一个函数”, 节点.生成展示文本 ())
+    
+    返回 (表达式求值 (待调用函数, 可用本层参数名, 可用本层参数值))
+
+.子程序 处理算符, 双精度小数型
+    .参数 节点, 抽象语法树节点
+    .参数 可用上层参数名, 文本型, 可空 数组
+    .参数 可用上层参数值, 双精度小数型, 可空 数组
+    .局部变量 节点名, 文本型
+    .局部变量 l, 双精度小数型
+    .局部变量 r, 双精度小数型
+
+    节点名 = 节点.获取函数名 ()
+    ' 调试输出 (可用上层参数名, 可用上层参数值)
+    
+    l = 表达式求值 (节点.获取参数节点 (1), 可用上层参数名, 可用上层参数值)
+    r = 表达式求值 (节点.获取参数节点 (2), 可用上层参数名, 可用上层参数值)
+    
+    .判断开始 (节点名 = “+”)
+        返回 (l + r)
+    .判断 (节点名 = “-”)
+        返回 (l - r)
+    .判断 (节点名 = “*”)
+        返回 (l × r)
+    .判断 (节点名 = “/”)
+        返回 (l ÷ r)
+    .默认
+        调试输出 (“警告 遇到奇怪的算符”, 节点名)
+    .判断结束
+    返回 (0)
+
+.子程序 添加函数
+    .参数 节点, 抽象语法树节点
+
+    调试输出 (“新增一个函数”, 节点.获取参数节点 (1).获取函数名 ())
+    加入成员 (函数列表, 节点)
+    
+
+.子程序 取最小, 双精度小数型
+    .参数 a, 双精度小数型
+    .参数 b, 双精度小数型
+
+    .如果真 (a > b)
+        返回 (b)
+    .如果真结束
+    返回 (a)
+

+ 377 - 0
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/代码/抽象语法树节点.class.e.txt

@@ -0,0 +1,377 @@
+.版本 2
+.支持库 spec
+.支持库 eAPI
+
+.程序集 抽象语法树节点, , 公开
+.程序集变量 当前节点指针, 长整数型, 数组
+.程序集变量 已初始化, 逻辑型, 数组
+.程序集变量 失败, 逻辑型, 数组
+
+.子程序 _初始化, , , 当基于本类的对象被创建后,此方法会被自动调用
+    已初始化 = 假
+    
+    ' {
+    ' char     函数名[16],   // 定长16, 再长不支持了
+    ' int32_t  参数量,
+    ' int32_t  参数数组容量, // 参数数组指针后有多大容量
+    ' uint64_t 参数数组指针, // 长整数, 未来迁移到x64时兼容
+    ' }
+    ' // 此结构单个长度为 16+8+8 = 32 字节
+    
+
+.子程序 _销毁, , , 当基于本类的对象被销毁前,此方法会被自动调用
+    .如果真 (已初始化)
+        ' 调试输出 (格式化文本 (“警告: %x : %s 未释放内存而销毁”, 到整数 (当前节点指针), 获取函数名 ()))
+    .如果真结束
+    
+
+.子程序 初始化内存, , 公开
+    .参数 函数名, 文本型, 可空
+    .参数 父节点地址, 长整数型, 可空
+
+    当前节点指针 = 到长整数 (申请内存 (#语法树节点_长度, 真))
+    .如果真 (是否为空 (函数名) = 假)
+        设置函数名 (函数名)
+    .如果真结束
+    .如果真 (是否为空 (父节点地址) = 假)
+        设置父节点指针地址 (父节点地址)
+    .如果真结束
+    ' 调试输出 (“设置参数指针地址”)
+    设置参数指针地址 (申请内存 (#语法树节点_参数容量初始值 × #指针大小, 真))
+    设置参数容量 (#语法树节点_参数容量初始值)
+    
+    已初始化 = 真
+    
+
+.子程序 初始化否, 逻辑型
+    返回 (已初始化)
+    
+
+.子程序 释放结构内存, , 公开
+    .如果真 (获取参数容量 () ≠ 0)
+        释放内存 (获取参数指针地址 ())
+    .如果真结束
+    释放内存 (当前节点指针)
+    已初始化 = 假
+    
+    
+
+.子程序 生成子节点, 抽象语法树节点, 公开
+    .参数 子节点函数名, 文本型, 可空
+    .局部变量 ast, 抽象语法树节点, 数组
+
+    .如果 (是否为空 (子节点函数名))
+        ast.设置函数名 (子节点函数名)
+    .否则
+        ast.设置函数名 (格式化文本 (“%s 的子节点”, 获取函数名 ()))
+    .如果结束
+    ast.设置父节点指针地址 (获取当前节点指针 ())
+    返回 (ast)
+    
+
+.子程序 生成匹配失败节点, 抽象语法树节点, 公开
+    .局部变量 ast, 抽象语法树节点, 数组
+
+    ast = 生成子节点 (格式化文本 (“%s 的失败子节点”, 获取函数名 ()))
+    ast._设置失败 ()
+    返回 (ast)
+    
+
+.子程序 失败, 逻辑型, 公开
+    返回 (失败)
+    
+
+.子程序 成功, 逻辑型, 公开
+    返回 (失败 = 假)
+    
+
+.子程序 _设置失败, , 公开
+    失败 = 真
+    已初始化 = 假
+    
+
+.子程序 从内存初始化, 抽象语法树节点, 公开
+    .参数 地址, 长整数型
+    .局部变量 res, 抽象语法树节点, 数组
+
+    res.设置当前节点指针 (地址)
+    返回 (res)
+    
+
+.子程序 获取当前节点指针, 长整数型, 公开
+    返回 (当前节点指针)
+    
+
+.子程序 设置当前节点指针, , 公开
+    .参数 地址, 长整数型
+
+    当前节点指针 = 地址
+    
+
+.子程序 设置函数名, , 公开
+    .参数 函数名, 文本型, , 最长实际上是 #语法树节点_函数名最大长度-1
+    .局部变量 字节数组, 字节型, 数组, "16"
+    .局部变量 i, , 数组
+    .局部变量 函数名长度, 整数型, 数组
+
+    重定义数组 (字节数组, 假, #语法树节点_函数名最大长度)
+    
+    函数名长度 = 取文本长度 (函数名)
+    
+    .计次循环首 (#语法树节点_函数名最大长度, i)
+        .判断开始 (i = #语法树节点_函数名最大长度 或 i > 函数名长度)
+            字节数组 [i] = 到字节 (0)
+        .默认
+            字节数组 [i] = 取代码 (函数名, i)
+        .判断结束
+        
+    .计次循环尾 ()
+    
+    写到内存 (字节数组, 当前节点指针 + #语法树节点_函数名偏移, #语法树节点_函数名最大长度)
+    
+
+.子程序 获取函数名, 文本型, 公开
+    返回 (指针到文本 (当前节点指针 + #语法树节点_函数名偏移))
+    
+
+.子程序 设置语类, , 公开
+    .参数 类, 整数型
+    .局部变量 当前语类, 整数型
+    .局部变量 新类, 整数型
+
+    当前语类 = 获取语类 ()
+    新类 = 到整数 (当前语类 + 类)
+    
+    ' 调试输出 (当前语类, 类, 新类)
+    .如果 (位与 (当前语类, 类) ≠ 0)
+        ' 调试输出 (“警告: 重复设置语类”, 类)
+    .否则
+        写到内存 (新类, 当前节点指针 + #语法树节点_语类, 4)
+    .如果结束
+    
+    
+
+.子程序 清理语类, , 公开
+    .参数 类, 整数型
+    .局部变量 当前语类, 整数型
+    .局部变量 新类, 整数型
+
+    当前语类 = 获取语类 ()
+    新类 = 到整数 (当前语类 - 类)
+    
+    ' 调试输出 (当前语类, 类, 新类)
+    .如果 (位与 (当前语类, 类) = 0)
+        ' 调试输出 (“警告: 尝试清除不存在语类”, 类)
+    .否则
+        写到内存 (新类, 当前节点指针 + #语法树节点_语类, 4)
+    .如果结束
+    
+
+.子程序 获取语类, 整数型, 公开
+    .局部变量 字节数组, 通用型, 数组, "0"
+
+    返回 (取字节集数据 (指针到字节集 (当前节点指针 + #语法树节点_语类, 4), #整数型, ))
+    
+
+.子程序 包含语类, 逻辑型, 公开
+    .参数 类, 整数型
+    .局部变量 当前语类, 整数型
+
+    当前语类 = 获取语类 ()
+    返回 (位与 (当前语类, 类) ≠ 0)
+
+.子程序 设置词类, , 公开
+    .参数 类, 整数型
+
+    写到内存 (类, 当前节点指针 + #语法树节点_词类, 4)
+    
+
+.子程序 获取词类, 整数型, 公开
+    .局部变量 字节数组, 通用型, 数组, "0"
+
+    返回 (取字节集数据 (指针到字节集 (当前节点指针 + #语法树节点_词类, 4), #整数型, ))
+
+.子程序 设置参数数量, , 公开
+    .参数 量, 长整数型
+
+    写到内存 (量, 当前节点指针 + #语法树节点_参数量偏移, 4)
+    
+
+.子程序 获取参数数量, 整数型, 公开
+    .局部变量 字节数组, 通用型, 数组, "0"
+
+    返回 (取字节集数据 (指针到字节集 (当前节点指针 + #语法树节点_参数量偏移, 4), #整数型, ))
+    
+
+.子程序 设置参数容量, , 公开
+    .参数 量, 整数型
+
+    写到内存 (量, 当前节点指针 + #语法树节点_参数容量偏移, 4)
+    
+
+.子程序 获取参数容量, 整数型, 公开
+    返回 (取字节集数据 (指针到字节集 (当前节点指针 + #语法树节点_参数容量偏移, 4), #整数型, ))
+    
+
+.子程序 设置参数指针地址, , 公开
+    .参数 地址, 长整数型
+
+    写到内存 (地址, 当前节点指针 + #语法树节点_参数指针偏移, #指针大小)
+    
+
+.子程序 获取参数指针地址, 长整数型, 公开, 已经不在本结构体了, 在远处了
+    返回 (取字节集数据 (指针到字节集 (当前节点指针 + #语法树节点_参数指针偏移, #指针大小), #长整数型, ))
+    
+
+.子程序 获取结构体字节集, 字节集, 公开
+    返回 (指针到字节集 (当前节点指针, #语法树节点_长度))
+    
+
+.子程序 获取参数数组字节集, 字节集, 公开
+    返回 (指针到字节集 (获取参数指针地址 (), 获取参数数量 () × #指针大小))
+    
+
+.子程序 扩容参数指针, 长整数型, 公开
+    .参数 新长度, 整数型, 可空
+    .局部变量 旧参数指针地址, 长整数型, 数组
+    .局部变量 旧参数数组打包, 字节集, 数组
+    .局部变量 新参数指针地址, 长整数型, 数组
+
+    .如果真 (是否为空 (新长度))
+        新长度 = 获取参数容量 () × #语法树节点_参数容量扩张系数
+    .如果真结束
+    
+    旧参数指针地址 = 获取参数指针地址 ()
+    旧参数数组打包 = 获取参数数组字节集 ()
+    新参数指针地址 = 申请内存 (新长度 × #指针大小, 真)
+    
+    
+    写到内存 (旧参数数组打包, 新参数指针地址, 获取参数数量 () × #指针大小)
+    释放内存 (旧参数指针地址)
+    
+    设置参数指针地址 (新参数指针地址)
+    
+    设置参数容量 (新长度)
+    返回 (新参数指针地址)
+    
+
+.子程序 添加参数节点, , 公开
+    .参数 节点, 抽象语法树节点
+    .局部变量 当前参数数量, 整数型, 数组
+
+    当前参数数量 = 获取参数数量 ()
+    
+    .如果真 (当前参数数量 ≥ 获取参数容量 ())
+        扩容参数指针 ()
+    .如果真结束
+    节点.设置父节点指针地址 (获取当前节点指针 ())
+    写到内存 (节点.获取当前节点指针 (), 获取参数指针地址 () + 当前参数数量 × #指针大小, )
+    设置参数数量 (当前参数数量 + 1)
+    
+
+.子程序 插入参数节点, , 公开
+    .参数 节点, 抽象语法树节点
+    .局部变量 当前参数数量, 整数型, 数组
+    .局部变量 新参数指针地址, 整数型, 数组
+    .局部变量 旧参数数组打包, 字节集, 数组
+    .局部变量 旧参数指针地址, 长整数型, 数组
+
+    当前参数数量 = 获取参数数量 ()
+    .如果真 (当前参数数量 ≥ 获取参数容量 ())
+        扩容参数指针 ()
+    .如果真结束
+    
+    旧参数指针地址 = 获取参数指针地址 ()
+    旧参数数组打包 = 获取参数数组字节集 ()
+    新参数指针地址 = 申请内存 (获取参数容量 () × #指针大小, 真)
+    
+    写到内存 (到字节集 (节点.获取当前节点指针 ()) + 旧参数数组打包, 新参数指针地址, (当前参数数量 + 1) × #指针大小)
+    释放内存 (旧参数指针地址)
+    
+    设置参数指针地址 (新参数指针地址)
+    设置参数数量 (当前参数数量 + 1)
+    
+
+.子程序 生成自词节点, 抽象语法树节点, 公开
+    .参数 词, 词
+    .局部变量 n, 抽象语法树节点, 数组
+
+    n.初始化内存 (词.内容, )
+    n.设置词类 (词.类型)
+    返回 (n)
+    
+
+.子程序 添加词节点, , 公开
+    .参数 词, 词
+
+    添加文本节点 (词.内容)
+    
+
+.子程序 添加文本节点, , 公开
+    .参数 文本, 文本型
+    .局部变量 n, 抽象语法树节点, 数组
+
+    n.初始化内存 (文本)
+    添加参数节点 (n)
+    
+
+.子程序 获取参数节点, 抽象语法树节点, 公开
+    .参数 i, 整数型, 可空
+
+    .如果真 (是否为空 (i))
+        i = 获取参数数量 ()
+    .如果真结束
+    
+    返回 (从内存初始化 (指针到整数 (获取参数指针地址 () + (i - 1) × #指针大小)))
+    
+
+.子程序 生成展示文本, 文本型, 公开
+    .局部变量 词类展示名集合, 文本型, , "0"
+    .局部变量 语类展示名集合, 文本型, , "0"
+
+    .局部变量 语类, 整数型
+    .局部变量 语类展示名, 文本型
+    .局部变量 i, 整数型
+    .局部变量 当前掩码, 整数型
+
+    ' 返回 (格式化文本 (“%s | 基地址: %x | 参数数量: %d | 参数容量: %d | 参数数组地址: %x ”, 获取函数名 (), 到整数 (获取当前节点指针 ()), 到整数 (获取参数数量 ()), 到整数 (获取参数容量 ()), 到整数 (获取参数指针地址 ())))
+    语类展示名集合 = { “语类_未定义”, “语类_定义”, “语类_函数调用”, “语类_函数原型”, “语类_形式参数”, “语类_实际参数”, “语类_根” }
+    语类 = 获取语类 ()
+    .如果 (语类 = 0)
+        语类展示名 = 语类展示名 + 语类展示名集合 [语类 + 1]
+    .否则
+        .计次循环首 (取数组成员数 (语类展示名集合), i)
+            当前掩码 = 左移 (1, i) ÷ 2
+            .如果真 (位与 (当前掩码, 语类) ≠ 0)
+                语类展示名 = 语类展示名 + 语类展示名集合 [i + 1] + “ ”
+            .如果真结束
+            
+        .计次循环尾 ()
+        
+    .如果结束
+    
+    
+    词类展示名集合 = { “词类_未定义”, “词类_数字”, “词类_整数部分”, “词类_小数部分”, “词类_标识符”, “词类_算符”, “词类_括号”, “词类_注释”, “词类_逗号”, “词类_双等号”, “词类_单等号”, “词类_空格”, “词类_结尾” }
+    
+    返回 (格式化文本 (“%s | %s | %s| 参数数量: %d ”, 获取函数名 (), 词类展示名集合 [获取词类 () + 1], 语类展示名, 到整数 (获取参数数量 ())))
+
+.子程序 设置父节点, , 公开
+    .参数 父节点, 抽象语法树节点
+
+    设置父节点指针地址 (父节点.获取当前节点指针 ())
+    
+
+.子程序 设置父节点指针地址, , 公开
+    .参数 地址, 长整数型
+
+    写到内存 (地址, 当前节点指针 + #语法树节点_父节点指针偏移, #指针大小)
+    
+
+.子程序 获取父节点指针地址, 长整数型, 公开, 已经不在本结构体了, 在远处了
+    返回 (取字节集数据 (指针到字节集 (当前节点指针 + #语法树节点_父节点指针偏移, #指针大小), #长整数型, ))
+    
+
+.子程序 获取父节点, 抽象语法树节点, 公开
+    返回 (从内存初始化 (获取父节点指针地址 ()))
+    
+

+ 6 - 0
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/代码/排序.list.txt

@@ -0,0 +1,6 @@
+程序集1
+词法分析程序集
+来自精易模块
+语法分析程序集
+抽象语法树节点
+即时解释虚拟机

+ 32 - 0
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/代码/来自精易模块.static.e.txt

@@ -0,0 +1,32 @@
+.版本 2
+
+.程序集 来自精易模块, , , 用于加速编译和导出文本
+.子程序 时间_取现行时间戳1, 长整数型, 公开, 生成一个10位或者13位的现行时间戳
+    .参数 精确到毫秒, 逻辑型, 可空, 默认为假 精确到秒10位数 精确到毫秒13位数
+    .局部变量 ret, 长整数型, 数组
+
+    ' https://bbs.125.la/forum.php?mod=viewthread&tid=14649396
+    GetSystemTimeAsFileTime (取指针地址_长整数型 (ret))
+    ret = FileTimeToUnixTime (ret)
+    .如果 (精确到毫秒)
+        ret = ret ÷ 10000
+    .否则
+        ret = ret ÷ 10000000
+    .如果结束
+    返回 (ret)
+    
+
+.子程序 FileTimeToUnixTime, 长整数型
+    .参数 FlieTime, 长整数型
+    .局部变量 ll, 长整数型, 数组
+
+    ll = FlieTime - 1.16444736e+017
+    返回 (ll)
+    
+
+.子程序 取指针地址_长整数型, 整数型, 公开
+    .参数 欲取地址的数据, 长整数型, 参考
+
+    返回 (lstrcpyn_长整数型 (欲取地址的数据, 欲取地址的数据, 0))
+    
+

+ 66 - 0
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/代码/程序集1.static.e.txt

@@ -0,0 +1,66 @@
+.版本 2
+
+.程序集 程序集1
+.子程序 _启动子程序, 整数型, , 本子程序在程序启动后最先执行
+    .局部变量 代码, 文本型
+
+    代码 = UTF8到文本 (读入文件 (“code-examples.ve”))
+    解释代码入口 (代码)
+    
+    交互运行 ()
+    
+    .判断循环首 (真)
+        标准输出 (, “> ”)
+        解析命令 (标准输入 ())
+    .判断循环尾 ()
+    
+    返回 (0) ' 可以根据您的需要返回任意数值
+    
+
+.子程序 解析命令
+    .参数 命令, 文本型
+    .局部变量 t, 文本型, 数组, "0"
+    .局部变量 文件名, 文本型
+    .局部变量 代码, 文本型
+
+    ' 支持命令
+    ' 「帮助」 「词法分析 some text」 「语法分析 some text」
+    t = 分割文本 (命令, “ ”, )
+    
+    
+    .判断开始 (t [1] = “帮助” 或 到半角 (t [1]) = “?”)
+        标准输出 (, #命令行帮助)
+    .判断 (t [1] = “词法分析”)
+        词法分析并输出 (取文本右边 (命令, 取文本长度 (命令) - 取文本长度 (“词法分析”)))
+    .判断 (t [1] = “语法分析”)
+        语法分析并输出 (取文本右边 (命令, 取文本长度 (命令) - 取文本长度 (“语法分析”)))
+    .判断 (t [1] = “运行” 或 t [1] = “run”)
+        文件名 = t [2]
+        代码 = UTF8到文本 (读入文件 (文件名))
+        解释代码入口 (代码)
+    .判断 (t [1] = “交互运行”)
+        交互运行 ()
+    .默认
+        标准输出 (, “未知命令” + #换行符)
+    .判断结束
+    
+
+.子程序 连接字符串, 文本型
+    .参数 字符串组, 文本型, 数组
+    .参数 连接词, 文本型
+    .局部变量 res, 文本型, 数组
+    .局部变量 i, 整数型, 数组
+    .局部变量 组长度, 整数型
+
+    res = “”
+    组长度 = 取数组成员数 (字符串组)
+    
+    .计次循环首 (组长度, i)
+        res = res + 字符串组 [i]
+        .如果真 (i < 组长度)
+            res = res + 连接词
+        .如果真结束
+        
+    .计次循环尾 ()
+    返回 (res)
+

+ 103 - 0
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/代码/词法分析程序集.static.e.txt

@@ -0,0 +1,103 @@
+.版本 2
+.支持库 RegEx
+
+.程序集 词法分析程序集
+.程序集变量 正则, 正则表达式, 数组
+
+.子程序 词法分析
+    .参数 表达式, 文本型
+    .参数 返回值, 词, 参考 数组
+    .局部变量 上次结果位置, 整数型, 数组
+    .局部变量 当前词, 词, 数组
+    .局部变量 当前匹配文本, 文本型, 数组
+    .局部变量 res, 搜索结果, 数组
+
+    .局部变量 i, 整数型, 数组
+
+    ' 可能带°的数字 (\d+)(\.\d+)*[°]{0,1}
+    ' 标识符 [a-zA-ZΑ-Ωα-ω_][a-zA-ZΑ-Ωα-ω0-9_]*
+    ' 算符 [\+\-\*\/\^]
+    ' 括号 [\(\)]
+    ' 注释 \#.+
+    ' 逗号 ,
+    ' 等号 =
+    ' 易语言的正则表达式没办法用\u, 也没办法写希腊字母, 也没办法写「°」, 因此去掉希腊字母和「°」, 加上空白, 合起来就是这样的
+    .如果真 (正则.是否为空 ())
+        正则.创建 (“((\d+)(\.\d+)*)|([a-zA-Z_][a-zA-Z0-9_]*)|([\+\-\*\/\^])|([\(\)])|(\#.+)|([,])|(==)|(=)|[ ]+$”, )
+    .如果真结束
+    
+    ' ________________m1______________ -> 数字
+    ' ____________ m2___m3____________ -> 数字的整数和小数部分
+    ' __________________________________________m4___________ -> 标识符 包含英文字母和希腊字母 只能以字母或下划线开头, 之后可以是数字或字母下划线
+    ' _______________________________________________________________m5______ -> 算符, +-*/^
+    ' __________________________________________________________________________m6___ -> 括号
+    ' _________________________________________________________________________________m7___ -> 注释
+    ' _______________________________________________________________________________________m8___ -> 逗号
+    
+    ' 调试输出 (正则.取子表达式个数 ())
+    
+    清除数组 (返回值)
+    上次结果位置 = 1
+    
+    .判断循环首 (上次结果位置 ≤ 取文本长度 (表达式) 且 当前词.类型 ≠ -1)
+        当前词.内容 = “”
+        当前词.类型 = -1
+        res = 正则.搜索 (表达式, 上次结果位置, )
+        
+        .计次循环首 (#词类型枚举数量, i)
+            .如果真 (i = #词类_整数部分 或 i = #词类_小数部分)
+                到循环尾 ()
+            .如果真结束
+            
+            当前匹配文本 = res.取子匹配文本 (表达式, i, 上次结果位置)
+            
+            .如果真 (取文本长度 (当前匹配文本) > 0 且 i ≠ #词类_空格)
+                当前词.内容 = 当前匹配文本
+                当前词.类型 = i
+                上次结果位置 = 上次结果位置 + 取文本长度 (当前匹配文本) + 1
+                加入成员 (返回值, 当前词)
+                
+                跳出循环 ()
+            .如果真结束
+            
+        .计次循环尾 ()
+        
+        
+    .判断循环尾 ()
+    
+    
+
+.子程序 词存在, 逻辑型
+    .参数 词, 词, 数组
+    .参数 类型, 整数型, , #词类枚举
+    .局部变量 i, 整数型
+
+    .计次循环首 (取数组成员数 (词), i)
+        .如果真 (词 [i].类型 = 类型)
+            返回 (真)
+        .如果真结束
+        
+    .计次循环尾 ()
+    返回 (假)
+
+.子程序 输出词法分析结果
+    .参数 词, 词, 数组
+    .局部变量 i, 整数型, 数组
+
+    .计次循环首 (取数组成员数 (词), i)
+        标准输出 (, “当前类型: ” + 到文本 (词 [i].类型) + “, 内容: ” + 词 [i].内容 + #换行符)
+    .计次循环尾 ()
+    标准输出 (, “----” + #换行符)
+    
+
+.子程序 词法分析并输出
+    .参数 表达式, 文本型
+    .局部变量 res, 词, 数组, "0"
+    .局部变量 t0, 长整数型, 数组
+
+    t0 = 时间_取现行时间戳1 (真)
+    词法分析 (表达式, res)
+    标准输出 (, “用时 ” + 到文本 (时间_取现行时间戳1 (真) - t0) + “ms” + #换行符)
+    输出词法分析结果 (res)
+    
+

+ 442 - 0
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/代码/语法分析程序集.static.e.txt

@@ -0,0 +1,442 @@
+.版本 2
+.支持库 spec
+
+.程序集 语法分析程序集
+.程序集变量 AST根, 抽象语法树节点, 数组
+.程序集变量 词, 词, 数组, "0"
+.程序集变量 当前词游标, 整数型, 数组
+
+.子程序 语法分析, 抽象语法树节点
+    .参数 _词, 词, 数组
+    .局部变量 当前节点, 抽象语法树节点, 数组
+    .局部变量 res, 抽象语法树节点, 数组
+
+    复制数组 (词, _词)
+    当前词游标 = 0
+    AST根.初始化内存 (“根”)
+    AST根.设置语类 (#语类_根)
+    
+    .判断循环首 (下个词 ().类型 ≠ #词类_结尾)
+        res = 匹配语句 (AST根)
+        ' 调试输出 (“匹配表达式 结束”, res.生成展示文本 ())
+        
+        .如果 (res.失败 ())
+            跳出循环 ()
+        .否则
+            AST根.添加参数节点 (res)
+        .如果结束
+        跳出循环 ()
+    .判断循环尾 ()
+    返回 (AST根)
+
+.子程序 匹配语句, 抽象语法树节点
+    .参数 父节点, 抽象语法树节点
+    .局部变量 当前节点, 抽象语法树节点
+    .局部变量 函数定义, 抽象语法树节点
+    .局部变量 表达式, 抽象语法树节点
+    .局部变量 注释, 抽象语法树节点
+
+    
+    当前节点.初始化内存 (“匹配语句 之起始”, )
+    ' 调试输出 (“当前父节点”, 父节点.获取函数名 ())
+    .如果真 (下个词 ().类型 = #词类_注释)
+        注释 = 父节点.生成自词节点 (下个词 ())
+        词游标自增 ()
+        返回 (注释)
+    .如果真结束
+    
+    
+    
+    .如果 (词存在 (词, #词类_单等号))
+        ' 这是个赋值语句
+        函数定义 = 匹配函数定义 (当前节点)
+        .如果真 (函数定义.失败 ())
+            返回 (父节点.生成匹配失败节点 ())
+        .如果真结束
+        返回 (函数定义)
+    .否则
+        表达式 = 匹配表达式 (当前节点)
+        .如果真 (表达式.失败 ())
+            返回 (父节点.生成匹配失败节点 ())
+        .如果真结束
+        返回 (表达式)
+    .如果结束
+    
+    
+
+.子程序 匹配函数定义, 抽象语法树节点
+    .参数 父节点, 抽象语法树节点
+    .局部变量 函数, 抽象语法树节点
+    .局部变量 等号, 抽象语法树节点
+    .局部变量 表达式, 抽象语法树节点
+    .局部变量 i, 整数型
+
+    函数 = 匹配函数 (父节点)
+    .如果真 (函数.失败 ())
+        返回 (父节点.生成匹配失败节点 ())
+    .如果真结束
+    
+    等号 = 通用词匹配 (#词类_单等号)
+    .如果真 (等号.失败 ())
+        返回 (父节点.生成匹配失败节点 ())
+    .如果真结束
+    
+    表达式 = 匹配表达式 (父节点)
+    .如果真 (表达式.失败 ())
+        返回 (父节点.生成匹配失败节点 ())
+    .如果真结束
+    
+    函数.设置语类 (#语类_函数原型)
+    .计次循环首 (函数.获取参数数量 (), i)
+        函数.获取参数节点 (i).设置语类 (#语类_形式参数)
+        函数.获取参数节点 (i).清理语类 (#语类_实际参数)
+    .计次循环尾 ()
+    表达式.设置语类 (#语类_函数调用)
+    等号.添加参数节点 (函数)
+    等号.添加参数节点 (表达式)
+    等号.设置语类 (#语类_定义)
+    
+    返回 (等号)
+    
+
+.子程序 匹配表达式, 抽象语法树节点
+    .参数 父节点, 抽象语法树节点
+    .局部变量 l, 抽象语法树节点, 数组
+    .局部变量 r, 抽象语法树节点, 数组
+    .局部变量 当前节点, 抽象语法树节点, 数组
+    .局部变量 右侧无穷, 抽象语法树节点, 数组
+    .局部变量 天父, 抽象语法树节点, 数组
+
+    当前节点.初始化内存 (“匹配表达式 之起始”)
+    ' 调试输出 (“当前父节点”, 父节点.获取函数名 ())
+    l = 匹配加后表达式 (当前节点)
+    l.设置语类 (#语类_实际参数)
+    
+    .如果真 (l.失败 ())
+        ' 调试输出 (“未匹配到左加后表达式”)
+        返回 (父节点.生成匹配失败节点 ())
+    .如果真结束
+    当前节点.添加参数节点 (l)
+    ' 调试输出 (“匹配到左加后表达式”, l.获取函数名 ())
+    
+    右侧无穷 = 匹配表达式右侧无穷 (父节点)
+    右侧无穷.插入参数节点 (l)
+    
+    天父 = 右侧无穷
+    .判断循环首 (天父.获取函数名 () ≠ “nop”)
+        ' 调试输出 (天父.生成展示文本 ())
+        天父 = 天父.获取父节点 ()
+    .判断循环尾 ()
+    天父 = 天父.获取参数节点 (1)
+    天父.设置语类 (#语类_函数调用)
+    返回 (天父)
+    
+
+.子程序 匹配表达式右侧无穷, 抽象语法树节点
+    .参数 父节点, 抽象语法树节点
+    .局部变量 当前节点, 抽象语法树节点, 数组
+    .局部变量 m, 抽象语法树节点, 数组
+    .局部变量 r, 抽象语法树节点, 数组
+    .局部变量 后续无穷, 抽象语法树节点, 数组
+
+    当前节点.初始化内存 (“nop”)
+    当前节点.设置语类 (#语类_nop)
+    .如果真 (下个词 ().内容 ≠ “+” 且 下个词 ().内容 ≠ “-”)
+        ' 调试输出 (“未匹配到+-中算符”)
+        返回 (当前节点)
+    .如果真结束
+    m = 父节点.生成自词节点 (下个词 ())
+    词游标自增 ()
+    
+    r = 匹配加后表达式 (当前节点)
+    r.设置语类 (#语类_实际参数)
+    .如果真 (r.失败 ())
+        返回 (父节点.生成匹配失败节点 ())
+    .如果真结束
+    
+    
+    .如果 (下个词 ().类型 ≠ #词类_结尾)
+        后续无穷 = 匹配表达式右侧无穷 (r)
+        .如果真 (后续无穷.失败 ())
+            返回 (后续无穷)
+        .如果真结束
+        
+    .否则
+        后续无穷.初始化内存 (“nop”, )
+        后续无穷.设置语类 (#语类_nop)
+    .如果结束
+    
+    ' 调试输出 (下个词 ().类型)
+    m.设置父节点 (后续无穷)
+    m.添加参数节点 (r)
+    m.设置语类 (#语类_函数调用)
+    后续无穷.插入参数节点 (m)
+    返回 (m)
+    
+
+.子程序 匹配加后表达式, 抽象语法树节点
+    .参数 父节点, 抽象语法树节点
+    .局部变量 l, 抽象语法树节点, 数组
+    .局部变量 当前节点, 抽象语法树节点, 数组
+    .局部变量 右侧无穷, 抽象语法树节点, 数组
+    .局部变量 r, 抽象语法树节点, 数组
+
+    .局部变量 天父, 抽象语法树节点, 数组
+
+    当前节点.初始化内存 ()
+    ' 调试输出 (“当前父节点”, 父节点.获取函数名 ())
+    l = 匹配因子 (父节点)
+    
+    .如果真 (l.失败 ())
+        调试输出 (“未匹配到左数字”)
+        返回 (父节点.生成匹配失败节点 ())
+    .如果真结束
+    ' 调试输出 (“匹配到左数字”, l.获取函数名 ())
+    当前节点.添加参数节点 (l)
+    
+    右侧无穷 = 匹配加后表达式右侧无穷 (父节点)
+    .如果真 (右侧无穷.获取参数数量 () > 0)
+        ' 调试输出 (“右侧无穷”, 右侧无穷.获取参数节点 (1).生成展示文本 ())
+    .如果真结束
+    右侧无穷.插入参数节点 (l)
+    ' 调试输出 (“右侧无穷”, 右侧无穷.获取参数节点 (1).生成展示文本 ())
+    
+    天父 = 右侧无穷
+    .判断循环首 (天父.获取函数名 () ≠ “nop”)
+        ' 调试输出 (天父.生成展示文本 ())
+        天父 = 天父.获取父节点 ()
+    .判断循环尾 ()
+    天父 = 天父.获取参数节点 (1)
+    天父.设置语类 (#语类_函数调用)
+    
+    返回 (天父)
+    
+
+.子程序 匹配加后表达式右侧无穷, 抽象语法树节点
+    .参数 父节点, 抽象语法树节点
+    .局部变量 当前节点, 抽象语法树节点, 数组
+    .局部变量 m, 抽象语法树节点, 数组
+    .局部变量 r, 抽象语法树节点, 数组
+    .局部变量 后续无穷, 抽象语法树节点, 数组
+
+    当前节点.初始化内存 (“nop”)
+    当前节点.设置语类 (#语类_nop)
+    .如果真 (下个词 ().内容 ≠ “*” 且 下个词 ().内容 ≠ “/”)
+        ' 调试输出 (“未匹配到*/中算符”)
+        返回 (当前节点)
+    .如果真结束
+    m = 父节点.生成自词节点 (下个词 ())
+    词游标自增 ()
+    
+    r = 匹配因子 (父节点)
+    
+    .如果真 (r.失败 ())
+        返回 (父节点.生成匹配失败节点 ())
+    .如果真结束
+    
+    
+    .如果 (下个词 ().类型 ≠ #词类_结尾)
+        后续无穷 = 匹配加后表达式右侧无穷 (r)
+        .如果真 (后续无穷.失败 ())
+            返回 (后续无穷)
+        .如果真结束
+        
+    .否则
+        后续无穷.初始化内存 (“nop”, )
+        后续无穷.设置语类 (#语类_nop)
+    .如果结束
+    
+    ' 调试输出 (下个词 ().类型)
+    m.设置父节点 (后续无穷)
+    m.添加参数节点 (r)
+    后续无穷.插入参数节点 (m)
+    m.设置语类 (#语类_函数调用)
+    
+    返回 (m)
+    
+
+.子程序 匹配因子, 抽象语法树节点
+    .参数 父节点, 抽象语法树节点
+    .局部变量 当前节点, 抽象语法树节点, 数组
+    .局部变量 左括号, 抽象语法树节点, 数组
+    .局部变量 中表达式, 抽象语法树节点, 数组
+    .局部变量 右括号, 抽象语法树节点, 数组
+    .局部变量 数字, 抽象语法树节点, 数组
+    .局部变量 函数, 抽象语法树节点, 数组
+    .局部变量 标识符, 抽象语法树节点
+
+    .判断开始 (下个词 ().类型 = #词类_括号)
+        .如果真 (下个词 ().内容 ≠ “(”)
+            返回 (父节点.生成匹配失败节点 ())
+        .如果真结束
+        左括号 = 当前节点.生成自词节点 (下个词 ())
+        词游标自增 ()
+        中表达式 = 匹配表达式 (当前节点)
+        .如果真 (下个词 ().内容 ≠ “)”)
+            返回 (父节点.生成匹配失败节点 ())
+        .如果真结束
+        
+        右括号 = 当前节点.生成自词节点 (下个词 ())
+        词游标自增 ()
+        当前节点.初始化内存 (“括号”, 父节点.获取当前节点指针 ())
+        当前节点.设置词类 (#词类_括号)
+        当前节点.添加参数节点 (中表达式)
+        返回 (当前节点)
+        
+    .判断 (下个词 ().类型 = #词类_数字)
+        数字 = 通用词匹配 (#词类_数字)
+        返回 (数字)
+        
+    .默认
+        ' 判断看起来真浑 非常担心一行放错了地方 还是写成普通的如果真吧
+    .判断结束
+    
+    函数 = 匹配函数 (当前节点)
+    .如果真 (函数.成功 ())
+        返回 (函数)
+    .如果真结束
+    
+    ' 函数的开头是标识符, 所以先尝试匹配下函数再去匹配标识符, 否则可能把
+    ' sin(x) 当成 sin 后面没了
+    .如果真 (下个词 ().类型 = #词类_标识符)
+        标识符 = 通用词匹配 (#词类_标识符)
+        标识符.设置语类 (#语类_实际参数)
+        返回 (标识符)
+    .如果真结束
+    
+    返回 (父节点.生成匹配失败节点 ())
+    
+
+.子程序 匹配函数, 抽象语法树节点
+    .参数 父节点, 抽象语法树节点
+    .局部变量 当前节点, 抽象语法树节点, 数组
+    .局部变量 标识符, 抽象语法树节点, 数组
+    .局部变量 参数, 抽象语法树节点, 数组
+    .局部变量 右侧无穷, 抽象语法树节点, 数组
+    .局部变量 括号内下一表达式, 抽象语法树节点, 数组
+
+    .如果真 (下个词 ().类型 ≠ #词类_标识符)
+        返回 (父节点.生成匹配失败节点 ())
+    .如果真结束
+    标识符 = 通用词匹配 (#词类_标识符)
+    
+    ' 现在标识符要么是函数的一部分, 要么是参数
+    .如果真 (下个词 ().内容 ≠ “(”)
+        标识符.设置语类 (#语类_实际参数)
+        返回 (标识符)
+    .如果真结束
+    标识符.设置语类 (#语类_函数调用)
+    词游标自增 ()
+    .如果真 (下个词 ().内容 = “)”)
+        词游标自增 ()
+        返回 (标识符)
+    .如果真结束
+    
+    参数 = 匹配表达式 (当前节点)
+    .如果真 (下个词 ().内容 = “)”)
+        标识符.添加参数节点 (参数)
+        词游标自增 ()
+        
+        返回 (标识符)
+    .如果真结束
+    标识符.添加参数节点 (参数)
+    
+    
+    .判断循环首 (真)
+        .如果真 (下个词 ().类型 ≠ #词类_逗号 或 假) ' 去掉「 或 假」后会触发e2txt的bug, 无法从.txt转回.e
+            返回 (父节点.生成匹配失败节点 ())
+        .如果真结束
+        词游标自增 ()
+        括号内下一表达式 = 匹配表达式 (当前节点)
+        .如果真 (括号内下一表达式.失败 ())
+            返回 (父节点.生成匹配失败节点 ())
+        .如果真结束
+        标识符.添加参数节点 (括号内下一表达式)
+        
+        .如果真 (下个词 ().内容 = “)”)
+            词游标自增 ()
+            跳出循环 ()
+        .如果真结束
+        
+    .判断循环尾 ()
+    返回 (标识符)
+
+.子程序 通用词匹配, 抽象语法树节点
+    .参数 词类型, 整数型, , #词类枚举
+    .局部变量 当前节点, 抽象语法树节点, 数组
+
+    当前节点.初始化内存 ()
+    
+    .如果 (下个词 ().类型 ≠ 词类型)
+        当前节点.释放结构内存 ()
+        返回 (当前节点.生成匹配失败节点 ())
+    .否则
+        当前节点.设置函数名 (下个词 ().内容)
+        当前节点.设置词类 (词类型)
+        词游标自增 ()
+        返回 (当前节点)
+    .如果结束
+    
+
+.子程序 下个词, 词
+    .局部变量 返回词, 词, 数组
+
+    .如果 (当前词游标 ≥ 取数组成员数 (词))
+        返回词.内容 = “”
+        返回词.类型 = #词类_结尾
+    .否则
+        返回词 = 词 [当前词游标 + 1]
+    .如果结束
+    
+    返回 (返回词)
+    
+
+.子程序 词游标自增
+    当前词游标 = 当前词游标 + 1
+    ' 调试输出 (格式化文本 (“游标增至 %d 下一个:(%d,%s)”, 当前词游标, 下个词 ().类型, 下个词 ().内容))
+    
+
+.子程序 词游标自减
+    当前词游标 = 当前词游标 - 1
+    ' 调试输出 (格式化文本 (“游标减至 %d 下一个:(%d,%s)”, 当前词游标, 下个词 ().类型, 下个词 ().内容))
+    
+
+.子程序 重复文本, 文本型
+    .参数 n, 整数型
+    .参数 s, 文本型
+    .局部变量 res, 文本型, 数组
+
+    res = “”
+    .计次循环首 (n, )
+        res = res + s
+    .计次循环尾 ()
+    返回 (res)
+    
+
+.子程序 输出语法分析结果
+    .参数 AST, 抽象语法树节点
+    .参数 当前层级, 整数型, 可空
+    .局部变量 i, 整数型, 数组
+
+    .如果真 (是否为空 (当前层级))
+        当前层级 = 0
+    .如果真结束
+    标准输出 (, 重复文本 (当前层级 × 2, “ ”))
+    标准输出 (, AST.生成展示文本 () + #换行符)
+    .计次循环首 (AST.获取参数数量 (), i)
+        输出语法分析结果 (AST.获取参数节点 (i), 当前层级 + 1)
+    .计次循环尾 ()
+    
+
+.子程序 语法分析并输出
+    .参数 表达式, 文本型
+    .局部变量 t0, 长整数型, 数组
+
+    t0 = 时间_取现行时间戳1 (真)
+    词法分析 (表达式, 词)
+    语法分析 (词)
+    标准输出 (, “用时 ” + 到文本 (时间_取现行时间戳1 (真) - t0) + “ms” + #换行符)
+    输出语法分析结果 (AST根)
+    
+    
+

+ 45 - 0
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/常量.e.txt

@@ -0,0 +1,45 @@
+.版本 2
+
+.常量 词类型枚举
+.常量 词类_未定义, "0"
+.常量 词类_数字, "1"
+.常量 词类_整数部分, "2"
+.常量 词类_小数部分, "3"
+.常量 词类_标识符, "4"
+.常量 词类_算符, "5"
+.常量 词类_括号, "6"
+.常量 词类_注释, "7"
+.常量 词类_逗号, "8"
+.常量 词类_双等号, "9"
+.常量 词类_单等号, "10"
+.常量 词类_空格, "11"
+.常量 词类型枚举数量, "11"
+.常量 词类_结尾, "99999"
+
+
+
+.常量 语法树节点_函数名最大长度, "32"
+.常量 语法树节点_函数名偏移, "0", , 长: 32
+.常量 语法树节点_语类, "32", , 长: 4
+.常量 语法树节点_词类, "36", , 长: 4
+
+.常量 语法树节点_参数量偏移, "40", , 长: 4
+.常量 语法树节点_参数容量偏移, "44", , 长: 4
+.常量 语法树节点_参数指针偏移, "48", , 长: 8
+.常量 语法树节点_父节点指针偏移, "56", , 长: 8
+.常量 语法树节点_长度, "64"
+.常量 语法树节点_参数容量初始值, "8"
+.常量 语法树节点_参数容量扩张系数, "2"
+.常量 语法树节点_匹配失败, "-1"
+
+.常量 语法类型枚举
+.常量 语类_未定义, "0"
+.常量 语类_定义, "1"
+.常量 语类_函数调用, "2"
+.常量 语类_函数原型, "4"
+.常量 语类_形式参数, "8"
+.常量 语类_实际参数, "16"
+.常量 语类_根, "32"
+.常量 语类_nop, "64"
+
+.常量 指针大小, "8"

+ 11 - 0
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/自定义类型.e.txt

@@ -0,0 +1,11 @@
+.版本 2
+
+.数据类型 词, 公开
+    .成员 内容, 文本型, 数组
+    .成员 类型, 整数型, 数组
+
+.数据类型 函数返回, 公开
+    .成员 函数名, 文本型
+    .成员 有效, 逻辑型
+    .成员 返回值, 双精度小数型
+

+ 12 - 0
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/资源/命令行帮助.txt

@@ -0,0 +1,12 @@
+--------
+> 帮助
+展示此帮助
+
+> 词法分析 [表达式]
+对[表达式]进行词法分析, 输出分析结果
+
+> 语法分析 [表达式] 
+对[表达式]进行语法分析, 输出语法树
+
+> 运行 [文件名]
+--------

+ 50 - 0
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/配置/支持库.config.json

@@ -0,0 +1,50 @@
+[
+    {
+        "CmdCount": 682,
+        "Guid": "d09f2340818511d396f6aaf844c7e325",
+        "Key": "krnln",
+        "MaxRefConstPos": 68,
+        "MaxRefObjectPos": 0,
+        "Name": "系统核心支持库",
+        "Version": {
+            "Major": 5,
+            "Minor": 7
+        }
+    },
+    {
+        "CmdCount": 13,
+        "Guid": "684944CB04624eb7BD5412A519421D34",
+        "Key": "RegEx",
+        "MaxRefConstPos": 0,
+        "MaxRefObjectPos": 2,
+        "Name": "正则表达式支持库",
+        "Version": {
+            "Major": 2,
+            "Minor": 0
+        }
+    },
+    {
+        "CmdCount": 11,
+        "Guid": "A512548E76954B6E92C21055517615B0",
+        "Key": "spec",
+        "MaxRefConstPos": 0,
+        "MaxRefObjectPos": 0,
+        "Name": "特殊功能支持库",
+        "Version": {
+            "Major": 3,
+            "Minor": 1
+        }
+    },
+    {
+        "CmdCount": 85,
+        "Guid": "F7FC1AE45C5C4758AF03EF19F18A395D",
+        "Key": "eAPI",
+        "MaxRefConstPos": 0,
+        "MaxRefObjectPos": 0,
+        "Name": "应用接口支持库",
+        "Version": {
+            "Major": 3,
+            "Minor": 1
+        }
+    }
+]

+ 23 - 0
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/配置/用户.config.json

@@ -0,0 +1,23 @@
+{
+    "Address": "",
+    "Author": "",
+    "BuilderVersion": {
+        "Major": 0,
+        "Minor": 0
+    },
+    "CompilePlugins": "",
+    "Copyright": "",
+    "Description": "",
+    "Email": "",
+    "ExportPublicClassMethod": false,
+    "FaxNumber": "",
+    "Homepage": "",
+    "Name": "",
+    "ReleaseVersion": {
+        "Major": 1,
+        "Minor": 0
+    },
+    "TelephoneNumber": "",
+    "WriteVersion": true,
+    "ZipCode": ""
+}

+ 13 - 0
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/配置/系统.config.json

@@ -0,0 +1,13 @@
+{
+    "Lang": 1,
+    "ProjectType": 1,
+    "ProjectVersion": {
+        "Major": 1,
+        "Minor": 7
+    },
+    "Type": 1,
+    "Version": {
+        "Major": 5,
+        "Minor": 6
+    }
+}

+ 16 - 0
4. 抽象语法树编译到 llvm/抽象语法树编译到 llvm.代码/项目.etprj

@@ -0,0 +1,16 @@
+{
+    "AsyncFile": false,
+    "Dest": "",
+    "E2TXT-EFile": "",
+    "E2TXT-InSourceDir": true,
+    "E2TXT-IsCreateE": true,
+    "Encoding": "UTF-8",
+    "Level": 1,
+    "NameStyle": 2,
+    "Password": "",
+    "ResetNames": [],
+    "Source": "../³éÏóÓï·¨Ê÷±àÒëµ½ llvm.e",
+    "TXT2E-CreateLog": true,
+    "TXT2E-EFile": "´úÂë.e",
+    "TXT2E-InSourceDir": true
+}