问题描述
我正在将(生成的)语法提供给Beaver解析器生成器。此规则中似乎存在悬而未决的其他问题,从而导致多次移位-减少冲突:
Condition
= IF LPAR Expression.expression RPAR Statement.trueStatement OptionalStatement_1.elem2
;
OptionalStatement_1
= ELSE StatementArray3.falseStatement
|
;
我认为悬空其他问题不会成为问题,因为该工具默认选择SHIFT,这是悬空其他问题AFAIK的公认解决方案。但是,存在一些问题,因为我还有其他16条警告,而且我不明白为什么:
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (ELSE: SHIFT; goto 93) over (ELSE: REDUCE OptionalStatement_1 = ) using precedence.
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (LBR: SHIFT; goto 5) over (LBR: REDUCE OptionalStatement_1 = ELSE StatementArray3.falseStatement) using precedence.
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (IF: SHIFT; goto 18) over (IF: REDUCE OptionalStatement_1 = ELSE StatementArray3.falseStatement) using precedence.
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (RETURN: SHIFT; goto 95) over (RETURN: REDUCE OptionalStatement_1 = ELSE StatementArray3.falseStatement) using precedence.
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (DO: SHIFT; goto 100) over (DO: REDUCE OptionalStatement_1 = ELSE StatementArray3.falseStatement) using precedence.
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (READ: SHIFT; goto 107) over (READ: REDUCE OptionalStatement_1 = ELSE StatementArray3.falseStatement) using precedence.
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (WRITE: SHIFT; goto 110) over (WRITE: REDUCE OptionalStatement_1 = ELSE StatementArray3.falseStatement) using precedence.
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (SEMICOLON: SHIFT; goto 113) over (SEMICOLON: REDUCE OptionalStatement_1 = ELSE StatementArray3.falseStatement) using precedence.
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (WHILE: SHIFT; goto 114) over (WHILE: REDUCE OptionalStatement_1 = ELSE StatementArray3.falseStatement) using precedence.
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (LPAR: SHIFT; goto 63) over (LPAR: REDUCE OptionalStatement_1 = ELSE StatementArray3.falseStatement) using precedence.
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (PLUSPLUS: SHIFT; goto 71) over (PLUSPLUS: REDUCE OptionalStatement_1 = ELSE StatementArray3.falseStatement) using precedence.
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (PLUS: SHIFT; goto 73) over (PLUS: REDUCE OptionalStatement_1 = ELSE StatementArray3.falseStatement) using precedence.
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (EXCL: SHIFT; goto 75) over (EXCL: REDUCE OptionalStatement_1 = ELSE StatementArray3.falseStatement) using precedence.
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (MINUS: SHIFT; goto 77) over (MINUS: REDUCE OptionalStatement_1 = ELSE StatementArray3.falseStatement) using precedence.
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (MINUSMINUS: SHIFT; goto 79) over (MINUSMINUS: REDUCE OptionalStatement_1 = ELSE StatementArray3.falseStatement) using precedence.
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (VALUE: SHIFT; goto 81) over (VALUE: REDUCE OptionalStatement_1 = ELSE StatementArray3.falseStatement) using precedence.
grammar.grammar: Warning: Resolved Shift-Reduce conflict by selecting (IDENT: SHIFT; goto 82) over (IDENT: REDUCE OptionalStatement_1 = ELSE StatementArray3.falseStatement) using precedence.
结果是在StatementArray3中将垃圾注入到else分支中(完全错误的类型,用List而不是Optional填充,填充了以下语句中的内容)。 有人可以请我解释一下这些移位减少冲突是由什么引起的(除了明显的第一个冲突之外)?请注意,语法是从类模型生成的,因此没有针对此问题的非常具体的解决方案最好的情况是,我通常需要解决此类问题,或者更改语法。
Condition
= IF LPAR Expression.expression RPAR Statement.trueStatement
| IF LPAR Expression.expression RPAR Statement.trueStatement ELSE Statement.falseStatement
;
在编译过程中没有冲突,但是对于以下输入:
{
if(b == 21)
c = 10;
else
c = 15;
}
解析器在运行时失败,只是跳过else并将第二个分配视为顶级:
4,4-4,7: Syntax Error: unexpected token "else"
4,7: Recovered: removed unexpected token "else"
完整的有问题的语法(去除了%import,%typeof和{: ... :}
):
%terminals PERC,ASSIGNDIV,LT,RPAR,VALUE,DO,ASSIGN,PLUSPLUS,QUESTION,MINUS,WRITE,RETURN,LPAR,SEMICOLON,ASSIGNADD,ELSE,LBR,IF,COMMA,RBR,OR,SLASH,MINUSMINUS,COLON,EQ,GT,READ,ASSIGNMUL,STAR,IDENT,ASSIGNSUB,ASSIGNMOD,AND,GTE,WHILE,NEQ,EXCL,LTE,PLUS;
%left LPAR,RPAR;
%nonassoc PLUSPLUS,MINUSMINUS;
%left PREC_13_1,PREC_13_2;
%left PERC,STAR;
%left PLUS,MINUS;
%left LT,GTE;
%left NEQ,EQ;
%left AND;
%left OR;
%left QUESTION,COLON;
%right ASSIGN,ASSIGNMOD;
%goal Program;
Number
= VALUE.value
;
Program
= FunctionArray1.functions Block.main
;
UnaryOperation
= PLUSPLUS Expression.expression
| PLUS Expression.expression @ PREC_13_1
| EXCL Expression.expression
| MINUS Expression.expression @ PREC_13_2
| MINUSMINUS Expression.expression
;
Block
= LBR StatementArray3.statements RBR
;
BinaryOperation
= Expression.expression1 NEQ Expression.expression2
| Expression.expression1 OR Expression.expression2
| Expression.expression1 PERC Expression.expression2
| Expression.expression1 EQ Expression.expression2
| Expression.expression1 PLUS Expression.expression2
| Expression.expression1 LT Expression.expression2
| Expression.expression1 MINUS Expression.expression2
| Expression.expression1 LTE Expression.expression2
| Expression.expression1 SLASH Expression.expression2
| Expression.expression1 GT Expression.expression2
| Expression.expression1 ASSIGN Expression.expression2
| Expression.expression1 STAR Expression.expression2
| AssignmentGeneric.val
| Expression.expression1 GTE Expression.expression2
| Expression.expression1 AND Expression.expression2
;
Expression
= LPAR Expression.val RPAR
| Expression.expression1 QUESTION Expression.expression2 COLON Expression.expression3
| UnaryOperation.val
| Number.val
| Variable.val
| FunctionCall.val
| BinaryOperation.val
;
Parameterarray2
= Parameterarray2.list COMMA Parameter.elem
|
| Parameter.elem
;
Statement
= Block.val
| Condition.val
| ReturnFunction.val
| ExpressionStatement.val
| DoWhile.val
| Read.val
| Write.val
| EmptyStatement.val
| WhileStatement.val
;
Parameter
= IDENT.ident
;
Write
= WRITE Expression.expression SEMICOLON
;
OptionalStatement_1
= ELSE StatementArray3.falseStatement
|
;
FunctionArray1
= FunctionArray1.list Function.elem
|
;
WhileStatement
= WHILE LPAR Expression.expression RPAR Statement.statement
;
ExpressionArray4
= ExpressionArray4.list COMMA Expression.elem
|
| Expression.elem
;
ExpressionStatement
= Expression.expression SEMICOLON
;
Variable
= IDENT.ident
;
EmptyStatement
= SEMICOLON
;
Read
= READ IDENT.ident SEMICOLON
;
FunctionCall
= IDENT.ident LPAR ExpressionArray4.expressions RPAR
;
Condition
= IF LPAR Expression.expression RPAR Statement.trueStatement OptionalStatement_1.elem2
;
DoWhile
= DO Statement.statement WHILE LPAR Expression.expression RPAR SEMICOLON
;
Function
= IDENT.ident LPAR Parameterarray2.parameters RPAR Block.body
;
ReturnFunction
= RETURN Expression.expression SEMICOLON
;
StatementArray3
= StatementArray3.list Statement.elem
|
;
AssignmentGeneric
= Expression.expression1 ASSIGNADD Expression.expression2
| Expression.expression1 ASSIGNMUL Expression.expression2
| Expression.expression1 ASSIGNDIV Expression.expression2
| Expression.expression1 ASSIGNSUB Expression.expression2
| Expression.expression1 ASSIGNMOD Expression.expression2
;
解决方法
语法生成中存在问题。应该是
OptionalStatement_1
= ELSE Statement.falseStatement
|
;
不是StatementArray3.falseStatement
正确生成ELSE Statement.falseStatement
替代项后,仅会发生一次shift-reduce冲突,并且我可以依靠默认的SHIFT动作。