.版本 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根)
    
    

