Parsing 移位/减少语法不明确的冲突

Parsing 移位/减少语法不明确的冲突,parsing,yacc,shift-reduce-conflict,Parsing,Yacc,Shift Reduce Conflict,由于yacc报告了6个班次/减少冲突,我已经被一些模棱两可的语法困扰了一段时间。我查看了y.output文件,试图了解如何查看状态,并找出如何修复不明确的语法,但没有效果。我理所当然地被困在如何解决这些问题上。我看了很多关于堆栈溢出的问题,看看其他人的解释是否对我的问题有帮助,但这对我也没有多大帮助。对于记录,我不能使用任何优先级定义指令,如%left来解决解析冲突。 是否有人能帮助我,指导我如何更改语法以修复移位/减少冲突?也许通过尝试解决其中一个问题并向我展示其背后的思考过程?我知道语法很长

由于yacc报告了6个班次/减少冲突,我已经被一些模棱两可的语法困扰了一段时间。我查看了y.output文件,试图了解如何查看状态,并找出如何修复不明确的语法,但没有效果。我理所当然地被困在如何解决这些问题上。我看了很多关于堆栈溢出的问题,看看其他人的解释是否对我的问题有帮助,但这对我也没有多大帮助。对于记录,我不能使用任何优先级定义指令,如
%left
来解决解析冲突。

是否有人能帮助我,指导我如何更改语法以修复移位/减少冲突?也许通过尝试解决其中一个问题并向我展示其背后的思考过程?我知道语法很长很重,我为此提前道歉。如果有人愿意在这方面腾出空闲时间,我将不胜感激,但我意识到我可能无法做到这一点

无论如何,这里是我的语法问题(它是MiniJava语法的一个轻微扩展):

以下是y.output中具有移位/减少冲突的相关状态

State 58
7 var_decl_list: var_decl_list . var_decl
12 method_decl: PUBLIC type ID '(' formal_list ')' '{' var_decl_list . statement_list RETURN exp ';' '}'

INT      shift, and go to state 20
BOOLEAN  shift, and go to state 21
ID       shift, and go to state 22

ID        [reduce using rule 30 (statement_list)]
$default  reduce using rule 30 (statement_list)

var_decl        go to state 24
type            go to state 25
statement_list  go to state 69


State 76
38 exp: ID . index
39    | ID . '.' LENGTH
40    | ID . index '.' LENGTH
46 object: ID .

'['  shift, and go to state 64
'.'  shift, and go to state 97

'.'       [reduce using rule 46 (object)]
$default  reduce using rule 46 (object)

index  go to state 98


State 100
33 exp: exp . OP exp
34    | '!' exp .

OP  shift, and go to state 103

OP        [reduce using rule 34 (exp)]
$default  reduce using rule 34 (exp)


State 101
33 exp: exp . OP exp
35    | '+' exp .

OP  shift, and go to state 103

OP        [reduce using rule 35 (exp)]
$default  reduce using rule 35 (exp)


State 102
33 exp: exp . OP exp
36    | '-' exp .

OP  shift, and go to state 103

OP        [reduce using rule 36 (exp)]
$default  reduce using rule 36 (exp)


State 120
33 exp: exp . OP exp
33    | exp OP exp .

OP  shift, and go to state 103

OP        [reduce using rule 33 (exp)]
$default  reduce using rule 33 (exp)

就在这里。对于本语法的长度和移位/减少冲突的数量,我再次表示歉意。我似乎不明白如何通过修改有问题的语法来修正它们。任何帮助都将不胜感激,但如果没有人有时间浏览如此庞大的帖子,我会理解的。如果有人需要更多信息,请毫不犹豫地询问。

基本问题是,在解析
方法\u decl
主体时,它无法判断
变量decl\u列表
的结束位置和
语句列表
的开始位置。这是因为当前瞻是
ID
时,它不知道这是另一个
var_decl
的开始还是第一个
语句的开始,它需要先减少一个空语句,然后才能开始处理
语句列表

您可以通过多种方式处理此问题:

  • 让lexer为类型id和其他id返回不同的标记——这样,差异将告诉解析器下一个是哪个

  • 在语句列表的开头不需要空语句。将语法更改为:

    statement_list: statement | statement_list statement ;
    opt_statement_list: statement_list | %empty ;
    
    并在
    方法decl
    规则中使用
    opt\u statement\u list
    。这解决了在开始解析语句之前必须减少空的
    语句\u列表的问题。这是一个称为“分解”语法的过程,因为您正在用多个变体替换规则。它使语法更加复杂,在这种情况下,它并不能解决问题,只是移动了它;然后您将看到
    语句:ID之间的shift/reduce冲突。在一个
    [
    前瞻上的index
    type:ID
    。这个问题也可以通过取消因子来解决,但难度更大


因此,这就提出了通过取消因子来解决移位-减少冲突的总体思路。基本思路是消除导致移位-减少冲突减少一半的规则,将其替换为在上下文中更为有限的规则,这样就不会触发冲突。上例由“用1个或多个递归重复和可选规则替换0个或多个递归重复”。如果以下上下文意味着您可以轻松解决0-case何时应为合法(在这种情况下,仅当下一个标记为
}
时),则这对于减少重复的epsilon规则上的shift-reduce冲突非常有效

第二个冲突更为棘手。这里的冲突是当前瞻是
[
时,减少
类型:ID
。因此我们需要复制类型规则,直到不需要为止。例如:

type: simpleType | arrayType ;
simpleType: INT | BOOLEAN | ID ;
arrayType: INT '[' ']' | BOOLEAN '[' ']' | ID '[' ']'
         | arrayType '[' ']' ;

用“1或更多”替换“0或更多重复的
'['']'
后缀”,并出于类似的原因工作(将缩减推迟到看到
'['']'
之后,而不是之前需要它。)关键是,当前瞻是
时,
simpleType:ID
规则永远不需要缩减['
因为它只在其他上下文中有效。

基本问题是,在解析
方法decl
主体时,它无法判断
变量decl\u列表
在哪里结束,而
语句列表
在哪里开始。这是因为当向前看是
ID
时,它不知道这是否是另一个
变量的开始l
或第一个
语句的开始,它需要减少一个空语句,然后才能开始处理
语句列表

您可以通过多种方式处理此问题:

  • 让lexer为类型id和其他id返回不同的标记——这样,差异将告诉解析器下一个是哪个

  • 不需要在语句列表的开头使用空语句。将语法更改为:

    statement_list: statement | statement_list statement ;
    opt_statement_list: statement_list | %empty ;
    
    并在
    方法decl
    规则中使用
    opt_statement_list
    。这可以解决在开始解析语句之前必须减少空
    语句_list
    的问题。这是一个称为“取消因子”的过程“当您用多个变体替换规则时,语法会变得更复杂。在这种情况下,语法并不能解决问题,它只是移动语法;然后您将看到在
    a上的
    statement:ID.index
    type:ID
    之间发生移位/减少冲突。”[
    lookahead。这个问题也可以通过取消因子来解决,但难度更大


因此,这就提出了通过取消因子来解决移位-减少冲突的总体思路。基本思路是摆脱导致移位-减少冲突减少一半的规则,用在上下文中更为有限的规则取代它,所以不要