Question

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 = directive + 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.

Was it helpful?

Solution

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;

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top