减少/减少银联中的冲突

时间:2018-12-08 05:43:38

标签: parsing compiler-construction grammar shift-reduce-conflict cup

我正在使用Java CUP为Java的子集实现解析器。

语法就像

vardecl ::= type ID
type    ::= ID | INT | FLOAT | ...
exp     ::= ID | exp LBRACKET exp RBRACKET | ...
stmt    ::= ID ASSIGN exp SEMI

这很好,但是当我添加

stmt ::= ID ASSIGN exp SEMI
        |ID LBRACKET exp RBRACKET ASSIGN exp SEMI 

CUP无法使用,警告是:

Warning : *** Shift/Reduce conflict found in state #122
  between exp ::= identifier (*) 
  and     statement ::= identifier (*) LBRACKET exp RBRACKET ASSIGN exp SEMI 
  under symbol LBRACKET
  Resolved in favor of shifting.

Warning : *** Reduce/Reduce conflict found in state #42
  between type ::= identifier (*) 
  and     exp ::= identifier (*) 
  under symbols: {}
  Resolved in favor of the first production.

Warning : *** Shift/Reduce conflict found in state #42
  between type ::= identifier (*) 
  and     statement ::= identifier (*) LBRACKET exp RBRACKET ASSIGN exp SEMI 
  under symbol LBRACKET
  Resolved in favor of shifting.

Warning : *** Shift/Reduce conflict found in state #42
  between exp ::= identifier (*) 
  and     statement ::= identifier (*) LBRACKET exp RBRACKET ASSIGN exp SEMI 
  under symbol LBRACKET
  Resolved in favor of shifting.

我认为有两个问题:
1. type ::= IDexp ::= ID,当解析器看到ID时,它想减少ID,但不知道减少typeexp。< / p>

  1. stmt ::= ID LBRACKET exp RBRACKET ASSIGN exp SEMI用于分配数组中的元素,例如arr[key] = value;
    exp :: exp LBRACKET exp RBRACKET用于从数组中获取元素的表达式,例如arr[key]

因此在arr[key]的情况下,当解析器看到arr时,它知道它是一个ID,但不知道它是否应该移动或减少到exp

但是,我不知道如何解决此问题,如果有的话,请给我一些建议,谢谢。

1 个答案:

答案 0 :(得分:2)

您的分析是正确的。语法为LR(2),因为在看到]标记之前无法识别声明,该标记将是ID中的第二个下一个标记,可能是一种类型。

一个简单的解决方案是,当括号显示为连续标记时,攻击词法分析器以将[]作为单个标记返回。 (词法分析器也应该在方括号之间留有空格,因此它并不琐碎,但并不复杂。)如果[之后没有紧跟着],则词法分析器会将其返回为普通[。这样,解析器就可以轻松区分对数组的分配(将具有[令牌)和对数组的声明(将具有[]令牌)之间的区别。

也可以重写语法,但这确实很麻烦。

第二个问题-数组索引分配与数组索引表达式。通常,编程语言允许分配以下形式:

exp [ exp ] = exp

,而不仅仅是ID [ exp ]。进行此更改将延迟减少的需求,直到解析器识别出正确的减少的时间足够晚为止。根据语言的不同,此语法在语义上可能没有意义,但是在类型检查(语义)领域中进行的检查不是语法。但是,如果存在某种形式的有意义的语法,则没有明显的理由禁止它。

某些解析器生成器实现GLR解析器。 GLR解析器对此语法没有问题,因为它没有歧义。但是银联不是这样的发电机。