سؤال

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.

هل كانت مفيدة؟

المحلول

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.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top