Epita 2008 THL Correction
Epita 2008 THL Correction
Epita 2008 THL Correction
Le sujet et une partie de sa correction ont été écrits par Akim Demaille.
Une copie synthétique, bien orthographiée, avec un affichage clair des résultats, sera toujours
mieux notée qu’une autre demandant une quelconque forme d’effort de la part du correcteur.
Une argumentation informelle mais convaincante, sera souvent suffisante.
1 Incontournables
Il n’est pas admissible d’échouer sur une des questions suivantes : chacune représente 25%
de la note finale. En d’autres termes, deux erreurs dans cette partie réduisent la note de la suite
de moitié.
1. Le langage engendré par S → aX S→b X → Sc est rationnel. vrai/faux ?
2 Langages rationnels
On pourra admettre le résultat principal de cette section dans la suite de l’épreuve.
1. Comment montre-t-on que l’intersection de deux langages rationnels est rationnelle ?
Correction: Par exemple en construisant le produit synchronisé de deux auto-
mates finis déterministes reconnaissant ces langages. Cf. le cours avec le cas de
l’intersection entre « les mots sur a, b avec un nombre impair de a » et « les mots
sur a, b avec un nombre impair de b » .
2. Comment montre-t-on que si un langage est rationnel, alors son « renversé » (tous les mots
écrits à l’envers) l’est aussi ?
Correction: Il suffit d’inverser toutes les flèches (y compris initiale et finales)
d’un automate reconnaissant le premier.
1
3. En déduire que {an bm |m ≤ n} n’est pas rationnel.
Correction: S’il l’était, alors l’intersection avec son renversé le serait aussi. On
montrerait alors que an bn est rationnel...
3 Si alors sinon
3.1 Grammaires
Considérons l’extrait de grammaire suivant :
<stm> : := if <exp> then <stm> else <stm>
| if <exp> then <stm>
| ···
1. Quelle est sa catégorie de Chomsky ? Justifier.
Correction: Grammaire hors-contexte : un seul symbole à gauche, et c’est un
non-terminal. Certaines règles ont plusieurs non-terminaux à gauche, elle n’est
donc pas rationnelle.
2. En considérant que <exp> et ... sont des terminaux, quelle est la catégorie de Chomsky du
langage engendré ? Justifier.
Correction: Supposons ce langage rationnel. Alors son intersection avec le
langage rationnel then∗ .else∗ doit l’être aussi. Or il est alors facile de voir qu’il ne
peut pas y avoir plus de else que de then. D’une façon certes un peu approxi-
mative, on voir que le résultat serait
La section 2 montre que ce langage n’est pas rationnel, ce qui permet de conclure
que le langage engendré est hors-contexte et non rationnel.
Noter que l’on ne peut pas juste se contenter de dire que « ce langage contient
thenn .elsem qui n’est pas rationnel, donc il n’est pas rationnel. « Contenir » est
bien trop flou, comme le montre la question 1.2.
3. Cette grammaire est-elle ambiguë ? Justifier.
Correction: C’est le « dangling-else » bien connu.
4. Produire deux arbres de dérivation différents d’une phrase la plus courte possible.
5. Pourquoi la syntaxe du shell comprend-elle un terminal fi ?
Correction: Pour désambiguïser.
3.2 Désambiguïsation
À partir de ce point on ne retiendra que l’interprétation la plus répandue dans les langages
de programmation : on attache un else au if le plus proche.
1. On rencontre fréquemment des macros comparables aux suivantes.
# define LOG(Msg) \
if ( using_syslog ) \
vsyslog (LOG_INFO , "%s\n", Msg ); \
else \
fprintf (stderr , "%s: %s\n", program_name , Msg)
2
Comment expliquez-vous cette différence de style ?
2. En introduisant <stm-if-then> et <stm-if-then-else>, proposer une grammaire non am-
biguë équivalente à celle-ci :
<stm-if> : := if <exp> then <stm-if> else <stm-if>
| if <exp> then <stm-if>
3. Dans la réalité la grammaire originelle est plutôt la suivante. Quel problème allons-nous
rencontrer pour adapter le travail précédent ?
3
<stm> : := if <exp> then <stm> else <stm>
| if <exp> then <stm>
| while <exp> do <stm>
| ···
3.3 Analyse LL
1. La grammaire suivante est-elle LL(k) ? Justifier.
<stm> : := if <exp> then <stm> else <stm>
| if <exp> then <stm>
| while <exp> do <stm>
| ···
Correction: Non, les deux premières règles ont le même f irst de partie droite.
4
Correction:
ast_t *
parse_stm (void)
{
ast_t *res;
switch ( lookahead )
{
case token_if :
{
ast_t *c = 0, *s1 = 0, *s2 = 0;
eat ( token_if );
cond = parse_exp ();
eat ( token_then );
s1 = parse_stm ();
if ( lookahead == token_else )
{
eat ( token_else );
s2 = parse_stm ();
}
return ast_if (c, s1 , s2 );
case token_while :
...
}
}
3.4 Analyse LR
1. Proposer une implémentation LALR(1) de la grammaire suivante qui tire parti des fonc-
tionnalités de Yacc.
<stm> : := if <exp> then <stm> else <stm>
| if <exp> then <stm>
| while <exp> do <stm>
| ···
Correction:
%nonassoc "then"
%nonassoc "else"
%%
stm:
"if" exp "then" stm "else" stm
| "if" exp "then" stm
| " while " exp "do" stm
| ...
;
2. Pourquoi préférer cette solution plutôt que celle retenue dans la section 3.2 ou dans la
section 3.3 ?