Comment définir un bloc « else » ?
Question
Voici ce que j'essaie:
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;
Mais j'obtiens un shift-reduce conflict
.Je ne sais pas trop pourquoi...ne devrait-il pas saisir avidement le « autre » s'il le peut ?Je ne sais pas trop comment définir autrement un bloc else de telle sorte qu'il ne puisse être suivi que d'un bloc "if".
je pense qu'un if_else
bloquer le nœud avec un if
nœud et un else
Le nœud serait optimal car je n'ai alors pas besoin de revenir en arrière et de vérifier le frère précédent lorsque j'essaie de traverser l'AST.
Si vous avez besoin d'en savoir plus sur la grammaire... faites-le-moi savoir.Un « bloc » est essentiellement défini comme { blah }
(un tas de déclarations entre {}
).
Essayez-le en tant que bloc facultatif :
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;
Il n'aime pas ça non plus.Jette toujours l'avertissement.
La solution
Pas grave...L'ironie a cette magie PreferShiftHere()
fonction qui fait l'affaire.
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;
Autres conseils
Je suppose ici, mais ne devriez-vous pas définir le IF comme :
if_condition.Rule = ToTerm("if") + "(" + comparison + ")" + block;
Et puis continuez en définissant la partie else comme :
else_block.Rule = ToTerm("else") + block;
Et enfin, rassemblez le tout :
if_else.Rule = if_condition + else_block;
Encore une fois, je suppose ici, car je n'ai pas encore travaillé avec EBNF.