Vous êtes sur la page 1sur 18

AUTOMATE A PILE ET ANALYSE SYNTAXIQUE

Définition :

Un automate à pile (PDA) est un septuplet N = (S, ∑, Γ, s0, Z0, F, S) où :

- S est un ensemble fini d’états


- ∑ est l’alphabet d’entrée
- Γ est l’alphabet de pile
- s0 ϵ S est l’état initial
- Z0 symbole initiale de la pile
- F ensemble des états de satisfaction
- : S × ∑ × Γ → S × Γ* est la fonction de transition

PDA

a a

X Z

A A
Contrôle Contrôle
. 

Z0 Z0

(s, a, X) = (q, X)

(s, a, X) = (q, ABX)

(s, a, X) = (q, ε)

Définition : Mots reconnues par un PDA. N

On a deux modes de reconnaissance, par pile vide et état de satisfaction.


1. Par pile vide

L (N, vide) = {ꞷ, ∑* /  q ϵ S / *(s0, ꞷ, Z0) = (q, Z0)}

2. Par état de satisfaction


L(N, satisfaction ) = {ꞷ, ∑* /  Z ϵ Γ* et * (s0, ꞷ, Z0) = (q , Z) q ϵ F}

Théorème

ꞷ ϵ L (N, vide) équivaut L(N, satisfaction)

On peut représenter un PDA par un diagramme de transition dans lequel la transition

(s, a, X) = (qZ, X) est représenté par :

a, X/Z
s q

Remarque : un PDA est dit non-déterministe s’il a des transitions de la forme

(s, ε, X) = (q, X)

Exemple :

S→ab /asb

Cette grammaire reconnait le langage L = {a nbn, n≥1}. Ce langage n’est pas régulier et ne
peut pas être reconnu par un automate d’état fini. Mais ce langage est reconnu par le langage a
pile suivant :

NB : tous les mots à analyser se termine par le marqueur de fin $

∑ = {a, b}

Γ = {a, b, $} Z0 = $

S = {q0, q1, qF} F = {qF}


b, a / ε $, $ / $

q0 qF
q1

Pour se convaincre que cet automate reconnait bien le langage {a nbn / n≥1} on peut montrer
que : [q0, an, $] * [q0, ε, an$]

[a0, b, an$]  [a1, ε, an-1$]

[a1, bk, ak$] * [a1, ε, $] (* = k)

[a1, $, $]  [qF, $, $] satisfaction

De ce qui précède on a bien : [q0, anbn, $] *[qF, $, $]

Exercice

i. Déterminer une grammaire algébrique qui généré L1 = {ꞷ ⸦ ῶ / ꞷ ϵ {a, b}*} ῶ est le


miroir de ꞷ en abbaacaabba

Déterminer un PDA qui reconnait ce langage :

ii. L2 = {ꞷ ⸦ ῶ / ꞷ ϵ {a,b}*}
iii. L3 = {ꞷ / ꞷ=ῶ ϵ {a,b}*}

Algorithme de décision :

état : = initial ;

pile[0] : = $

sommet : =0

C : = car-suivant ; erreur : = faux ;

Tq C < > $ et ⅂erreur faire


Début

(état, Z) := trans(état, C, pile[sommet]) ;

Mettre Z au sommet de la pile ;

Mettre à jour la variable sommet ;

C : = car-suivant ;

Fin

Si sommet = 0 alors accepté.

Exemple :

Analyseur de L = {anbn n≥1

état : =q0

pile [0] : = $

Sommet : = 0 ; erreur : = faux ; c : = car-suivant ;

Tq c ≠ $ et ⅂erreur faire

Début

Selon le cas de l’état faire

q0 : selon le cas de pile[sommet] faire

$ : selon le cas de c faire

b : erreur :=vrai

a :{état :=q0 ; pile[sommet+1] := ‘a’

sommet : = sommet +1 }

a :

Fin

ANALYSE SYNTAXIQUE
Etant donné une grammaire algébrique G = (V N, VT, ⅋, S), construire un analyseur
syntaxique de G revient à construire un PDA qui accepte (par pile vide) le langage généré par
G. On ajoute des actions aux transitions de cet automate qui permettent de construire une
dérivation gauche d’un mot accepté.

Exemple: S→ab / aSb L(S) = {anbn / n≥1}

a,$/a$ b, a/ε
a,$ / a$ b, a/ ε $,$/ $
0 1 $

a,a /aa

Cet automate reconnait juste un mot sans construire un arbre de dérivation du mot reconnu.
On peut remarquer qu’étant donné un PDA, on peut construire un PDA qui reconnait le même
langage mais dont les états indiquent le symbole qui se trouve au sommet de la pile.

a,a/aa
a, $ / a$ b, a$ / $ $, $$
$1 a $2 qF

b, aa/a
L’écriture de l’analyseur devient plus simple :

pile[0] = $ sommet : = 0 ;

Tq C ≠ $ et ⅂erreur faire

Début

Selon le cas de pile[sommet] faire

Début

a: si C = ‘a’ alors {pile[sommet+1] ← ‘a’

sommet ← sommet + 1}

Si C = ‘b’ alors sommet : =sommet -1

Sinon erreur : = vrai

$ :

Fin

C : =car-suivant

Fin

Si ⅂erreur alors accepté.

On va utiliser ce principe pour construire un analyseur à partir de la grammaire. La pile de


l’automate va contenir la note de dérivation et l’état courant indique le sommet de la pile.

Exemple :

S → aA/ bB

A→ ca / aAa / bBa L = {ꞷ ⸦ ῶ / ꞷ ϵ {a, b}*}

B→cbbAb / bBb

On veut analyser abaacaaba$

Remarque
L’analyseur qui ne lit qu’un seul car à la fois doit décider à l’aide de ce caractère, de la
dérivation à faire. On peut simuler une dérivation à l’aide d’une pile.

S→aA→abBa

Pile entrée action

$S abaacaaba$ S→aA

$A baacaaba$ A→bBa

$aB aacaaba$ B→aAb

$abA acaaba A→aAa

$abaA caaba$ A→ca

$abaa aaba$ dépiler

$aba aba$ ….

$ab ba$ ….

$a a$ …

$ $ accepté
A→aAa
a,A/Aa a, aa/a
c, A / a
S→aA A
a
a, S /A a, a$ / $

b, A / Ba a,ab / b b/ ba /a
b→aAb $
S A→bBa
A

a,B/Ab

b, S / B b, b / $
S→bB

B b
c, B / b
b,B/Bb b, bb/b

Cet automate peut être résumé par une table d’analyse

Entrée

a b c $
Sommet S S→aA S→bB X X

De pile A A→aAa A→bBa A→ca X


B B→aAb B→bBb B→cb X
La table d’analyse permet
de décrire un analyseur
descendant. L’analyseur de la grammaire est donc:

pile [0] : = S sommet := 0 ;

c := car-suivant ; erreur := faux

Tant que c≠$ et ⅂erreur faire

Début
Selon le cas de pile[sommet] faire

S : si c = ‘a’ alors {écrire (S→aA) ; pile[sommet]←A}

Sinon

Si c=’0’ alors {S→bB) ; pile[sommet]←B}

Sinon erreur : = vrai ;

A : …....

B : si c=’b’ alors {écrire(B→bBb), pile[sommet]←b

Pile[sommet+1] ←B

Sommet : = sommet + 1 }

a: si c = ‘a’ alors sommet := sommet -1 (dépiler)

Sinon dsfefedf

b :

$ :

Remarques :

Nous avons dit que les grammaires non contextuelles (algébrique) sont gérées avec des
automates a pile. Dans le cas de notre étude de l’analyse syntaxique, nous effectuons une
analyse descendante (c’est-à-dire l’axiome vers les feuilles). Nous construisons des analyseurs
descendants, sans rebroussement (récursivité à gauche), appelé analyseur prédictifs.
L’exemple précèdent est un prototype de grammaire algébrique sans ambiguïté et sans
récursivité, qui nous a amené à écrire un analyseur descendant à partir de la table d’analyse.

Toute fois une table d’analyse descendante peut avoir des conflits, dans ce cas la
grammaire n’est pas LL(1) (est donc ambiguë). Une grammaire est dite LL(k) s’il faut un
maximum de k caractères à partir du symbole courant pour résoudre tous les conflits
d’analyse.
Exemple : une table d’analyse qui a des entrées multiples. Considérons la grammaire

S→abS / aSb

La table est

a b $

S→ab X X
S
S→aSb X X

Cette grammaire n’est pas LL(1) mais est LL(2), car qui suffit de consulter le caractère qui
suit ‘a’ pour résoudre le conflit. Cette grammaire est donc ambiguë.

Pour lever l’ambigüité on factorise à gauche :

Exemple 1 :

S→aA

A→bS/ Sb

Exemple 2 : résoudre la grammaire suivante LL(1)

S→aAbB / bB S→aAbB / bB

A→aA / a  A→a (A/ε)

B→bB / b B→b (B/ε)


 S→aAbB / bB S→aAbB / bB
A→aA’ A→aA’

A’→A / ε  A’→ aA’ / ε

B→b B’ B→b B’

B’→b / ε B’→bB’ / ε

Exercice: analyser le mot aabb$ L(S) ?

Outre les ambiguïtés, les méthodes d’analyse descendante ne fonctionnent pas


également avec des grammaires récursives à gauche. Une grammaire est récursive à gauche si
elle contient un non terminal X tel qu’il existe une dérivation X→+ Xα, α ϵ (V*N, VT)*.

Pour analyser une grammaire récursive à gauche avec la méthode descendante, il faut d’abord
transformer la grammaire.

Exemple3 : E→E*T | T E→TE’

T→T*F | F E’→*TE’ | ε

F→(E) | a T→FT’

T’→*FT’ | ε

F→(E) | a

Construction pratique des ensembles premier et suivant

Ensemble premier:

On calcule les ensembles premiers et suivant sur les non terminaux de G (bien que l’on
puisse aussi le faire sur des terminaux inutile)

1) Si X→ε ajouter ε à premier(X)


2) Si X→Yγ. γ ϵ (VT U VN)* , alors premier (Y) ⸦ premier (X)

Si de plus Y* ε alors premier(γ) ⸦ premier(X)

Ensemble suivant :
1- Mettre $ dans suivant (S), S l’axiome de la grammaire. $ le marqueur de fin du texte à
analyser.
2- Si X→αYβ alors premier(β) –{ε} ⸦ suivant(Y)
3- Si X→αY et si β *ε alors suivant (X) ⸦ suivant (Y)

Exemple : résoudre la grammaire G LL(1)

a- Faisons la grammaire S→aAbB / bB

A→a (A / ε)

B→ b (B / ε)

 S→aAbB / bB

A→aA’

A’→aA’ / ε

B→bB’

B’→bB’ / ε

Exemple : Analysons le mot aabb$

Pile entrée action

$S aabb$ S→aAbB

$BbA abb$ A→aA’

$BbA’ bb$ A’ →ε

$Bb bb$ depiler

$B b$ B→b B’

$B’ $ B’→ε

$ $ accepté
Remarque:

A la suite de cet exemple on constate que:

a- Lorsqu’au sommet de la pile on a un non terminal C et en entré un caractère c qui peut


être produit par C, on fait une dérivation du membre gauche C.
Dans le cas contraire, s’il n’y a pas une règle C → ε on déclare une erreur. Si C→ε
existe, on fait l’action C→ε.
b- Lorsqu’on a pas une grammaire qui n’est pas sur la forme de Greibich, il est difficile
de déterminer les actions d’analyse. Pour faciliter l’analyse on commence par
déterminer les ensembles premier et suivant. Elles permettent quand c’est possible de
remplir les entrées de la table d’analyse prédictives.

Premier(A) = à l’ensemble de tous les terminaux qui peuvent être produits par A

= {a ϵ VT / A *aα, α ϵ (VN U VT)*}

Suivant(A) = ensemble de tous les terminaux qui peuvent suivrent un mot généré par A

= {a ϵ VT U {$} / S *αAaβ, α,β ϵ (VN U VT)*}

Exemple3 :

S→aAbB / bB prem(S) = {a,b} suiv(S) = {$}

A→aA’ prem(A) ={a} suiv(A) = {b}

A’→aA’ / ε prem(A’) ={a,ε} suiv(A’) = {b}

B→bB’ prem(B) ={b} suiv(B) = {$}

B’→bB’ / ε prem(B’) ={b,ε} suiv(B’) = {$}

Exemple: A→aBDc

D→bD / ε

Suiv (B) = {b, ε}


a b $
S S→aAbB S→bB X
A A→aA’ X X
A’ A’→aA’ A’→ε X
B X B→bB’ X
B’ X B’→bB’ B’→ε

La grammaire est LL(1)

Exemple 4:

Montrer que la grammaire ci-dessous est LL(1). Dans ce cas écrire un


analyseur syntaxique pour cette grammaire.

E→TE’ prem(E) = {(, a} suiv(E) = {$,)}

E’→ +T E’ / ε prem(T) = {(, a} suiv(T) = {+, ), $ }

T→FT’ prem(F) = {(, a} suiv(F) = {+, *, $,) }

T’→*FT’ / ε prem(E’) = {+, ε} suiv(E*) = {), $ }

F →(E) / a prem(E) = {*, ε} suiv(T’) = {+,), $ }

+ * ( ) a $

E E→TE’ E→TE’

E’ E→+TE’ E’→ε E’→ε

T T→FT’ T→FT’

T’ T’→ε T’→*FT’ T’→ε T’→ε

F F→(E) F→a
La grammaire est LL(1)

Procédure Analyser (ꞷ$ : mot)

Begin

pile [0] : = $ ; pile[1] := E ;

Sommet : = 1 ; erreur : = faux ;

c := car-suivant ;

tq c ≠ $ et ⅂erreur faire

Début

Selon le cas de pile[sommet] faire

E : si c ϵ {(, a} alors

Début

Ecrire(E→TE’)

Pile[sommet] = E’

Pile[sommet+1] : = T

Sommet : = sommet +1

Fin

Sinon erreur : = vrai ;

E’ : si c ϵ {), $} alors

Sommet : = sommet + 1

Si c=’+’ alors

Début

Ecrire(E’→TE’)

Pile[sommet] : = E’
Pile[sommet+1] : = T

Sommet : = sommet +1

c :=car-suivant

Fin

Sinon erreur : = vrai ;

F : si c =’a’ alors

Début

Ecrire(F→a) ;

Sommet : = sommet-1

c : =car-suivant

Fin

Sinon

Si c= ‘ (‘ alors

Début

écrire (F→(E))

Fin

+ :

* :

( :

) :

Fin 

Fincas
Exercice

1- S→Ad / BF 2- S→AS / AB

F→f F / ε A→aA / ε

A→aA / ε B→bB / b

B’→bB

3- S→aG / adDf / BDC

B→bB / ε

D→ aD /b

G→gGK

4- Axiome est < I > I: instruction

< I >::= < A > / if < I > then < I > else < I >

< A >::= < B > < D >

< B > ::= x / (< I >) / ⅂ < B >

< D > := ε / ⅂ < B >

Vérifier la condition LL(1) pour cette grammaire.

Vérifier si ces grammaires sont LL(1). Auquel cas écrire les analyseurs.

5- Rendre LL(1) la grammaire ci-dessous

S→AB/A
A→Da / eD
B→b / bB
D→ε / dB

Obtenir une seule règle et écrire l’analyseur LL(1) de cette grammaire.


Exercice 6 :

On considère la grammaire S→SS+ / $S* / a

a- Montrer que aa+a* est généré par cette grammaire


b- Construire l’arbre de dérivation de cette chaine
c- Quel est le langage généré par cette grammaire ? Justifier

Exercice2 :

Quel est le langage généré par chacune des grammaires suivantes. Justifiez

a- S→0S1 / 01
b- S→ +SS / -SS /a
c- S→S(S)S / ε
d- S→ aSbS / bSaS / ε
e- S→ a/S + S/SS/ S * / (S)

Exercice 3: lesquels des grammaires de l’exercice 2 sont ambiguës ?

Exercice 4 : Montrer que toute chaine binaire généré par la grammaire a une valeur divisible
par 3.

num → 11/ 1001/ num 0 / num num

Vous aimerez peut-être aussi