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