【项目开源在 Gitee:木兰编程语言/mulan-rework】
去年对木兰编程语言的报错信息作了 初步中文化与内容改进,原因见前文《一岁了!》。积累了几十个用例但一直没有纳入自动测试,本周整理后纳入了 Gitee 流水线测试,期间重温了各个报错信息性质,小结如下。
报错分类
词法分析、语法分析、编译为可执行码(用 Python 的 compile 方法)、运行(用 Python 的 exec 方法)四个阶段都会报错,逐个举例。
- 词法分析
# c = 3
【给出行列号】分词时没认出这个词 "#" - 语法分析
a = ["1",]
【给出行列号】没认出这个词 "]" - 编译
例一:print(2)=3
ValueError: expression which can't be assigned to in Store context
例二:return
语法错误: 'return' outside function (函数外return.ul, line 1) - 运行时
print("1" + 2)
字符串只能拼接字符串,请将“int”先用 str() 转换
见第1行:print("1" + 2)
可用性分析
- 词法或语法分析的报错信息内容相似,但是否在“分词时”认不出 token 恐怕对语言开发者更有用。最终用户应该只在乎为何认不出,以及如何修改。
- 例子中可见,一些报错信息并未指向问题源头。比如
a = ["1",]
是因为 ] 之前多了个逗号。这种报错对用户并不友好。 - 与上一条相关,在定位偏差之外,很多时候并未给出修改建议,这应该是用户最关心的。
- 部分报错信息尚未中文化,尤其像某些编译时的报错非常晦涩,还有很大改进空间。
- 之前的分词例子实际还包含了如下大块的回溯信息,这些对最终用户来说无大价值
Traceback (most recent call last):
File "/opt/anaconda3/lib/python3.7/site-packages/木兰/分析器/语法分析器.py", line 1037, in 分析
节点 = self.分析器.parse(各词, state=self)
【略去六行】
rply.errors.LexingError: (None, SourcePosition(idx=12, lineno=3, colno=6))
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/opt/anaconda3/bin/木兰", line 8, in <module>
sys.exit(中())
【略去四行】
木兰.分析器.错误.词法错误: 文件 "测试/错误处理/词不识.ul", 第3行, 第6列, 分词时没认出这个词 "#"
# c =✋ 3
之后需针对这几项在使用中逐步改进。
附:代码量统计
主要部分的代码行数统计,格式为:上次->现在。
- 木兰代码量 3349 -> 3324
- 运行环境,实现与测试大部为木兰代码:582
- 木兰测试用例,包括部分实用小程序(如井字棋):2767 -> 2742 (报错信息测试用例替代了源码中的注释)
- Python 代码量(木兰实现与测试框架):2816 -> 2934
测试/期望值表.py
:135 -> 144功用/反馈信息.py
:75 -> 81测试/unittest/报错.py
:117测试/unittest/语法树.py
,确保生成的语法树与原始版本一致,拆分报错部分:88 -> 58- 未变
分析器/语法分析器.py
:1049分析器/语法树.py
:225分析器/词法分析器.py
:216环境.py
,定义全局方法: 174交互.py
,交互环境(REPL):148分析器/语法成分.py
,从语法分析器中提取出来的枚举常量:85中.py
,主程序:74测试/运行所有.py
,检验所有木兰测试代码片段:71功用/调试辅助.py
,:57setup.py
, 34测试/unittest/交互.py
,交互环境相关测试:28测试/unittest/所有用例.py
:24分析器/错误.py
:26