Points clé analyse syntaxique – PF, Info4

Table of Contents

Ce document résume, les points clé de l'analyse syntaxique récursive descendante enseignée dans ce cours. Les explications détaillées se trouvent dans les supports utilisés en CM, tels que anacomb_decouverte.ml.

1 Méthodologie

1.1 Étapes

Toujours bien suivre les trois étapes suivantes :

  • écrire la grammaire et la laisser en commentaire ;
  • écrire un analyseur pur basé sur analist et le tester ;
  • enfin, décorer le programme précedent avec des arguments supplémentaires pour obtenir un analyseur informatif basé sur ranalist.

Cela vaut aussi bien pour les programmes basés sur le style

let analyseur : ... =
  let l = auxiliaire1 l in
  let l = auxiliaire2 l in
  let l = auxiliaire3 l in
  etc.

que pour les programmes basés sur des combinateurs comme

let analyseur : ... =
  auxiliaire1 -->  auxiliaire2 --> auxiliaire3
  etc.

1.2 Élimination de la récursion à gauche

Commencer par transformer une grammaire récursive à gauche en un grammaire récursive à droite.

Par exemple un non-terminal R qui répète X au moins une fois avec un séparateur ','

R ::= R ',' X | X

s'exprimera plutôt :

R ::= X ',' R | X

ou plutôt, en factorisant X :

R ::= X S
S ::= ',' X S | ε

Attention, l'analyseur informatif qui en découle doit être programmé en respectant l'associativité à gauche qui est initialement prévue pour le séparateur (',' ci-dessus). À cet effet on programmera l'aspirateur pour X comme un programme qui prend un argument supplémentaire transportant le contenu informatif de la séquence déjà parcourue – on peut le voir comme un accumulateur.

2 Pièges et astuces

2.1 Ajout de fun l -> l |>

Ce petit morceau de code est à placer au début de la définition d'un analyseur lorsqu'il est récursif.

2.2 Récupération de la valeur rendue par une fonction rendant un ranalist

À cet effet p_NonTerminal ++> est généralement suivi de fun x -> ...x capture le résultat rendu par p_NonTerminal .

2.3 Ajout d'un epsilon_res en fin de séquence

Considérons un membre droit de règle de grammaire A B C traduit en analist par une composition séquentielle.

p_A --> p_B --> p_C

La version ranalist est obtenue en remplaçant --> par ++> fun selon le mécanisme décrit précédemment :

p_A ++> fun a -> p_B ++> fun b -> p_C fun c -> code_final

À l'endroit de code_final, on a la visibilité de a, b et c et on peut donc fabriquer une expression f a b c qui sera l'information retournée (par exemple un AST fait avec les sous-AST a, b et c). Mais on ne peut pas écrire simplement

p_A ++> fun a -> p_B ++> fun b -> p_C ++> fun c -> f a b c

car il faut retourner non seulement f a b c mais aussi la liste restant après aspiration successive d'un A par p_A, d'un B par p_B et d'un C par p_C. C'est d'ailleurs signalé au niveau du typage OCaml.

D'un point de vue grammatical on ajoute en fait un ε supplémentaire, ce qui revient à remplacer le membre droit A B C par A B C ε. Rien de gênant car ε est élément neutre. Dans le code avec analist, cela serait traduit par :

p_A --> p_B --> p_C --> epsilon

Et dans le code avec ranalist :

p_A ++> fun a -> p_B ++> fun b -> p_C ++> fun c -> epsilon_res (f a b c)

Ainsi tout va bien, vérifiez en passant que les exigences du typage sont satisfaites.

Author: jf

Created: 2023-11-07 mar. 22:15

Validate