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

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

内容简介:上周试用木兰语言加 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 ( ),可以移入 (

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


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

查看所有标签

猜你喜欢:

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

Automate This

Automate This

Christopher Steiner / Portfolio / 2013-8-9 / USD 25.95

"The rousing story of the last gasp of human agency and how today's best and brightest minds are endeavoring to put an end to it." It used to be that to diagnose an illness, interpret legal docume......一起来看看 《Automate This》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具