开发者

How can I define an "else" block?

Here's what I'm trying:

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 = dir开发者_如何学Goective + block;

But I get a shift-reduce conflict. I'm not quite sure why... shouldn't it greedily grab the "else" if it can? Not quite sure how else to define an else block such that it can only be followed by an "if" block.

I think an if_else block node with an if node and an else node would be optimal because then I don't have to go back and check the previous sibling when I try traverse the AST.

If you need to see more of the grammar...just let me know. A "block" is basically defined as { blah } (a bunch of statements between {}).


Trying it as an optional block:

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;

Doesn't like that either. Still throws the warning.


Nevermind... Irony has this magical PreferShiftHere() function that does the trick.

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;


I'm guessing here, but shouldn't you define the IF as:

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

And then go on to define the else part as:

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

And Finally put it all together:

if_else.Rule = if_condition + else_block;

Once more, I'm guessing here, 'cause I haven't worked with EBNF yet.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜