【发布时间】:2015-01-14 18:41:18
【问题描述】:
我正在为具有以下类型的语言开发 Happy 解析器,等等。
type :: { ... }
type :
'void' { ... }
| type '*' { ... } {- pointer -}
| type '(' types ')' { ... } {- function -}
| ... {- many more! -}
types :: { ... }
{- empty -} { ... }
| types ',' type { ... }
该语言的调用语法显然不明确。
callable :: { ... }
callable :
type operand { ... } {- return type -}
| type '(' types ')' '*' operand { ... } {- return and argument types -}
当type 采用函数指针的类型时,第二条规则与第一条规则的含义不同。
可以通过为不是函数指针的类型添加特殊规则来消除歧义。除非这样做并复制所有类型定义以产生类似的东西
callable :: { ... }
callable :
typeThatIsNotAFunctionPointer operand { ... }
| type '(' types ')' '*' operand { ... }
我如何才能指定替代type operand 仅在type '(' types ')' '*' operand 替代失败时才合法?
关于堆栈溢出有很多关于为什么语法有歧义的问题(我发现至少有 7 个),还有一些关于如何消除歧义的问题,但没有关于如何指定如何解决歧义的问题。
不受欢迎的解决方案
我知道我可以将类型的语法重构为一个巨大的复杂混乱。
neverConstrainedType :: { ... }
neverConstrainedType :
'int' { ... }
| ... {- many more! -}
voidType :: { ... }
voidType :
'void'
pointerType :: { ... }
pointerType :
type '*' { ... } {- pointer -}
functionType :: { ... }
type '(' types ')' { ... } {- function -}
type :: { ... }
type :
neverConstrainedType { ... }
| voidType { ... }
| pointerType { ... }
| functionType { ... }
typeNonVoid :: { ... } {- this already exists -}
typeNonVoid :
neverConstrainedType { ... }
| pointerType { ... }
| functionType { ... }
typeNonPointer :: { ... }
typeNonPointer :
neverConstrainedType { ... }
| voidType { ... }
| functionType { ... }
typeNonFunction :: { ... }
typeNonFunction :
neverConstrainedType { ... }
| voidType { ... }
| functionType { ... }
typeNonFunctionPointer :: { ... }
typeNonFunctionPointer :
typeNonPointer { ... }
| typeNonFunction '*' { ... }
然后将callable定义为
callable :: { ... }
callable :
typeNonFunctionPointer operand { ... }
| type '(' types ')' '*' operand { ... }
【问题讨论】:
-
操作数是什么样的?
-
另外,这对您的问题并不重要,但我很好奇您对类型的定义。类型列表似乎以逗号开头 - 对吗?
-
@user5402 这些细节都不重要。知道
types与operand出现的任何地方总是完全相同就足够了。实际上types被定义为不能以,开头。本质上是types' : type | types' ',' type和types : {- empty -} | types'。