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.
精彩评论