我正在研究解析器,我真的很沮丧。在语言中,我们可以有一个表达式:
new int[3][][]
或
new int[3]
除了最后的空数组外,其中大多数都正确解析。 在我的解析器中,我有:
Expression : int
char
null
(...many others...)
new NewExpression
然后NewExpression是:
NewExpression : NonArrayType '[' Expression ']' EmptyArrays
| NonArrayType '[' Expression ']'
然后EmptyArrays是一个或多个空括号 - 如果EmptyArrays派生空字符串,它会增加20个shift / reduce冲突:
EmptyArrays : EmptyArrays EmptyArray
| EmptyArray
EmptyArray : '[' ']'
然而,当我查看解析器的.info
文件时,我得到了这个:
State 214¬
¬
▸ NewExpression -> NonArrayType lbrace Expression rbrace . EmptyArrays (rule 80)¬
▸ NewExpression -> NonArrayType lbrace Expression rbrace . (rule 81)¬
¬
▸ dot reduce using rule 81¬
▸ ';' reduce using rule 81¬
▸ ',' reduce using rule 81¬
▸ '+' reduce using rule 81¬
▸ '-' reduce using rule 81¬
▸ '*' reduce using rule 81¬
▸ '/' reduce using rule 81¬
▸ '<' reduce using rule 81¬
▸ '>' reduce using rule 81¬
▸ '<=' reduce using rule 81¬
▸ '>=' reduce using rule 81¬
▸ '==' reduce using rule 81¬
▸ '!=' reduce using rule 81¬
▸ ')' reduce using rule 81¬
▸ '[' reduce using rule 81 --I expect this should shift
▸ ']' reduce using rule 81¬
▸ '?' reduce using rule 81¬
▸ ':' reduce using rule 81¬
▸ '&&' reduce using rule 81¬
▸ '||' reduce using rule 81
我希望如果我们处于状态214并且我们看到左括号,我们应该将它移到堆栈上并继续解析EmptyArrays。
我不确定发生了什么事,因为当我通过NewExpression
启动解析来剥离所有多余的行李(例如)时,额外的括号正确解析。表达式或语句或语法中的任何非终端都不可能以左括号开头。特别是因为我对if / else语句有一个类似的规则,它会产生一个shift / reduce冲突,但是如果下一个标记是else,则选择转换(这个问题有详细记录)。
你能帮我弄清楚出了什么问题吗?我真的很感谢你的帮助,我真的倾向于试图找出问题的风车。
答案 0 :(得分:1)
你可能有一个'['和/或']'的优先级设置,例如%left '['
会导致这种行为。删除该优先级声明,这将显示您在此处的转移/减少冲突。至于为什么它会发生转变/减少冲突,你可能也有一个规则:
Expression: Expression '[' Expression ']'
用于数组访问。问题在于,因为NewExpression
是Expression
,所以可能会跟着这样的索引,当看到'['的前瞻时,它无法判断这是否是一个开头索引表达式或EmptyArray
的开头 - 这需要2个令牌前瞻。
您可以尝试针对此特定情况尝试的一件事是让您的词法分析员在此处执行额外的预测并将[]
识别为单个令牌。