编译原理词法解析器开发脚本解释器必备

易语言 2020-02-24 19:46:45

编译原理词法解析器开发脚本解释器必备

.子程序 CreateTree_Start, 整数型, 公开, 开始创建树,编码必须是UTF-8,树全部生成返回1,中途终止返回0
.参数 CodeText, 文本型, , 源代码
.参数 CallBack, 整数型, , 回调函数,每次识别成功都会调用这个函数
.参数 Type, 文本型, , 留空 = 通常,a = 不转义,b = 不识别字符串,多选可以将这些值合并
.局部变量 字符数组, 文本型, , "0"
.局部变量 临时文本, 文本型
.局部变量 n, 整数型
.局部变量 cb, 子程序指针
.局部变量 当前行, 整数型
.局部变量 ifre, 整数型
.局部变量 cbre, 整数型, , , call back 返回 ,返回 1 按通常处理 , 返回0结束,返回2进入下一次循环 ,返回2需要用户自行判断情况,否则容易导致崩溃
.局部变量 zyre, 文本型, , , 转义返回

' 想看具体输出,可以去 CallBack 函数看
cb = 整数到指针 (CallBack)
文本_逐字分割 (CodeText, 字符数组)
加入成员 (字符数组, 到文本 ({ 0 })) ' \0
' 调试输出 (字符数组)
n = 1
当前行 = 1
.判断循环首 (字符数组 [n] ≠ 到文本 ({ 0 })) ' 判断不是数组结尾
.如果 (是字母 (字符数组 [n]) 或 是中文 (字符数组 [n]))
临时文本 = 临时文本 + 字符数组 [n]
' 当下一个字符不为字母或数字,则停止扫描,并将扫描结果存入 临时文本
.判断循环首 (是字母 (字符数组 [n + 1]) 或 是数字 (字符数组 [n + 1]) 或 是中文 (字符数组 [n + 1]))
n = n + 1
临时文本 = 临时文本 + 字符数组 [n]
.判断循环尾 ()
' 判断 临时文本 是否为保留字(如果,否则,整数,文本),否则为标识符
ifre = 是保留字 (临时文本)

.如果 (ifre ≠ -1)
调试输出 (“保留字[” + 到文本 (ifre) + “,” + 临时文本 + “]”)
调用子程序 (cb, , cbre, ifre, 临时文本, 当前行)
.如果真 (cbre = 0) ' 返回0,终止运行
返回 (0)
.如果真结束
.如果真 (cbre = 2) ' 进入下一次循环
到循环尾 ()
.如果真结束

.否则
调试输出 (“标识符[” + 到文本 (100) + “,” + 临时文本 + “]”)
调用子程序 (cb, , cbre, 100, 临时文本, 当前行)
.如果真 (cbre = 0) ' 返回0,终止运行
返回 (0)
.如果真结束
.如果真 (cbre = 2) ' 进入下一次循环
到循环尾 ()
.如果真结束

.如果结束

.否则
' 当开头为数字时,可能为整数或小数
.如果 (是数字 (字符数组 [n]))
临时文本 = 临时文本 + 字符数组 [n]
.判断循环首 (是数字 (字符数组 [n + 1]))
n = n + 1
临时文本 = 临时文本 + 字符数组 [n]
.判断循环尾 ()
' 如果有小数点
.如果 (字符数组 [n + 1] = “.”)
n = n + 1
' 如果小数点后无数字,报错
.如果 (是数字 (字符数组 [n + 1]) = 假)
调试输出 (“错误:小数点后无数字”)
调用子程序 (cb, , cbre, -1, “第” + 到文本 (当前行) + “行存在错误,原因:小数点后无数字”, 当前行)
临时文本 = “”
.如果真 (cbre = 0) ' 返回0,终止运行
返回 (0)
.如果真结束
.如果真 (cbre = 2) ' 进入下一次循环
到循环尾 ()
.如果真结束

' 就算不返回 2 也是到循环尾,嘻嘻
到循环尾 ()
.否则
' 继续扫描数字
临时文本 = 临时文本 + 字符数组 [n]
.判断循环首 (是数字 (字符数组 [n + 1]))
n = n + 1
临时文本 = 临时文本 + 字符数组 [n]
.判断循环尾 ()

.如果结束
调试输出 (“小数[103,” + 临时文本 + “]”)
' ms.键 = 6
' ms.值 = 临时文本
' 加入成员 (结果数组, ms)
调用子程序 (cb, , cbre, 103, 临时文本, 当前行)
.如果真 (cbre = 0) ' 返回0,终止运行
返回 (0)
.如果真结束
.如果真 (cbre = 2) ' 进入下一次循环
到循环尾 ()
.如果真结束

.否则
调试输出 (“整数[102,” + 临时文本 + “]”)
' ms.键 = 6
' ms.值 = 临时文本
' 加入成员 (结果数组, ms)
调用子程序 (cb, , cbre, 102, 临时文本, 当前行)
.如果真 (cbre = 0) ' 返回0,终止运行
返回 (0)
.如果真结束
.如果真 (cbre = 2) ' 进入下一次循环
到循环尾 ()
.如果真结束

.如果结束

.否则
' 既不是数字也不是字母也不是空格,则为界符或运算符,跳过空
.如果 (字符数组 [n] ≠ “ ”)
临时文本 = 临时文本 + 字符数组 [n]
' 由于界符只有一个字符长度,则 临时文本 放入一个字符后直接开始匹配界符数组
' 匹配成功则跳出循环,匹配失败则继续扫描
ifre = 是界符 (临时文本)
.如果 (ifre ≠ -1)
' 判断是否为换行符,用于记录当前行
.如果真 (临时文本 = 到文本 ({ 10 }) 或 临时文本 = 到文本 ({ 13, 10 }))
当前行 = 当前行 + 1
.如果真结束
' 2019年1月13日13:09:23 获取字符串
.如果 (临时文本 = #引号 且 寻找文本 (Type, “b”, , 假) = -1) ' 有b是不识别字符串
临时文本 = “”
.判断循环首 (字符数组 [n + 1] ≠ #引号)
.如果真 (寻找文本 (Type, “a”, , 假) = -1)
' 转义
.如果真 (字符数组 [n + 1] = “\”)
n = n + 1
zyre = 是转义符 (字符数组 [n + 1])
.如果 (zyre ≠ “error”)
.如果真 (zyre = “”)
' 不转义
临时文本 = 临时文本 + “\”
到循环尾 ()
.如果真结束
n = n + 1
临时文本 = 临时文本 + zyre
到循环尾 ()
.否则
' 不存在或非法的转义符
调试输出 (“非法转义字符”)
调用子程序 (cb, , , -1, “第” + 到文本 (当前行) + “行存在错误,原因:非法的转义字符” + #左引号 + “\” + 字符数组 [n + 1] + #右引号, 当前行)
' 这里不要清除 临时文本
' 留着下面的报错用
.如果真 (cbre = 0) ' 返回0,终止运行
返回 (0)
.如果真结束
.如果真 (cbre = 2) ' 进入下一次循环
到循环尾 ()
.如果真结束

.如果结束
到循环尾 ()
.如果真结束


.如果真结束

n = n + 1
临时文本 = 临时文本 + 字符数组 [n]

' 这个是防止数组越界
.如果真 (n + 1 > 取数组成员数 (字符数组))
调试输出 (“字符串没有结尾”)
调用子程序 (cb, , , -1, “第” + 到文本 (当前行) + “行存在错误,原因:字符串” + #左引号 + 临时文本 + #右引号 + “缺少引号结尾,继续向下解析会导致数组越界,已终止进程”, 当前行)
返回 (0) ' 因为比较危险,也容易出BUG,所以不判断返回值,直接强制返回
' 跳出循环 ()
.如果真结束

.判断循环尾 ()
n = n + 1
调试输出 (“字符串[101,” + 临时文本 + “]”)
' ms.键 = 5
' ms.值 = 临时文本
' 加入成员 (结果数组, ms)
调用子程序 (cb, , cbre, 101, 临时文本, 当前行)
临时文本 = “”
.如果真 (cbre = 0) ' 返回0,终止运行
返回 (0)
.如果真结束
.如果真 (cbre = 2) ' 进入下一次循环
到循环尾 ()
.如果真结束

.否则
调试输出 (“界符[” + 到文本 (ifre) + “,” + 临时文本 + “]”)
' ms.键 = 1
' ms.值 = 临时文本
' 加入成员 (结果数组, ms)
调用子程序 (cb, , cbre, ifre, 临时文本, 当前行)
临时文本 = “”
n = n + 1
.如果真 (cbre = 0) ' 返回0,终止运行
返回 (0)
.如果真结束
.如果真 (cbre = 2) ' 进入下一次循环
到循环尾 ()
.如果真结束
到循环尾 ()
.如果结束

.否则
' 判断是否为运算符
.判断循环首 (是界符 (字符数组 [n + 1]) = -1 且 是数字 (字符数组 [n + 1]) = 假 且 是字母 (字符数组 [n + 1]) = 假 且 是中文 (字符数组 [n + 1]) = 假 且 字符数组 [n + 1] ≠ “ ”)
n = n + 1
临时文本 = 临时文本 + 字符数组 [n]
.判断循环尾 ()
' 与运算符数组匹配,匹配成功,则为运算符,失败,则可能出现了检测不了的字符
ifre = 是运算符 (临时文本)
.如果 (ifre ≠ -1)
调试输出 (“运算符[” + 到文本 (ifre) + “,” + 临时文本 + “]”)
' ms.键 = 3
' ms.值 = 临时文本
' 加入成员 (结果数组, ms)
调用子程序 (cb, , cbre, ifre, 临时文本, 当前行)
.如果真 (cbre = 0) ' 返回0,终止运行
返回 (0)
.如果真结束
.如果真 (cbre = 2) ' 进入下一次循环
到循环尾 ()
.如果真结束

.否则
调试输出 (“无法识别的字符”)
调用子程序 (cb, , cbre, -1, “第” + 到文本 (当前行) + “行存在错误,原因:无法识别的字符” + #左引号 + 临时文本 + #右引号, 当前行)
.如果真 (cbre = 0) ' 返回0,终止运行
返回 (0)
.如果真结束
.如果真 (cbre = 2) ' 进入下一次循环
到循环尾 ()
.如果真结束

.如果结束

.如果结束

.否则


.如果结束

.如果结束

.如果结束
临时文本 = “”
n = n + 1
.判断循环尾 ()