Probleme – La grammaire de balisage du programme, de bout en bout
Exercice · niveau 3 (difficile) · informatique (MP2I/MPI), chapitre 30 — Grammaires non contextuelles
Énoncé
On étudie complètement , .
- Démontrer que la grammaire n'est pas ambiguë.
- Écrire un analyseur qui construit l'arbre, et le vérifier par un aller-retour.
- Combien la grammaire engendre-t-elle de mots de longueur ?
Corrigé
1. La non-ambiguïté. Introduisons la hauteur .
Lemme. Tout vérifie et tout préfixe de vérifie . Tout vérifie , et tout préfixe propre et non vide de vérifie .
Preuve du lemme, par induction mutuelle. Pour : hauteur nulle partout. Pour : la concaténation de deux mots de hauteur nulle, dont les préfixes restent positifs. Pour : le a initial monte à , les préfixes de y ajoutent une quantité positive, et seul le b final redescend à .
La non-ambiguïté suit. Soit , non vide. Sa première lettre décide la règle : si c'est c, la seule règle possible est et ; si c'est a, la seule règle possible est . Il reste à montrer que la coupure entre et est unique : d'après le lemme, la partie est le préfixe de qui ramène à zéro pour la première fois, et cette position est déterminée par seul. Chaque nœud de l'arbre étant ainsi forcé, l'arbre est unique.
Le décompte machine confirme : les mots de longueur au plus ont chacun exactement un arbre d'analyse.
2. L'analyseur qui construit l'arbre. Le type inductif est la grammaire :
type arbre =
| Feuille (* S -> c *)
| Bloc of arbre * arbre (* S -> T S, avec T -> a S b *)
exception Echec
(* Analyse mot et rend son arbre. Leve Echec si mot n'est pas dans L(S).
INVARIANT : a l'appel de s (), pos designe le debut d'un mot de L(S) ;
au retour, pos designe la position juste apres ce mot.
VARIANT : n - !pos decroit strictement a chaque appel de lire. *)
let arbre_de mot =
let n = String.length mot in
let pos = ref 0 in
let lire c = if !pos < n && mot.[!pos] = c then incr pos else raise Echec in
let rec s () =
if !pos < n && mot.[!pos] = 'a' then
let dedans = t () in Bloc (dedans, s ())
else (lire 'c'; Feuille)
and t () =
lire 'a'; let a = s () in lire 'b'; a
in
let a = s () in
if !pos <> n then raise Echec;
a
(* Le mot se relit depuis l'arbre : c'est le test d'ALLER-RETOUR. *)
let rec vers_mot = function
| Feuille -> "c"
| Bloc (d, suite) -> "a" ^ vers_mot d ^ "b" ^ vers_mot suite
Terminaison. Chaque appel de t consomme au moins un caractère avant de rappeler s : le variant décroît strictement. Il n'y a pas de récursivité à gauche, et c'est ce qui rend l'analyseur possible.
Correction. L'invariant écrit au-dessus du code : le choix de règle est déterminé par le caractère courant — a force , tout le reste force —, ce qui est exactement le contenu de la démonstration de non-ambiguïté.
L'aller-retour. vers_mot (arbre_de w) = w doit être vrai pour tout du langage. Exécuté sur les mots reconnus de longueur au plus : aucun échec. C'est le test qui vaut le plus cher pour son prix : il éprouve d'un coup l'analyseur et la structure de l'arbre.
Les arbres obtenus :
c arbre c profondeur 1
acbc arbre T(c).c profondeur 3
aacbcbc arbre T(T(c).c).c profondeur 5
acbacbc arbre T(c).T(c).c profondeur 4
aaacbcbcbc arbre T(T(T(c).c).c).c profondeur 7
Noter les deux mots de longueur : même longueur, arbres de profondeurs et . L'un imbrique, l'autre juxtapose.
3. Le dénombrement. Notons le nombre de mots de de longueur , et celui de . Les deux règles donnent
On sait déjà que les longueurs sont congrues à modulo . Posons . Alors , et la première relation devient
qui est exactement la récurrence de Catalan. Donc .
Vérifié de deux façons : par énumération exhaustive de tous les mots sur trois lettres jusqu'à la longueur , qui donne mots pour ; et par la récurrence poussée jusqu'à , qui donne .
Pourquoi Catalan, encore. Parce qu'un mot du langage est un arbre : les blocs sont les nœuds, le c final est la fin d'une liste de fils. Le langage de balisage et les arbres binaires sont deux écritures du même objet — c'est ce que la remarque du chapitre appelle « une grammaire non contextuelle est une définition inductive ».
Les autres exercices de ce chapitre Le cours du chapitre
Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.