如何在 Yacc 中强制转换?
How to force shift in Yacc?
我有以下结构作为 yacc 语法的一部分(或者更确切地说是 jison,但两者共享相同的公共基础):
Type
: IDENT
| Type "[" "]"
| Type "*"
| "func" "(" Types ")" "=>" Type
;
Types
: /* No arguments */
| Type /* Single argument */
| Types "," Type /* Multiple arguments */
;
这当然是一个简化的例子,但它应该给出总体思路并展示实际问题。我想将 Foo[]
、Foo*
、Foo*[]
等结构分别解析为 (Foo)[]
、(Foo)*
、((Foo)*)[]
。
然而,Yacc 理所当然地抱怨它在遇到以下结构时不知道该怎么做:
func (A, B) => C[]
可以解析为func (A, B) => (C[])
或(func (A, B) => C)[]
。我当然希望它成为第一个(因为我有一个 ( Type )
构造用于第二种情况)。有什么办法可以告诉yacc(或jison)遇到这种情况我要shift吗?
给最后一个 Type
产品一个优先级,或者使用 %prec
声明和 pseudo-terminal,或者使用默认值,即 =>
的优先级,最后一个终端。然后确保 [
标记的优先级更高。 (您还必须使 *
的优先级高于 =>
,以解决另一个 shift-reduce 冲突。)
还有其他解决方案,但这个是最简单的。
其实bison/yacc/jison/etc。 always prefer shift in a shift-reduce conflict,所以你不需要做任何事情来换班。优先规则将抑制警告,但您也可以使用 expect
声明来做到这一点。
我有以下结构作为 yacc 语法的一部分(或者更确切地说是 jison,但两者共享相同的公共基础):
Type
: IDENT
| Type "[" "]"
| Type "*"
| "func" "(" Types ")" "=>" Type
;
Types
: /* No arguments */
| Type /* Single argument */
| Types "," Type /* Multiple arguments */
;
这当然是一个简化的例子,但它应该给出总体思路并展示实际问题。我想将 Foo[]
、Foo*
、Foo*[]
等结构分别解析为 (Foo)[]
、(Foo)*
、((Foo)*)[]
。
然而,Yacc 理所当然地抱怨它在遇到以下结构时不知道该怎么做:
func (A, B) => C[]
可以解析为func (A, B) => (C[])
或(func (A, B) => C)[]
。我当然希望它成为第一个(因为我有一个 ( Type )
构造用于第二种情况)。有什么办法可以告诉yacc(或jison)遇到这种情况我要shift吗?
给最后一个 Type
产品一个优先级,或者使用 %prec
声明和 pseudo-terminal,或者使用默认值,即 =>
的优先级,最后一个终端。然后确保 [
标记的优先级更高。 (您还必须使 *
的优先级高于 =>
,以解决另一个 shift-reduce 冲突。)
还有其他解决方案,但这个是最简单的。
其实bison/yacc/jison/etc。 always prefer shift in a shift-reduce conflict,所以你不需要做任何事情来换班。优先规则将抑制警告,但您也可以使用 expect
声明来做到这一点。