本文主要说明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. CORE DUMP生成调试

    之前我调试嵌入式linux程序,一般是借助ucontext库,在发生段错误时,直接将错误函数打印出来.有同事建议我使用core dump,于是我今天在嵌入式板卡尝试了core文件的生成,但是也是几经波 ...

  2. Android开发:为什么你的学习效率如此低,为什么你很迷茫?

    一天一天的过的真的是太快了,常常感到时间在前进,而我们还在停滞不前,看似每天努力的工作学习着,仔细想想其实又会发现,一天下来我们好像还真的什么都没干,看似忙碌的一天,我们把时间都用在哪了?学习!可是为 ...

  3. opencv 程序

    IplImage结构中的一个元素:struct _IplROI *roi; //图像感兴趣区域,当该值非空时,只对该区域进行处理 .   ROI :Region of Interest,表示感兴趣的区 ...

  4. BZOJ4241:历史研究(回滚莫队)

    题意:给定N个数字,Q次询问,询问这个区间的最大加权众数是多少. 加权众数是指出现次数*数字大小.N,Q<1e5. 思路:不难发现可以N*sqrtN*logN的思路做,但是应该过不了. 这个Ns ...

  5. 微信2.1 for Windows发布 微信群可多人语音或视频通话

    5月31日,windows电脑版微信发布更新,微信2.1 for Windows带来最主要的功能是微信群可以多人语音或视频通话了,建个家庭群组,常年在外工作的家人也可以每天见面了,多亲切! 除了可以建 ...

  6. 08-C#笔记-判读语句

    同C++ 支持if.switch.?: 不同之处 1. switch case支持字符. 参考: http://www.runoob.com/csharp/csharp-switch.html htt ...

  7. Hbase与hive集成与对比

    HBase与Hive的对比 1.Hive (1) 数据仓库 Hive的本质其实就相当于将HDFS中已经存储的文件在Mysql中做了一个双射关系,以方便使用HQL去管理查询. (2) 用于数据分析.清洗 ...

  8. Java反射之Bean修改更新属性值等工具类

    package com.bocean.util; import java.lang.annotation.Annotation; import java.lang.reflect.Field; imp ...

  9. Leecode之双指针及二分查找

    题目 给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数. 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2. 说明: 返回的 ...

  10. java注释代码规范

    //收集了一小部分,忘记的时候过来查一下 java--hadoop部分 /** * 此类用来处理DNS原始日志:统计给定域名平均响应时延 * @param Input * @param Output ...