LR编写grammar中的问题和解决方法
本文主要说明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中的问题和解决方法的更多相关文章
- PowerShell因为在此系统中禁止执行脚本解决方法
PowerShell因为在此系统中禁止执行脚本解决方法 在Powershell直接脚本时会出现: 无法加载文件 ******.ps1,因为在此系统中禁止执行脚本.有关详细信息,请参阅 " ...
- (转)ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务 的解决方法
早上同事用PL/SQL连接虚拟机中的Oracle数据库,发现又报了"ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务"错误,帮其解决后,发现很多人遇到过这样的问 ...
- ORA-01652:无法通过128(在表空间temp中)扩展temp段 解决方法
ORA-01652:无法通过128(在表空间temp中)扩展temp段 解决方法 (2016-10-21 16:49:53) 今天在做一个查询的时候,报了一个"ORA-01652无法通过 ...
- Oracle中的 UPDATE FROM 解决方法
转:http://www.cnblogs.com/JasonLiao/archive/2009/12/23/1630895.html Oracle中的 UPDATE FROM 解决方法 在表的更新操作 ...
- win7 安装过程中遇到的错误解决方法
win7 安装过程中遇到的错误解决方法 windows安装无法继续.若要安装windows 请单击 确定 重新启动计算机: 当 出现如上提示的时候,按下shift+f10 会打开命令窗口,进入到C:\ ...
- [转载]Ubuntu 14.04中root 密码忘记解决方法
Ubuntu 14.04中root 密码忘记解决方法 方法一: 如果用户具有sudo权限,那么直接可以运行如下命令: #sudo su root #passwd #更改密码 或者直接运行sudo ...
- oracle中can not set解决方法
原因:set autotrace on和set trimspool on在pl\sql中使用不了 解决方法:在window环境中,使用cmd命令,sqlplus user_name/password@ ...
- 【转】eclipse中window->preference选项中没有tomcat的解决方法
eclipse中window->preference选项中没有tomcat的解决方法 2011-09-09 13:46:35| 分类: eclipse|字号 订阅 其实一共有好几种方法,这只是 ...
- Oracle更新表字段时内容中含有特殊字符&的解决方法
今天在做 Oracle表字段更新时出现了特殊字符&,导致无法更新. 这个问题是第二次碰到了,所以在此记录下,以备后用. 举例: update t set col1='A&B' wher ...
随机推荐
- MySQLDump--导出数据脚本异常
在一次使用mysqldump导出数据过程中,发现导出SQL无法正常执行,仔细观察后发下导出脚本为: (,,,,' Yimu(id:5085297)',''¥','[新教室V32] ',15593224 ...
- TinyXML2 使用
TinyXML2 TinyXML2 TinyXML是一个开源的解析XML的解析库,能够用于C++,能够在Windows或Linux中编译,使用TinyXML进行C++ XML解析,使用简单,容易上手. ...
- 堆叠降噪自编码器SDAE
https://blog.csdn.net/satlihui/article/details/81006906 https://blog.csdn.net/github_39611196/articl ...
- Linux小知识:CentOS使用Google-BBR加速网络
准备一台centos的服务器查看系统内核:rpm -qa | grep kernel这里需要Linux内核在4.9 RC版本以上,如果版本不是请继续下面操作 访问https://elrepo.org/ ...
- 17 个方面,综合对比 Kafka、RabbitMQ、RocketMQ、ActiveMQ 四个分布式消息队列
原文:https://mp.weixin.qq.com/s/lpsQ3dEZHma9H0V_mcxuTw 一.资料文档 二.开发语言 三.支持的协议 四.消息存储 五.消息事务 六.负载均衡 七.集群 ...
- Ubuntu配置samba服务器
假设我的Ubuntu用户名:myname 1. 安装和卸载samba: sudo apt-get install samba samba-common sudo apt-get autoremove ...
- centos7下安装docker 以及简单使用
一 环境准备1.虚拟机or物理机 2.centos7系统(稳定,对docker支持友好) 二 安装过程step1:使用yum命令进行安装 yum install -y docker备注:-y 表示不询 ...
- VSS 使用方法
VSS 的全称为 Visual Source Safe .作为 Microsoft Visual Studio 的一名成员,它主要任务就是负责项目文件的管理,几乎可以适用任何软件项目.管理软件开发中各 ...
- 10-排序5 PAT Judge (25 分)
The ranklist of PAT is generated from the status list, which shows the scores of the submissions. Th ...
- js 测试题
//身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字母x function isCardNo(card) { }$)|(^\d{}(\d|X|x) ...