本文主要说明LR解析过程中关于BNF的典型冲突如何在LR中解决

冲突一般分为两种:

  • shift/reduce错误
  • redure/redure错误

下面分别解释两种冲突

1. shift/reduce错误

这种错误是因为 分析器在这种情况下不知道是归约还是移进导致的。

2. redure/redure错误

这种错误是因为,解析器在解析栈中规则时发现有多个规则可以进行归约。rejected rule 会指出跟哪个rule冲突

我们首先举个例子。

例子1

文法如下: 这是一个简单的解析

"<><><><>"

"<>"

""

class classnam {}

def p_start(p):
'''
start : typeArguments
''' def p_typeArguments(p):
'''
typeArguments : typeArgument
| typeArguments typeArgument
''' def p_typeArgument(p):
'''
typeArgument : LESS MORE
| empty
''' def p_empty( p ):
'''empty : '''

这时产生的错误。

WARNING:
WARNING: Conflicts:
WARNING:
WARNING: shift/reduce conflict for LESS in state 0 resolved as shift
WARNING: shift/reduce conflict for LESS in state 2 resolved as shift
WARNING: reduce/reduce conflict in state 2 resolved using rule (start -> typeArguments)
WARNING: rejected rule (empty -> <empty>) in state 2

那么下面看看如何来解决这个问题。

def p_start(p):
'''
start : typeArguments
| empty
''' def p_typeArguments(p):
'''
typeArguments : typeArgument
| typeArguments typeArgument
''' def p_typeArgument(p):
'''
typeArgument : LESS MORE
''' def p_empty( p ):
'''empty : '''

这个问题出现在

def p_typeArgument(p):
'''
typeArgument : LESS MORE
| empty
'''

身上,因为empty比较特殊可以告诉yacc可以reduce,因为结束了。而LESS还需要shift.

而在 typeArgument 身上也出现了一个问题就是到底 typeArgument是redure成empty还是 LESS MORE形式。

例子2

def p_start(p):
'''
start : typeArguments
''' def p_typeArguments(p):
'''
typeArguments : typeArgument
| typeArguments typeArgument
''' def p_typeArgument(p):
'''
typeArgument : LESS MORE
| list
''' def p_list(p):
'''
list : LESS MORE
''' def p_empty( p ):
'''empty : '''

这个问题是比较典型的redure冲突

出现在 typeArgument和list的冲突上。

WARNING:
WARNING: Conflicts:
WARNING:
WARNING: reduce/reduce conflict in state 7 resolved using rule (typeArgument -> LESS MORE)
WARNING: rejected rule (list -> LESS MORE) in state 7
WARNING: Rule (list -> LESS MORE) is never reduced

这种情况就是因为在一个规则树中出现了两个同样的规则在同一个里面。

例子3

这个例子算是一个较为经典的shift/redure的问题。

expression : expression PLUS expression
| expression MINUS expression
| expression TIMES expression
| expression DIVIDE expression
| LPAREN expression RPAREN
| NUMBER

如果我们不只用优先级来定义,那么我们可以如下方法解决优先级别的问题:

def p_start(p):
'''
start : expression
''' def p_expression(p):
'''
expression : multExpression
| expression PLUS multExpression
| expression MINUS multExpression
''' def p_multExpression(p):
'''
multExpression : subExpression
| multExpression TIMES subExpression
| multExpression DIVIDE subExpression
''' def p_subExpression(p):
'''
subExpression : LPAREN expression RPAREN
| primary
''' def p_primary(p):
'''
primary : NUMBER
'''

在java中也可以使用如上方法来定义一个expression来完成整个expression树的解析过程。因为过于复杂,所以这里不就写了,有兴趣的可以看java 7 lanaguage

上面3个例子都比较典型,基本能把大部分书写LR文法的时候遇到的问题解决掉。

参考:https://www.ituring.com.cn/article/52229

LR编写grammar中的问题和解决方法的更多相关文章

  1. PowerShell因为在此系统中禁止执行脚本解决方法

    PowerShell因为在此系统中禁止执行脚本解决方法   在Powershell直接脚本时会出现: 无法加载文件 ******.ps1,因为在此系统中禁止执行脚本.有关详细信息,请参阅 " ...

  2. (转)ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务 的解决方法

    早上同事用PL/SQL连接虚拟机中的Oracle数据库,发现又报了"ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务"错误,帮其解决后,发现很多人遇到过这样的问 ...

  3. ORA-01652:无法通过128(在表空间temp中)扩展temp段 解决方法

    ORA-01652:无法通过128(在表空间temp中)扩展temp段 解决方法 (2016-10-21 16:49:53)   今天在做一个查询的时候,报了一个"ORA-01652无法通过 ...

  4. Oracle中的 UPDATE FROM 解决方法

    转:http://www.cnblogs.com/JasonLiao/archive/2009/12/23/1630895.html Oracle中的 UPDATE FROM 解决方法 在表的更新操作 ...

  5. win7 安装过程中遇到的错误解决方法

    win7 安装过程中遇到的错误解决方法 windows安装无法继续.若要安装windows 请单击 确定 重新启动计算机: 当 出现如上提示的时候,按下shift+f10 会打开命令窗口,进入到C:\ ...

  6. [转载]Ubuntu 14.04中root 密码忘记解决方法

      Ubuntu 14.04中root 密码忘记解决方法 方法一: 如果用户具有sudo权限,那么直接可以运行如下命令: #sudo su root #passwd #更改密码 或者直接运行sudo ...

  7. oracle中can not set解决方法

    原因:set autotrace on和set trimspool on在pl\sql中使用不了 解决方法:在window环境中,使用cmd命令,sqlplus user_name/password@ ...

  8. 【转】eclipse中window->preference选项中没有tomcat的解决方法

    eclipse中window->preference选项中没有tomcat的解决方法 2011-09-09 13:46:35|  分类: eclipse|字号 订阅 其实一共有好几种方法,这只是 ...

  9. Oracle更新表字段时内容中含有特殊字符&的解决方法

    今天在做 Oracle表字段更新时出现了特殊字符&,导致无法更新. 这个问题是第二次碰到了,所以在此记录下,以备后用. 举例: update t set col1='A&B' wher ...

随机推荐

  1. Qemu-4.1 桥接网络设置

    参考: [qemu] qemu旧的net参数已经不再可用了,新的这样用. QEMU's new -nic command line option 用Qemu模拟vexpress-a9 --- 配置 q ...

  2. 调试CEF3程序的方法

    CEF3多进程模式调试时按F5只会启动调试Browser进程,要调试Renderer进程就要让进程在启动时就暂停并附加进程. 所幸google早就想到了这一点,chrome的命令行参数就可以办到, - ...

  3. 201671030129 周婷 实验十四 团队项目评审&课程学习总结

    项目 内容 这个作业属于哪个课程 软件工程 这个作业的要求在哪里 团队项目评审&课程学习总结 课程学习目标 (1)完成项目验收(2)反思总结课程学习内容 1.对<实验一 软件工程准备&g ...

  4. destoon搜索伪静态失败解决办法

    今天给一个朋友调试DT6.0内核的站点,搜索中文出现http 403 forbidden,找了半天,很纳闷,最后一个一个查看源代码总算找到,在此分享给大家! 解决的方法: 1.找到include/sa ...

  5. andrlid 处理大图片思路,未实践

    Loading Large Bitmaps Efficiently 先不解码,读取image的宽高,然后降采样显示图片. 参考:http://developer.android.com/trainin ...

  6. (二)STM32开发例程

    1控制LED和继电器 除了 PA11和PA12其他都可以 void setup() { pinMode(PC13, OUTPUT); pinMode(PC14, OUTPUT); pinMode(PC ...

  7. freeradius编译安装+mysql配置

    参考文档: freeradius 官网的wikihttp://wiki.freeradius.org/Home ubuntu freeradius搭建教程 http://yustanto.com/fr ...

  8. 从一段文字中提取出uri信息

    package handle.groupby; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io ...

  9. MYSQL:基于哈希的索引和基于树的索引有什么区别?

    B+树是一个平衡的多叉树.B+树从根节点到叶子节点的搜索效率基本相当,不会出现大幅波动. 哈希索引采用一定的哈希算法,把键值换成新的哈希值,检索时不需要类似B+树那样从根节点逐级查找,只需一次哈希算法 ...

  10. python3 修改excel 单元格的值(xlsx)

    excel code #coding=utf- import os.path import os from openpyxl.reader.excel import load_workbook # e ...