我正在研究解析器,我真的很沮丧。在语言中,我们可以有这样的表达:

new int[3][][]

或者

new int[3]

除了末尾的空数组之外,大部分内容都能正确解析。在我的解析器中我有:

Expression : int
             char
             null
             (...many others...)
             new NewExpression

然后 NewExpression 是:

NewExpression : NonArrayType '[' Expression ']' EmptyArrays
              | NonArrayType '[' Expression ']' 

然后 EmptyArrays 是一个或多个空大括号 - 如果 EmptyArrays 派生空字符串,它会添加 20 个移位/归约冲突:

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 语句有类似的规则,它会产生移位/归约冲突,但如果下一个标记是 else 则选择移位(这个问题有详细记录)。

你能帮我弄清楚出了什么问题吗?我真的很感谢你的帮助,我真的很想解决这个问题。

有帮助吗?

解决方案

您可能为“[”和/或“]”设置了优先级,例如 %left '[' 这会导致这种行为。删除该优先级声明,这将揭示您在这里遇到的移位/归约冲突。至于为什么会发生移位/归约冲突,您可能也有一个规则:

Expression: Expression '[' Expression ']'

用于数组访问。问题是,自从 NewExpression 是一个 Expression 它后面可能跟着这样的索引,当查看“[”的前瞻时,它无法判断这是索引表达式的开头还是一个索引表达式的开头 EmptyArray ——这需要 2 个令牌前瞻。

对于这种特定情况,您可以尝试的一件事是让您的词法分析器执行此处所需的额外前瞻并识别 [] 作为单个令牌。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top