如何定义“else”块?

时间:2011-03-28 03:20:52

标签: c# parsing grammar ebnf irony

以下是我正在尝试的内容:

foreach_in.Rule = ToTerm("foreach") + "(" + VARIABLE + "in" + list_obj + ")";
foreach_as.Rule = ToTerm("foreach") + "(" + list_obj + "as" + VARIABLE + ")";
for_loop.Rule = ToTerm("for") + "(" + simple_assignment + ";" + comparison + ";" + assignment + ")";
if_condition.Rule = ToTerm("if") + "(" + comparison + ")";
if_else.Rule = if_condition + block + "else"; // <-- PROBLEM
preset_directive.Rule = foreach_in | foreach_as | for_loop | if_else | if_condition;
directive.Rule = preset_directive | custom_directive;
directive_blk.Rule = directive + block;

但是我得到了shift-reduce conflict。我不太清楚为什么......如果可以的话,不应该贪婪地抓住“别的”吗?不太确定如何定义一个else块,以便它只能跟一个“if”块。

我认为具有if_else节点和if节点的else块节点将是最佳的,因为当我尝试时我不必返回并检查先前的兄弟节点遍历AST。

如果您需要查看更多语法...请告诉我。 “块”基本上定义为{ blah }{}之间的一堆语句。)


尝试将其作为可选块:

custom_directive_kw.Rule = ToTerm("custom_directive1") | "custom_directive2";
custom_directive.Rule = custom_directive_kw + free_args_opt;
foreach_in.Rule = ToTerm("foreach") + "(" + variable + "in" + list_obj + ")" + block;
foreach_as.Rule = ToTerm("foreach") + "(" + list_obj + "as" + variable + ")" + block;
for_loop.Rule = ToTerm("for") + "(" + simple_assignment + ";" + comparison + ";" + assignment + ")" + block;
if_condition.Rule = ToTerm("if") + "(" + comparison + ")" + block + else_blk_opt;
else_blk.Rule = "else" + block;
else_blk_opt.Rule = else_blk | Empty;
preset_directive.Rule = foreach_in | foreach_as | for_loop | if_condition;
directive.Rule = preset_directive | custom_directive;
directive_blk.Rule = directive;

也不喜欢。仍然会发出警告。

2 个答案:

答案 0 :(得分:2)

没关系......反讽有这个神奇的PreferShiftHere()功能可以解决问题。

foreach_in.Rule = ToTerm("foreach") + "(" + variable + "in" + list_obj + ")" + block;
foreach_as.Rule = ToTerm("foreach") + "(" + list_obj + "as" + variable + ")" + block;
for_loop.Rule = ToTerm("for") + "(" + simple_assignment + ";" + comparison + ";" + assignment + ")" + block;
if_condition.Rule = ToTerm("if") + "(" + comparison + ")" + block;
if_else.Rule = if_condition + PreferShiftHere() + "else" + block;
preset_directive.Rule = foreach_in | foreach_as | for_loop | if_else | if_condition;
directive_blk.Rule = preset_directive | custom_directive;

答案 1 :(得分:1)

我猜这里,但你不应该把IF定义为:

if_condition.Rule = ToTerm("if") + "(" + comparison + ")" + block;

然后继续将else部分定义为:

else_block.Rule = ToTerm("else") + block;

最后把它们放在一起:

if_else.Rule = if_condition + else_block;

再一次,我猜这里,因为我还没有和EBNF合作过。