LR编写grammar中的问题和解决方法

Posted davygeek

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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中的问题和解决方法的主要内容,如果未能解决你的问题,请参考以下文章

Eclipse 中的通用代码片段或模板

如何解决XML文件中的警告提示“No grammar constraints (DTD or XML Schema) referenced in the document.”

片段中ListView的setOnItemClickListener

如何在Sublime Text中添加代码片段

编写代码片段的更简洁的方法

JDBC Spring中的Bad Sql Grammar异常