木兰语言 0.0.17.2 实现简易网页浏览器,又一次碰到语法歧义

栏目: 软件资讯 · 发布时间: 3年前

内容简介:上周试用木兰语言加 QtWebkit 实现简易网页浏览器(已开源在 Gitee ,81 行代码)时,发现需要复现带参数的 super: super(演示, self).__init__() 实现过程中,又一次遇到了这个头疼的报错: ParserGenerato...

上周试用木兰语言加 QtWebkit 实现简易网页浏览器(已开源在 Gitee ,81 行代码)时,发现需要复现带参数的 super:

super(演示, self).__init__()

实现过程中,又一次遇到了这个头疼的报错:

ParserGeneratorWarning: 1 shift/reduce conflict 

去年碰到过几次,都是通过照着逆向工程设置词的优先级来规避,没有深究调试方法,这次决定下点功夫搞清楚缘由。

rply 的调试信息有限,貌似 七年前就是如此,包括 shift/reduce 在内的所有信息都极简,项目现在似乎也没有什么改进的迹象。由于它是参考 ply 重写的,于是查看了 ply 对歧义语法的调试信息示例。纠结了一下是把木兰用 ply 重写还是修改 rply 来获得类似调试信息,决定走后者。

这里记一下:任何框架或工具,包括编程语言,可调试性——即告知用户“哪儿出错了?”——对于可用性非常非常重要。任何的反馈信息,包括警告、报错,都应以用户可理解、问题可定位、提供解决方案为首要目标。

首先,分别创建了 plyrply 的最简歧义演示。语法如下(ply 不支持在语法定义中使用中文标识符,下面是 rply 的表示):

表达式 : 数
表达式 : 表达式 减 表达式 

测试表达式为 2 - 3 - 4。在没有优先级设置时,会报警:1 shift/reduce conflict 而且输出:3

在 ply 的 parser.out 文件中,可以看到进一步细节:

state 4

    (1) expression -> expression MINUS expression .
    (1) expression -> expression . MINUS expression

  ! shift/reduce conflict for MINUS resolved as shift
    $end            reduce using rule 1 (expression -> expression MINUS expression .)
    MINUS           shift and go to state 3

  ! MINUS           [ reduce using rule 1 (expression -> expression MINUS expression .) ] 

根据 ply 官方文档,可以估摸出是第二个减号有歧义,可以先将 2-3 化简为“expression”,也可以将减号接在 3 后面,作为 expression . MINUS expression 的一部分。在有此类歧义时,默认 shift 而不化简。因此,待 3-4 都解析完后化为 expression,求值为 -1,再将 2-(-1) 化简求值为 3。

这里注意到,这个报警信息与具体的测试表达式无关。在语法分析器生成时,会根据语法定义生成所有可能的语法要素序列,在此基础上发现所有歧义。另一方面也好奇,是否能够进一步生成能够复现歧义的表达式用例,这样应该可以更方便开发者调试吧。

接下来,就是在 rply 源码内加入调试信息输出(开源在此)。可以看到下面的 5 个序列:

0[LRItem(S' -> . 表达式), LRItem(表达式 -> . 数), LRItem(表达式 -> . 表达式 减 表达式)]
1[LRItem(表达式 -> 数 .)]
2[LRItem(S' -> 表达式 .), LRItem(表达式 -> 表达式 . 减 表达式)]
3[LRItem(表达式 -> 表达式 减 . 表达式), LRItem(表达式 -> . 数), LRItem(表达式 -> . 表达式 减 表达式)]
4[LRItem(表达式 -> 表达式 减 表达式 .), LRItem(表达式 -> 表达式 . 减 表达式)] 

以及歧义相关的序列和词:4 》》 '减',即:4[LRItem(表达式 -> 表达式 减 表达式 .), LRItem(表达式 -> 表达式 . 减 表达式)] 中的减号,句点含义与 ply 中相同,这样包含的信息已接近了 ply 的。

回头看 super 语法,整理后的输出如下:

词'('有歧义,默认进行 shift2
歧义序列:
        超类: super .
        超类: super . 实参部分
        实参部分: . ( )
        实参部分: . ( 各实参 ) 

仍然看不大清,简化了 实参部分 语法后,仍然有歧义:

词'('有歧义,默认进行 shift2
歧义序列:
        超类: super .
        超类: super . 实参部分
        实参部分: . ( ) 

继续简化:

词'('有歧义,默认进行 shift2
歧义序列:
        超类: super .
        超类: super . ( ) 

到这里看出,其实很简单,没有优先级设置时,super() 有两种解析方式:

步骤 符号栈 词输入 行为
1   super ( ) 移入 super
2 super ( )

歧义:
1)根据 超类: super,可以直接消减(reduce)为 超类

2) 根据 超类: super ( ),可以移入 (

问题确定之后,就是如何确定优先级高低,待继续研究。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

服务设计与创新实践

服务设计与创新实践

宝莱恩 (Andy Polaine)、乐维亚 (Lavrans Lovlie)、里森 (Ben Reason) / 王国胜、张盈盈、付美平、赵芳 / 清华大学出版社 / 2015-6-1 / CNY 69.00

产品经济的时代渐行渐远,在以服务为主导的新经济时代,在强调体验和价值的互联网时代,如何才能做到提前想用户之所想?如何比用户想得更周到?如何设计可用、好用和体贴的服务?这些都可以从本书中找到答案。本书撷取以保险业为代表的金融服务、医疗服务、租车及其他种种服务案例,从概念到实践,有理有据地阐述了如何对服务进行重新设计?如何将用户体验和价值提前与产品设计融合在一起? 《服务设计与创新实践》适合产品......一起来看看 《服务设计与创新实践》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具