Salut,
Je dois parser une grammaire qui malheureusement a, en l’état, un conflit de shift reduce. Et je ne peux pas faire grand chose pour changer la grammaire en question. J’ai essayé de simplifier au maximum (et j’espère n’avoir pas trop simplifié).
En gros, j’ai des règles qui ont une forme comme:
list_inst:
{ [] }
| inst list_inst { $1 :: $2 }
inst:
| IF exp inst { ... }
| IF exp inst ELSE inst { ... }
| IF exp inst OPEN_SPECIAL ELSE inst CLOSE_SPECIAL { ... }
| OPEN_SPECIAL inst CLOSE_SPECIAL { ... }
...
Le problème, c’est que si je suis dans un état:
IF exp inst ELSE . OPEN_SPECIAL
Le parseur ne peut pas savoir si je suis en train d’activer la troisième règle de inst
ou si je suis en train d’activer la quatrième règle, depuis la règle list_inst
. L’idéal dans ce cas serait de pouvoir changer la grammaire mais je n’en ai pas vraiment la liberté.
Du coup, je pensais utiliser le lexer pour aller jeter un oeil un peu en avant histoire de regarder ce que j’y trouve. Avec dans l’idée de dire "si je tombe sur ELSE, plutôt que mettre un token OPEN_SPECIAL, je met un token OPEN_SPECIAL_ELSE", ce qui règlerait le problème de la grammaire.
Du coup dans le lexer, j’ai tenté un truc super élégant à base de:
| "open_special" {
let pos = lexbuf.Lexing.lex_curr_pos in
look_for_else lexbuf ;
lexbuf.Lexing.lex_curr_pos <- pos ;
OPEN_SPECIAL
}
and look_for_else = parse
| blank { look_for_else lexbuf }
| "else" { next_else_special := true }
| "//" { do_lex_comment lexbuf }
| _ { () }
Juste pour voir si déjà je pouvais faire mon backtracking tranquillement, sans même tenter d’insérer quoi que ce soit pour l’instant. Mais ça explose (sur une opération refill_buff
). Alors avant d’investiguer plus (parce que le programme en question n’est pas un petit morceau), je voudrais déjà savoir si cette idée à la moindre chance de fonctionner ou si quelque chose d’intrinsèque à OcamlLex (dans la manière dont il gère le buffer par exemple) l’empêche complètement.