Cours 6 : Partie avant d’un compilateur
Partie avant d’un compilateur
digraph {
rankdir=LR;
AL[label="Analyse lexicale (Lex) : expr. rat."];
AS[label="Analyse syntaxique (Yacc) : gramm. alg."];
Programme[label="Programme (alphabet UTF8/ASCII)"];
ASem[label="Analyse sémantique : optimisation/interprétation/prod. de code"];
Programme -> AL;
AL -> AS[label="𝛴^*"];
AS -> ASem[label="Abres de syntaxe"];
}
On veut générer des analyseurs syntaxiques qui sont des automates à pile déterministes pour une exécution en temps linéaire.
- Lex : générateur d’analyseurs lexicaux
- Yacc : générateurs d’analyseurs syntaxiques ⟶ donne un AST
Construction d’un automate à pile à partir d’une grammaire
- $q, A ⟶^𝜀 q, 𝛼^R$ pour $A⟶𝛼∈P$ (guess)
- $q, a ⟶^a q, 𝜀$ pour $a∈𝛴$ (check)
Cet automate est déterministe ssi $∀A∈N$, il existe au plus une règle $A⟶𝛼∈P$
i.e la classe $LL(0)$ de langages associés est :
- soit les singletons sur $𝛴^\ast$
- soit le vide
NB : problème : on ne peut donc reconnaître qu’un programme au plus, il nous faut donc étendre un peu la définition
- Automate à $k$-fenêtres :
-
$q, z⟶^{u,a} q’, 𝛾$
- où $u∈𝛴^{≤k}, a∈ 𝛴∪{𝜀}, q,q’∈Q, z∈𝛤, 𝛾∈𝛤^\ast$
- NB : on peut, sans perte de généralité, supposer $u∈𝛴^{k}$ quitte à compléter avec des $EOF$ à la fin du fichier
- $u$ est notre fenêtre de lecture (de $k$ lettres) ⟶ on ne touche pas à $u$ (à part sa première lettre), $a$ le symbole couramment lu (première lettre de $u$) _____
Sémantique :
$q, 𝛾z, uw ⟶^a q’, 𝛾𝛾’, w’$ si $(q, z, u, a, q’, 𝛾’) ∈𝛿$ tq $uw = aw’$
On accepte dans une configuration $(q, 𝜀, $^k)$ :
\[N(𝒜) ≝ \lbrace w∈𝛴^\ast \mid (q_0, z_0, w\$^k) ⟶^w_𝒜 (q, 𝜀, \$^k) \text{ pour } q∈Q\rbrace\]Syntaxe :
\[𝒜 = (Q, 𝛤, 𝛴, 𝛿, q_0, z_0)\]mais $𝛿⊆ Q×𝛤×𝛴^k×(𝛴∪ \lbrace 𝜀 \rbrace ) × Q × 𝛤^\ast$ fini
Déterministe si $∀ q, z, u∈Q ×𝛤×𝛴^k$ :
- soit il existe une seule transitions $q, z⟶^{u,𝜀} q’, 𝛾$
- soit il n’y en a pas et alors $∀a∈𝛴$, il existe au plus une transition $q, z⟶^{u,a} q’, 𝛾$
Soit un automate à pile à $k$ fenêtres. On peut construire un automate équivalent (avec $N(𝒜)\cdot $^k = L(𝒜’)$) qui de plus est dét. si $𝒜$ l’est.
Preuve :
\[𝒜' ≝ ⟨Q', 𝛤, 𝛴, 𝛿', q_0, \bot z_0, F⟩\]- $Q’ ≝ Q×𝛴^{≤k} \sqcup \lbrace q_f \rbrace$
- $F ≝ \lbrace q_f \rbrace$
- $𝛤’ = 𝛤 \sqcup \lbrace \bot \rbrace$
- \[𝛿' ≝ \lbrace \Big( (q, u), z, a, (q, ua), z \Big) \mid q∈Q, z∈𝛤, \vert u \vert<k, a∈𝛴\rbrace \\ ∪ \lbrace \Big( (q, u), z, 𝜀, (q', u'), 𝛾' \Big) \mid (q, z, u, a, q', 𝛾') ∈𝛿, u=au', \vert u \vert=k \rbrace \\ ∪ \lbrace \Big( (q, \$^k), \bot, 𝜀, q_f, 𝜀 \Big) \mid q∈Q \rbrace\]
Réciproque :
Premiers et suivants
\[Prem_k(𝛼) ≝ \lbrace \underbrace{k:w}_{\text{préfixe maximal de longueur } ≤ k \text{ de } w} \mid 𝛼⟹^\ast_{lm G} w\rbrace\]Pour $A∈N$ :
\[Suiv_k(A) ≝ \bigcup \lbrace Prem_k(𝛾) \mid S ⟹^\ast_{lm G} uA𝛾 \rbrace \\ = \lbrace \underbrace{k:v}_{\text{préfixe de longueur } k \text{ de } v} \mid S⟹^\ast_{G} 𝜃Av \rbrace\]Ex :
\[Prem_k(A) = \bigcup_{A⟶𝛼∈P} Prem_k(𝛼) \\ Prem(𝛼 \cdot 𝛽) = \lbrace k: ww' \mid w∈Prem_k(𝛼), w'∉Prem_k(𝛽) \rbrace \\ Prem_k(a∈𝛴) = \begin{cases} a \text{ si } k>0 \\ 𝜀 \text{ sinon} \end{cases} \\ Prem_k(𝜀) = \lbrace 𝜀 \rbrace\] \[Suiv_k(A) = \bigcup_{B⟶𝛼A𝛽∈B} \lbrace k: ww' \mid w∈Prem_k(𝛽), w'∈Suiv_k(B) \rbrace ∪ \lbrace 𝜀 \mid A=S \rbrace\]Ex :
\[S ⟶ E \$ \\ E ⟶ E+T \mid T \\ T ⟶ T*F \mid F \\ F ⟶ (E) \mid i\]N | Prem_1 | Suiv_1 |
---|---|---|
E | (, i | $, ), + |
T | (, i | *, $, ), + |
F | (, i | *, $, ), + |
- La $k$-fenêtre de $A⟶𝛼$ est :
- \[LA_k(A⟶𝛼) ≝ Prem_k\Big(𝛼 \cdot Suiv_k(A) \Big)\]
- Grammaire alg. $G$ fortement $LL(k)$ :
-
si $∀A⟶𝛼_1≠A⟶𝛼_2 ∈P$, $LA_k(A⟶𝛼_1) ∩ LA_k(A⟶𝛼_2) = ∅$
Th : Si $G$ est fortement $LL(k)$ alors son automate guess/check à $k$-fenêtres est déterministe.
Ex :
Dans l’exemple précédent, la grammaire n’est pas fortement $LL(1)$ :
\[LA_1(E ⟶ E+T) = \lbrace (, i \rbrace \\ LA_1(E ⟶ T) = \lbrace (, i \rbrace\]Comment changer la grammaire pour que ce soit le cas ?
\[S ⟶ E \$ \\ E ⟶ T E' \\ E' ⟶ 𝜀 \mid + T E' \\ T ⟶ F T' \\ T' ⟶ 𝜀 \mid * F T' \\ F ⟶ (E) \mid i\]N | Prem_1 | Suiv_1 |
---|---|---|
E | (, i | $, ) |
E’ | 𝜀, + | $, ) |
T | (, i | +, ), $ |
T’ | 𝜀, * | +, ), $ |
F | (, i | *, +, ), $ |
Maintenant :
\[LA_1(E' ⟶ 𝜀) = \lbrace \$, ) \rbrace \\ LA_1(E' ⟶ +TE') = \lbrace +\rbrace \\ LA_1(T' ⟶ 𝜀) = \lbrace +, ), \$\rbrace \\ LA_1(T' ⟶ *FT') = \lbrace *\rbrace \\\]Analyseur récursif descendant
Exemple :
fonction $E$ : $𝛴^\ast \ni w \mapsto w’ \text{ suffixe de } w$
w = T(w)
return E'(w)
fonction $T$ : $𝛴^\ast \ni w \mapsto w’ \text{ suffixe de } w$
w = F(w)
return T'(w)
fonction $F$ : $𝛴^\ast \ni w \mapsto w’ \text{ suffixe de } w$
if w == (w':
w = E(w')
if w == )w':
return w'
if w == iw':
return w'
fonction $E’$ : $𝛴^\ast \ni w \mapsto w’ \text{ suffixe de } w$
if w == 𝜀 or w == )w':
return w
if w == +w':
w = T(w')
return E'(w)
- Une grammaire est $LL(k)$ :
-
si $∀S⟹_{lm G} uA𝛿$ et $∀A⟶𝛼_1≠A⟶𝛼_2 ∈P$ :
\[Prem_k(𝛼_1𝛿) ∩ Prem_k(𝛼_2 𝛿) = ∅\]
Prop : Si $G$ est fortement $LL(k)$, alors elle est $LL(k)$
L’inverse est faux : il existe des grammaires $LL(2)$ qui ne sont fortement $LL(k)$ pour aucun $k$.
Prop : Si $G$ est $LL(1)$ alors elle est fortement $LL(1)$
Prop : Si $G$ est $LL(k)$, alors elle n’est pas ambiguë
Prop : Si $G$ est $LL(k)$, alors elle n’est pas récursive à gauche
Hiérarchies $LL(k)$
Langages algébriques
∨
Langages non ambigus
∨
Langages déterministes
∨
$\vdots$
∨
$LL(k)$ = fortement $LL(k)$
∨
$\vdots$
∨
$LL(1)$ = fortement $LL(1)$
∨
Langages rationnels
∨
$LL(0)$ (singleton ou vide)
Grammaires :
digraph {
rankdir=TB;
GA[label="Grammaires algébriques"];
GNA[label="Grammaires non ambiguës"];
LD[label="Grammaires déterministes"];
LLk[label="LL(k)"];
fLLk[label="fortement LL(k)"];
fLLk1[label="fortement LL(k-1)"];
LLk1[label="LL(k-1)"];
LL1[label="LL(1) = fortement LL(1)"];
LL0[label="LL(0) : au plus une règle par non terminal"];
LLk[label="LL(k)"];
GA -> GNA -> LD;
LD -> LLk[style="dashed"];
LLk -> {LLk1, fLLk};
LLk1 -> fLLk1;
fLLk -> fLLk1;
LLk1 -> LL1[style="dashed"];
fLLk1 -> LL1[style="dashed"];
LL1 -> LL0;
}
Prop : Soit $G$ $LL(k)$. On peut construire une grammaire équivalente fortement $LL(k)$.
Leave a comment