|
@@ -62,6 +62,32 @@
|
|
|
end
|
|
|
```
|
|
|
|
|
|
+至于匹配, 是用正则表达式做的, 这一部分当然也能手写, 但是太无聊了, 手写留到下部一份词法分析吧, 那地方更有价值一些. 正则如下:
|
|
|
+
|
|
|
+```
|
|
|
+.版本 2
|
|
|
+.支持库 RegEx
|
|
|
+
|
|
|
+' 可能带°的数字 (\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___ -> 逗号
|
|
|
+```
|
|
|
+
|
|
|
这样一趟后就得到了这样的结果
|
|
|
|
|
|
```
|
|
@@ -108,6 +134,7 @@ a + b -> +(a, b)
|
|
|
- 原始文本, debug用
|
|
|
- 函数名
|
|
|
- 参数数组, 类型为节点
|
|
|
+- 父节点, 类型为节点
|
|
|
|
|
|
但是很遗憾, 这样的代码会报递归定义错误, 我又没找到怎么把一个指针重新解释成某个自定义类型<sup>等我开始扩展易语言语法的时候首先要处理这个事情</sup>, 那只能自己申请内存管理数据了, 按C的写法数据结构定义如下:
|
|
|
|
|
@@ -142,10 +169,10 @@ a + b -> +(a, b)
|
|
|
# + 与正则表达式内星号含义相同, 指匹配至少1次
|
|
|
# | 表 或.
|
|
|
|
|
|
-表达式 := 加后表达式 (("+" | "-") 加后表达式)*
|
|
|
-加后表达式 := 因子 (("*" | "/") 因子)*
|
|
|
-因子 := 左括号 表达式 右括号 | 函数 | 数字
|
|
|
-函数 := 标识符 左括号 (表达式 (逗号 表达式)*){0,1} 右括号
|
|
|
+表达式 ::= 加后表达式 (("+" | "-") 加后表达式)*
|
|
|
+加后表达式 ::= 因子 (("*" | "/") 因子)*
|
|
|
+因子 ::= 左括号 表达式 右括号 | 函数 | 数字
|
|
|
+函数 ::= 标识符 左括号 (表达式 (逗号 表达式)*){0,1} 右括号
|
|
|
|
|
|
```
|
|
|
光写出来构造还是蛮简洁的, 匹配表达式时可以沿着`表达式->加后表达式->因子->函数->表达式`走, 这就是递归下降里的递归含义, 而下降则是指自顶向下慢慢解析. 如果你足够敏锐, 一定能意识到这个流程可能出现无限循环, 这就是左递归问题, 好在上面所提到的数学表达式是LL(1)文法(从左往右每次多看1个词就可以确定究竟是什么), 脑子不糊涂一般不会写出来无限循环. 对于更复杂的情况, 可以上LL(k)解析器, 尽量多看几个. 不过还有一些其他处理方法, 后面再提.
|