问题描述
expression -> expression OPER expression
expression -> PREFIX expression
expression -> expression POSTFIX
expression -> expression ‘?’ expression ‘:’ expression
expression -> expression ‘[’ expression ‘]’
expression -> expression ‘(’ expression ‘)’
expression -> ID
expression -> CONSTANT
expression ->‘(’ expression ‘)’
LR 解析器分析时,该文法中的 reduce-reduce 和 shift-reduce 冲突是什么?
解决方法
在那段摘录中没有归约冲突,但肯定到处都是移位归约冲突。它们都有相同的原因:语法没有尝试定义各种运算符的优先级,结果是任何具有多个运算符的表达式都是不明确的。
例如,PREFIX ID POSTFIX
可以被解析为 (PREFIX ID) POSTFIX
或 PREFIX (ID POSTFIX)
。在 ID
减少到 expression
后,这显然会产生一个 shift-reduce 冲突:
Stack: PREFIX expression
Lookahead: POSTFIX
此时,解析器可以使用 expression
将堆栈减少到 expression -> PREFIX expression
。但它也可以将 POStFIX
从输入转移到堆栈上,为减少 expression -> expression POSTFIX
做准备。
每个其他运算符都会发现相同的歧义。
,Reduce-reduce 意味着它已经达到了一种状态,在一个语言符号之前,它可以减少两个不同的规则,从而导致代表你的句子的两种不同的语法树。由于下一个符号在两种情况下都是有效的,并且是一个一个符号解析器,这意味着您的语法有歧义,您需要提供更多信息(如优先规则或类似的)以便使解析器采用一种归约或另一种归约。
您可以从 yacc
类型的语法编译器或 shift-reduce 收到此错误,这再次意味着您的语法中存在歧义。虽然没有解决办法,只能改变你的语法定义方式,或者切换到基于运算符优先级的语法来解决这个问题,但在这两种情况下,我们都在研究某种歧义,导致两种不同的语法树描述你的语言句子.
就你而言,规则
expression : expression OPER expression
充满歧义,因为您无法猜测:
3 + 5 + 8
将产生一个解析树:
/--- <3> expression : CONSTANT
<+> expression : expression OPER expression
\ /--- <5> expression : CONSTANT
\--- <+> expression : expression OPER
\--- <8> expression : CONSTANT
或
/--- <3> expression : CONSTANT
/--- <+> expression : expression OPER expression
/ \--- <5> expression : CONSTANT
<+> expression : expression OPER expression
\--- <8> expression : CONSTANT
第一个表示表达式被解析为(用完整的括号表示法)(3 + (5 + 8))
,第二个表示您的解析器已经解释了 ((3 + 5) + 8)
。