我为 C++17 编写了一个 LALR(1) 解析器。我发现了156个歧义,其中一些我可以根据标准解决它,但其他我不能。
例如:当遇到小于时,在解析“ operator+ < ...... ”时发生 Shift-Reduce 冲突:
我们可以将其解析为:
(1)
模板 ID -> 操作符函数 ID · < ...... >
或者:
(2)
unqualified-id -> operator-function-id · 其中 (1) 需要移位但 (2) 需要减少。
但是,该标准具有:
在名称查找 (3.4) 发现名称是模板名称或 operator-function-id 或literaloperator-id 引用一组重载函数后,其中任何成员都是函数模板,如果后面跟着一个<,< 总是作为模板参数列表的分隔符,而不是小于运算符。解析模板参数列表时,第一个非嵌套 >137 被视为结束分隔符而不是大于运算符。
所以我们选择转移。
不幸的是,有很多歧义我找不到解决方案。在这里,我列出了其中的一些(其中一些可以清楚地做出选择,但我就是找不到证据):
- 当出现歧义时,标准中是否有某些部分表明“转移”是默认选择?
声明者
(1)当解析一个 noptr-declarator 并遇到一个左括号时,我应该根据以下方式减少它:
ptr-declarator -> noptr-declarator ·
或移动左括号以满足:
declarator -> noptr-declarator ·参数和限定符
parameters-and-qualifiers -> · left-paren parameter-declaration-clause right-paren......
(2)当解析一个declarator-id遇到左括号时,我应该按照以下方式减少它:
noptr-declarator -> declarator-id · noptr-declarator -> noptr-declarator · \left-bracket ?constant-expression \right-bracket ?attribute-specifier-seq
或移动左方以满足:
noptr-declarator -> declarator-id ·attribute-specifier-seq
(属性说明符序列为 [[.......]])