我有以下(严重剥离)快乐语法
%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
个案例。
如果我的问题不清楚,我道歉 - 部分问题是我很难确定问题甚至是什么。 :(
答案 0 :(得分:5)
首先,了解转变是很重要的。移位是接受下一个输入令牌并将其放在解析器堆栈上的结果(最终它将成为生产的一部分,但是没有必要知道哪一个。)减少需要零个或多个令牌在堆栈顶部与某些生产的右侧相匹配,并用左侧替换它们。
当解析器决定从identifier pattern
中创建binding_mode ident at_pat
时,at_pat
为空,它不会移位;它正在减少。实际上,它减少了两次:首先它将零堆叠符号减少为空at_pat
,然后将前三个堆栈符号减少为identifier pattern
。如果没有binding_mode
,则可以将ident
缩减为expr_path
,然后将expr_path
缩减为constant_expression
。这将是减少/减少冲突。
但还有另一个问题,正是因为binding_mode
可以为空。当解析器看到ident
时,它不知道binding_mode
是否可行,因此它不知道是否减少空binding_mode
或移位{{} 1}}。这是一个转变/减少冲突。由于它更喜欢shift to reduce,因此它选择移动ident
,这意味着无法生成空ident
,这反过来会排除减少/减少冲突(并阻止binding_mode
完全被认可。)
因此,为了解决所有这些问题,我们需要首先避免减少空ident @ pat
的必要性。我们通过通常的可空产生消除算法来做到这一点,该算法包括制作右侧的两个副本,一个具有可空的非终结,另一个没有;然后我们删除可空的生产。一旦我们这样做,就会出现减少/减少冲突。
为了避免减少/减少冲突,我们需要明确哪个生产是首选。减少/减少冲突不能通过优先级声明来解决,因为优先级算法总是涉及生产(可以减少)和终端(可以转移)之间的比较。所以解决方案必须是明确的,这意味着我们需要说明binding_mode
是一个模式,而ident
不是expr_path
是一个常量表达式。这给我们留下了以下内容:
(请注意,我使用非终端标记ident
的三个不同作品,而不是依赖于行动。对我来说,这更容易思考和阅读。)
pattern
以下是空产生消除:
pattern: identifier_pattern | constant_expression | struct_pattern
以下是对观点的明确禁止:
identifier_pattern: ident at_pat
| binding_mode ident at_pat
constant_expression: complex_expr_path
struct_pattern: expr_path '{' '..' '}'
不再可以为空:
binding_mode
这里我们创建两个不同的expr_paths:
binding_mode: mut
at_pat
: '@' pat
| %empty
我希望解决方案与原始语法有一定的关系。