Domanda

Ecco cosa sto provando:

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;

Ma ottengo un shift-reduce conflict. Non sono sicuro del perché ... non dovrebbe afferrare avidamente "altro" se possibile? Non sono abbastanza sicuro di come definire un blocco altro in modo tale che possa essere seguito solo da un blocco "if".

Penso che un if_else bloccare il nodo con un file if nodo e un else Il nodo sarebbe ottimale perché allora non devo tornare indietro e controllare il fratello precedente quando provo a attraversare l'AST.

Se hai bisogno di vedere più grammatica ... fammi sapere. Un "blocco" è sostanzialmente definito come { blah } (un mucchio di dichiarazioni tra {}).


Provandolo come un blocco opzionale:

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;

Neanche questo piace. Lancia ancora l'avvertimento.

È stato utile?

Soluzione

Nevermind ... Irony ha questo magico PreferShiftHere() funzione che fa il trucco.

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;

Altri suggerimenti

Immagino qui, ma non dovresti definire se come:

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

E poi continua a definire l'altro parte come:

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

E finalmente metti tutto insieme:

if_else.Rule = if_condition + else_block;

Ancora una volta, immagino qui, perché non ho ancora lavorato con EBNF.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top