此刻支持的语法
if 0 {
print(1)
} elif 0 {
print(2)
} else {
print(3)
}
print(6) if 1
项目地址仍在此。
接续上文,添加条件语句。暂未实现布尔值与比较语法,于是暂用数字代替。0 为假,非 0 为真,这与 Python 相同。
吃过上次的亏,于是小心地在词法规则的适当位置加了如下规则(细节如为何 if 前后有 \b 但没有 \s* 等等还需回头研究),另外仍然不知flags=(re.DOTALL)
有何用:
分词器母机.add('如果', '\\bif\\b')
分词器母机.add('否则如果', '\\r*\\n*\\s*elif\\s*\\r*\\n*')
分词器母机.add('否则', '\\r*\\n*\\s*else\\s*\\r*\\n*')
最简单的测试:
if 1{print(3)}
结果没过,只识别出了第一个if
:
$ python 中.py 测试/条件.ul
Token('如果', 'if')
Traceback (most recent call last):
File "中.py", line 18, in <module>
查看(各词)
File "中.py", line 10, in 查看
for 词 in 各词:
File "/opt/miniconda3/envs/prototype/lib/python3.7/site-packages/rply/lexer.py", line 60, in __next__
return self.next()
File "/opt/miniconda3/envs/prototype/lib/python3.7/site-packages/rply/lexer.py", line 57, in next
raise LexingError(None, SourcePosition(self.idx, -1, -1))
rply.errors.LexingError: (None, SourcePosition(idx=2, lineno=-1, colno=-1))
貌似是空格问题,试出来是缺了这句导致的:
分词器母机.ignore('[ \t\r]+')
如果仅处理空格,就是这样也可以:
分词器母机.ignore('[ ]+')
发现之前的测试用例中还没有出现过空格(非换行),于是加了这个测试:
print(2 )
果然同样报错:
rply.errors.LexingError: (None, SourcePosition(idx=7, lineno=-1, colno=-1))
idx 就是出错的位置,也就是第一个空格所在位置。加了上面的 ignore 规则,所有空格就都被忽略(还是作为分隔符?)
语法添加规则如下( parser 实现中貌似与规则顺序无关):
声明 : 条件声明
条件声明 : 如果 表达式 块 否则如果声明
| 如果 表达式 块 否则 块
| 声明 如果 表达式
否则如果声明 :
| 否则如果 表达式 块 否则如果声明
| 否则如果 表达式 块 否则 块
实现上,转换为 Python 的 if 语句:
@分析器母机.production('条件声明 : 如果 表达式 块 否则如果声明')
@分析器母机.production('条件声明 : 如果 表达式 块 否则 块')
@分析器母机.production('否则如果声明 : ')
@分析器母机.production('否则如果声明 : 否则如果 表达式 块 否则如果声明')
@分析器母机.production('否则如果声明 : 否则如果 表达式 块 否则 块')
def 条件声明(片段):
if len(片段) == 0:
return []
否则部分 = 片段[-1]
return 语法树.如果(
条件=片段[1],
主体=片段[2],
否则=否则部分 if isinstance(否则部分, list) else [否则部分],
片段=片段)
这里的否则=否则部分 if isinstance(否则部分, list) else [否则部分],
至今还没全想清楚,因为牵涉到嵌套。真是自己写的话,肯定要费大劲。
走马观花,先过。