【发布时间】:2017-02-01 23:52:54
【问题描述】:
我有以下(严重剥离)快乐语法
%token
'{' { Langle }
'}' { Rangle }
'..' { DotDot }
'::' { ColonColon }
'@' { At }
mut { Mut }
ident { Ident }
%%
pattern
: binding_mode ident at_pat { error "identifier pattern" }
| expr_path { error "constant expression" }
| expr_path '{' '..' '}' { error "struct pattern" }
binding_mode
: mut { }
| { }
at_pat
: '@' pat { }
| { }
expr_path
: expr_path '::' ident { }
| ident { }
在模式中的标识符周围存在移位/减少冲突。默认情况下,Happy 选择转移,但在这种情况下,这不是我想要的:它会尝试将所有内容都塞进constant expression,即使它可能是identifier pattern。
我读过优先级/关联性是解决此类问题的方法,但我添加的任何内容都无法使语法朝着正确的方向发展(公平地说,我一直在拍摄在黑暗中)。
使用一些明显的标记化,我想要:
-
x产生identifier pattern -
mut x产生identifier pattern -
std::pi产生constant expression -
point{..}产生struct pattern -
std::point{..}产生struct pattern
基本上,除非有 { 或 :: 令牌等待使用,否则标识符应该转到 identifier pattern 案例。
如果我的问题不清楚,我深表歉意 - 部分问题是我很难确定问题所在。 :(
【问题讨论】:
-
我想你错过了一些作品。如图所示,没有冲突(也没有 constant_expression)
-
@rici 很可能就是这种情况。如果是这样,我将删除问题并在重新发布之前更仔细地查看它!不应该有
constant_expression生产——这只是我遇到pattern的expr_path变体后选择打印的消息。而且我认为应该至少存在一个移位/减少冲突 - 只给Ident,我可以从pattern转换为expr_path变体,或者完全减少binding_mode ident at_pat。 -
好吧,如果你将结果描述为生产而不是行动,对我来说会更清楚;我倾向于忽略行动。您是否打算将朴素的标识符作为一种模式?你为什么不直接写语法说呢?
-
是的,我的意图是让朴素的标识符成为模式。我没有这样写,因为我不相信其他部分不是问题的一部分。请随时编辑问题以使其更清楚 - 我不假装在编写语法方面有任何实际经验,更不用说调试它们了。
标签: haskell grammar parser-generator happy ambiguous-grammar