此刻支持的语法示例:
sum = 0
number = 1
while number < 4 {
sum = sum + number
number = number + 1
}
print(sum)
添加了比较(包括且、或)、while循环相关语法,详见语法描述。一个有意思的细节是支持这样的布尔操作:xx or yy and zz
,其中and
优先级高。
RPly 源码中,看到词法分析的机制很单纯。就是按顺序匹配词法规则中的正则表达式, 匹配的就识别为一个词。难怪之前词法规则的添加顺序不同直接影响分析结果。词法规则设计感觉挺容易出错,回头研究下有没有啥辅助工具。
参照逆向工程,做了一下代码整理,以尽量接近源码结构,以便今后更加方便对比。包括将词法分析器提取到单独文件,将语法分析规则的顺序调整为与逆向相同。在此过程中,居然发现了两处语法分析规则的错误,其中一处比较严重:
表达式声明 : 表达式 <---- 此处木兰原本为“表达式前缀”(prefix_expr)
赋值 : 表达式前缀 = 表达式
表达式 : 二元表达式
| 表达式前缀
| 数
表达式前缀 : 变量
| 调用
在改正之前,像“2”(数)、“2+1”(二元表达式)这样的表达式是单一“表达式声明”的合法代码。而改为“表达式前缀”后,这些都不合法,也导致了不少相关测试需要修改(还好早发现)。
BTW 木兰交互控制台(REPL)中支持运行2+1
是因为套了层 print:
node = self.parser.parse('___=(%s);__print__(___)' % self.stmt, '<STDIN>')
这样设计暂时没看出啥硬伤,也许还有些好处。比如下面这样的 Python 代码是可运行的,输出为 2。但也许程序员原本希望看到的是 3,只是误写代码:
a = 2
a + 1
print(a)
而在木兰中,同样的代码运行会报错(报错信息是大短板):
SyntaxError: File "xxx.ul", line 2:3, unexpected token "+"
a + 1
^
从这个角度来说,这样的设计似乎可以更早发现不必要的代码误写。
语法分析器 220 行(不包括 ast 库的 API 中文封装部分),还早着。