Vous êtes sur la page 1sur 99

Langages hors contexte :

Context-Free Languages
Introduction
Le contexte des langages hors contexte
Notion de Grammaires :
P→SVC
S → il | elle P ⤳¹ S V C
V → lit | ecrit
⤳² il V C
C→DN
D → une | la ⤳⁴ il lit C
N → leçon | voiture ⤳⁶ il lit D N
⤳⁸ il lit la N
il lit la leçon ⤳⁹ il lit la leçon 3
elle ecrit une voiture :

P ⤳¹ S V C ⤳³ elle V C ⤳⁵ elle ecrit C ⤳⁶ elle


ecrit D N ⤳⁸ elle ecrit une N ⤳¹º elle lit une
voiture
il lit les les la :

P ⤳¹ S V C
⤳² il V C
⤳⁴ il lit C
⤳⁶ il lit D N
⤳⁸ il lit : expected tokens la ou une
G = < T, N, R, S >
T : alphabet de terminaux
N : alphabet de non-terminaux
N ∩ T = ∅ et V = T ∪ V
R ⊆ V*× V* fini
S ∈ N : Start Symbol
L(G) = { w ∈ T* / S ⟹* w }
R ⊆ V*× V* fini
Le vide (epsilon) des deux côtés des règles de production :
Le vide à gauche et à droite
Cela veut dire quoi ?

Problème:
Du côté gauche cela signifie que le vide peut produire une
proto-phrase !
Deux restrictions s’imposent :

1. Le vide ne doit produire rien !


2. Mais il faut pouvoir produire le vide
Besoin fondamental devant être réalisé

R ⊆ V⁺ × V⁺ fini ∪ ( S → 𝜺 )
Exemple :

Sequence → Nom | Liste Fin


Nom → ali | fatima | omar
Liste → Nom | Nom ‘,’ Liste
‘,’ Nom Fin → et Nom

T = { ali, fatima , omar }; N= Sequence, Nom Liste Fin }


S = Sequence
Sequence → Nom 1
Sequence → Liste Fin 2
Nom → ali 3
Nom → fatima 4
Nom → omar 5
Liste → Nom 6
Liste → Nom ‘,’ Liste 7
‘,’ Nom Fin → et Nom 8
Les plus petits mots sont de longueur 1 :

Sequence →¹ Nom →³ ali


Sequence →¹ Nom →⁴ fatima
Sequence →¹ Nom →⁵ omar
Les plus mots de longueur 2 :
Sequence →² Liste Fin
→⁷ Nom ‘,’ Liste Fin
→⁶ Nom ‘,’ Nom Fin
→ ⁸ Nom et Nom → ...

Le nombre de mots de longueur 2 = 3*3


Les mots de longueur 3 :

Sequence → Liste Fin


→ Nom ‘,’ Liste Fin
→ Nom ‘,’ Nom ‘,’ Liste Fin
→ Nom ‘,’ Nom ‘,’ Nom Fin
→ Nom ‘,’ Nom et Nom
‘,’ Nom Fin → et Nom
Le nombre de symboles de la partie gauche d’une
règle de production peut diminuer

La réécriture de terminaux : le ‘i’ est réécrit ‘et’

Notre objectif qui est pouvoir analyser un mot est


loin d’étre garanti
Si la longueur de chaque proto-phrase gauche est
inférieure ou égale à celle de chaque proto-phrase
droite lui correspondant alors dans ce cas le
problème admet une solution.

Sinon ...

La diminution de la longueur de la partie gauche


pose problème de la terminaison
Grammaires monotones

R ⊆ V⁺× V⁺ fini ∪ ( S → 𝜺 )

𝞪 → 𝞫 𝞪, 𝞫 ∈ V⁺

Chaque couple de R vérifie :


|𝞪| ≤ |𝞫|
Sequence → Nom | Liste
Nom → ali | fatima | omar
Liste → NomFinal | Nom ‘,’ Liste
‘,’ NomFinal → et Nom

xE→yF
XE→YF
X→x
Y→y
Exemple : A →² aABC
A → abC →¹ aabCBC
A → aABC
→³ aabBCC
CB → BC
bB → bb →⁴ aabbCC
bC → bc →⁵ aabbcC
cC → cc
→⁶ aabbcc
A →¹ abC →⁵ abc
Cette grammaire dénote le langage aⁿbⁿcⁿ
Grammaires sensibles au contexte
Context -Sensitive Grammars (CSG)

𝞪A𝞫 → 𝞪𝞬𝞫
𝞬 ∈ V⁺
Toute grammaire sensible au contexte est
monotone
A → abC
A → aABC
CB → BC CB → CX
CX → BX
bB → bb
BX → BC
bC → bc
cC → cc
Toute grammaire monotone est sensible au
contexte
Grammaires hors contexte
Context-Free Grammars (CFG)

A → 𝞪
𝞪 ∈ V⁺, A ∈ N

Autrement dit : R ⊆ N × V⁺ fini ∪ ( S → 𝜺 )


Grammaire à Choix Finie
Langages finis

A → 𝞪
𝞪 ∈ T⁺
a,b
a a, b
A B C

A → aA | bA | aB A → aA | bA | aB
B → aC | bC B → a𝜺 | b𝜺
C → 𝜺
En général si A →* 𝜺

A → BC | Da | Ae | 𝜺
A → A’ | 𝜺
A’ → BC | Da | Ae | e

Tout langage rationnel est hors contexte


Grammaire linéaire à droite

A → uB | v
u ∈ T*, v ∈T⁺ , A, B ∈ N

Grammaire linéaire à gauche

A → Bu | v
u ∈ T*, v ∈T⁺ , A, B ∈ N
S→N |L& N S→a|f|o|L
N→a|f|o L→aF|fF|oF
L → N ‘,’ N | N F → ‘,’ L | & a | & f | &o

( ( (a + f + o) , )* (a + f + o ) & )? (a + f + o)
aⁿ n ∈ N Grammaires à. Choix Fini Type 4

aⁿ ∀ n ∈ N Grammaires Rationnelles Type 3

aⁿbⁿ Grammaires Hors Contexte- CFG Type 2

aⁿbⁿcⁿ Grammaires monotones MG - & Type 1


Grammaires sensibles au
contexte CSG
Grammaires syntagmatiques Type 0
Langages rationnels : a*

Finite . Mémoire :
Automaton - ∅ : FA
Langages hors contexte : aⁿbⁿ

IN : . I /o :
I : accepteur
I/O : Traducteur
O : Producteur
Finite
Automaton
. Mémoire :
LIFO - ∅ : FA
OUT :
Langages hors contexte : aⁿbⁿ
. I /o :
I : accepteur
IN :
I/O : Traducteur
O : Producteur

FA . Mémoire :
- ∅ : FA
LIFO - LIFO : PDA
Push Down
OUT Automaton
:
IN : . I /o :
I : accepteur
I/O : Traducteur
O : Producteur
FA

. Mémoire :
LIFO - ∅ : Finite Automaton
OUT : - LIFO : Push Down
Automaton
-
- RAM : Turing Machine
Mémoire & Machines:
- ∅ : FA
- LIFO : PDA
- LBRAM : Lineary Bounded TM
- RAM : TM
IN : . I /o :
I : accepteur
I/O : Traducteur
O : Producteur
FA

. Mémoire :
LIFO - ∅ : FA
OUT :
- LIFO : PDA
- LBRAM : LBTM
- RAM : TM
Langages hors contexte
& Analyse
Une approximation du type des langages de
programmation : ils sont hors contexte modulo le
typage !

Que représente en C : a * b ;

Deux lectures : expression et déclaration de variable


Grammaires des Expressions arithmétiques:

E→ E+E|E-E|E*E|E/E|n

Cette grammaire est de type 2 : CFG

Le langage engendré est donc Hors contexte

Mais est ce qu’il est rationnel ? Oui


n ( (+ | - | * | / ) n) *
expressions non parenthésées

E→ E+E|E-E|E*E|E/E| (E)|n

Le langage engendré par E n’est plus rationnel


E→ E+E (1)
|n (2)

● E ⤳² n
● E ⤳¹ E + E ⤳² n + E ⤳² n + n
● E ⤳¹ E + E ⤳² E + n ⤳² n + n
Deux dérivations pour un même mot : n + n

Un proto-mot avec deux non terminaux

Hors-contexte signifie que chaque non-terminal


engendre un langage qui est indépendant des autres
langages.
Deux choix s’immposent et conernent :

1. le sens de l’utilisation des règles de la grammair


: de la gauche vers la droite ou l’inverse :
derivation ou reduction.

2. le non-terminal à développer à chaque étape :


le plus à gauche ou le plus à droite.
Left Most ou Right Most
● E ⤳¹ E + E ● E ⤳¹ E + E
⤳² n + E ⤳¹ E + E+ E
⤳¹ n + E + E ⤳² n + E + E
⤳² n + n + E ⤳² n + n + E
⤳² n + n + n ⤳² n + n + n
Découvrir un mot avec deux structures différentes

Quelle est la distinction entre ces deux façons ? :


profonde ou un détail

Comment transcrire syntaxiquement ces deux


lectures ?
Le mot n + n + n est dit ambiguë
La grammaire est donc ambiguë

La question d'ambiguïté d’une grammaire


est indécidable
● E ⤳¹ E + E ● E ⤳¹ E + E
⤳² n + E ⤳¹ E + E+ E
⤳¹ n + E + E ⤳² n + E + E
⤳² n + n + E ⤳² n + n + E
⤳² n + ( n + n ) ⤳² ( n + n )+ n
E 1+2*3
+
E + E
1 *

n n 2 3

Arbre de dérivation ou arbre syntaxique concret

Arbre syntaxique abstrait (AST) : Abstract Syntax Tree


On crée un arbre de noeuds et qui sont étiquetés par les symboles
grammaticaux de telle manière que :

- les noeuds feuilles sont étiquetés par des terminaux, et les noeuds
internes par des non-terminaux ;

- le noeud racine est étiqueté par le symbole de départ de la


grammaire ;

- les fils d’un noeud interne X correspondent aux membres d’un


des choix de X, dans le même ordre que dans le choix ;

- les terminaux étiquetant les noeuds feuilles correspondent à la


suite de lexèmes, dans le même ordre que dans l’entrée.
E E

E + E E + E

n E + E E + E n

n n n
n

n + (n + n) (n + n) + n
E₊ E₊

En + E₊ E₊ + En

n En + En En + En n

n n n n

n + (n + n) (n + n) + n
E→ E+E |n
E₊ → E₊ + E₊ NON
E → E₊ |
E₊ → E₊ + OUI
E₊ → E + E ≡ E₊ → + E₊ NON
→ n E₊ → + OUI
E → E₊ |
⇒ E₊ → E₊ + | +
→n
E → E₊ | E → E+ |
⇔ E₊ → E + →n
→n

⇔ E→ E+n |n

Grammaire récursive à gauche


L’arbre syntaxique croit vers la gauche
n ( + n) *
En général :

S → S op S

op est symétrique donc la grammaire est


ambiguë
E→ E+E |E*E| n
Les opérateurs + et * sont associatifs à gauche :
la grammaire devient :

E→ E+n E→ E*n
|E*n |E+n
| n | n
Ces deux grammaires ne sont pas équivalentes

C’est la même grammaire


E₊ Eₓ

En + Eₓ E₊ * En

n En * En En + En n

n n n n

n + (n * n) (n + n) * n
E→ E+E |E*E| n E₊ → E₊ + E₊ NON
| E₊ + Eₓ OUI
E → E₊ | Eₓ |
| E₊ + OUI
E₊ → E + E
| Eₓ + E₊ NON
Eₓ → E * E
| Eₓ + Eₓ NON
→n
| Eₓ + OUI
| + E₊ NON
| + Eₓ NON
| + OUI
Eₓ → E₊ * E₊ NON
| E₊ * Eₓ NON
| E₊ * NON
| Eₓ * E₊ NON
| Eₓ * Eₓ NON
| Eₓ * OUI
| * E₊ NON
| * Eₓ NON
| * OUI
E → E₊ | Eₓ | E → E₊ | T
E₊ → E₊ + Eₓ | E + T → Eₓ |
Eₓ → Eₓ * | * E₊ → E + T
→n Eₓ → T *
→n

E→E +T| T E→E +T| T


T→T* | T→T* F|F
→n F→n
E→E +T| E +T|T
T→T* F|T/ F|F
F→n|(E)
Analyse descendante

Analyse prédictive par desente récursive


LL(1)
S → if E then S
| echo bonjour
E → true | false

Quel est le type du langage engendré par S ?

( if ( true | false ) then )* . echo bonjour


Soit la grammaire :
S → if E then S fi | echo bonjour
E → true | false
● Analyse LL(1) :
On lit le mot de la gauche vers la droite
Left to rignt scanning of the input

On utiliser les règles de la gauche vers la droite


dérivation et on développe à chaque étape le
non-terminal le plus à gauche : Left Most drivation
● A chaque étape on dispose d’un seul symbole pour
prendre une décision d’analyse : lookahead symbol (la)

if true then if false then echo bonjour fi fi

la

S if E then S fi
La question :
Quelle partie droite de la notion non terminal utiliser ?

Une réponse : la partie droite qui engendre un mot qui


commence par le terminal de prévision la.
Deux cas se présentent pour le symbole courant de la
dérivation (le pointeur rouge) :

● Soit c’est un terminal : le comparer avec lookahead :


on lit le prochain ou on rentre dans le mode erreur

● Soit c’est un non-terminal : même question


if true then if false then echo bonjour fi fi

la la

S if E then S fi if true then S fi

if true then if false then S fi fi


if true then if false then echo bonjour fi fi
S

E S

E S

if true then if false then echo bonjour fi fi


Z→S$
S → if E then S fi | echo bonjour
E → true | false

if true then if false then echo bonjour fi fi $

la la
Z S$ if E then S fi $ if true then S

fi $ if true then if false then S fi fi $


if true then if false then echo bonjour fi fi $
if echo true false

S S → if E then S fi S → echo bonjour

E E → true E → false

Les entrés vides ?

Les colonnes : then bonjour fi ?


Les ensembles :

Premiers, Suivants et nullifiables:

First, Follow and Nullable


0 Z→S$
1 S → if E then S fi
2 S → echo bonjour
3,4 B → true | false if echo true false
5 E→B Z 0 0
E S 1 2
B 3 4
E 5 5
0 Z→S$
1 S → if E then S fi
2 S → echo bonjour
3,4 B → true | false if echo true false
5 E→NB Z 0 0
6 N→𝛆
S 1 2
E
B 3 4
E 5 5
N B N 6 6
Pour construire la table d’analyse on utilise
deux règles :
First (𝛼 )
Règle 1 :
A A →𝛼

Follow (A)
Règle 2 :
A A →𝛼 𝛆
● First (t) ={t} ∀ t ∊ T

● X → X1X₂...Xn
First (X1X₂...Xn) ⊇ First(X₁)\ {𝛆 }
si X₁ est nullable alors
First (X1X₂...Xn) ⊇ First(X₂)\ {𝛆 }
……

si ∀ j=1,..n, Xj est nullable alors X est nullable


M → 𝛼N : Follow(N) ⊇ Follow(M)

M → 𝛼N𝛽 :

● Follow(N) ⊇ First (𝛽)

● si 𝛽 𝛆 alors Follow(N) ⊇ Follow(M)


L’ensemble des nullifiables - Nullables :
Z → XYZ 0 1 2 3 0 1 2
Z→d Z N N N N Y N O O
X→a
X→Y X N N O O X N O O
Y→c
Y→𝛆 Y N O O O Z N N N

Les non terminaux nullable sont : X et Y


Null = { X, Y }
Les ensembles premiers First :
Z → XYZ First(Z) ⊇ First(XYZ) = First(X) ⋃First(YZ)
= First(X) ⋃ First(Y)⋃ First(Z)
Z→d First(Z) ⊇ {d}
X→a First(X) ⊇ {a}
0 1 2 3
X→Y First(X) ⊇ First(Y)
Y→c First(Y) ⊇ {c} Z ∅ d d, a, c d, a, c
Y→𝛆
X ∅ a a, c a, c

Y ∅ C c c
Les ensembles Follow :
Z → XYZ Follw(X) ⊇ First(YZ) = First(Y) ⋃ First(Z)
Follw(Y) ⊇ First(Z)
Z→d
X→a
X→Y Follow(Y ) ⊇ Follow(X) 0 1 2

Y→c Z ∅ ∅ ∅
Y→𝛆
X ∅ a, c, d a, c, d

Y ∅ acd a, c, d
LL a c d
Z → XYZ
Z→d Z Z → XYZ Z → XYZ Z → XYZ
X→a Z→d
X→Y
Y→c X X→a
X→Y X→Y X→Y
Y→𝛆

Y Y→𝛆 Y→c Y→𝛆


Y→𝛆
Une grammaire est LL(1) si
toute entrée de la table d’analyse est définie de
façon unique

( Zéro ou une (seule) règle de production )


S→E$ 0 E() {
switch(la) // lookahead symbol
E→E +T |T 1, 2 case First (E+T) :
T→T* F| |F 3, 4 E(); eat(+), T(); break;
case First (T) :
F→n|(E) 5, 6 T(); break;
} :
2 Problèmes !
n (
S 0 0

E 1, 2 1, 2

T 3, 4 3, 4

F 5 6
Toute grammaire récursive à gauche est non LL(1)

A → A 𝞪₁ | A 𝞪₂ |... | A 𝞪 | 𝞫₁ | 𝞫₂ |... | 𝞫

A → 𝞫₁ A’ | 𝞫₂ A’ |...| 𝞫 A’

A’ → 𝞪₁A’ | 𝞪₂A’ |... |𝞪 A’ | 𝛆


Toute grammaire non factorisée est non LL(1)

A → 𝞪𝞫₁ | 𝞪𝞫₂ |... 𝞪𝞫

A → 𝞪 A’

A’ → 𝞫₁ | 𝞫₂ |... | 𝞫
S → if b then S else S S → if b then S S’ | a
| if b then S | a S’ → else S | 𝛆

First Follow
Nullables S’
: S if , a else, $
S’ else else, $

LL if a else $

S 1 2

S’ 3, 4 4
S→E$ S→E$
E→T +E |T E → T E’
T→F* T| |F E’→ + T E’ | 𝛆
F→n|(E) 1 2 T → F T’
E’ o o
T’ → * F T’ | 𝛆
T’ o o
F→n|(E)
E N n
T N n
F N n
1 2
1 2 3 4
S→E$
E $, ) $, )
S ∅ ∅ ∅ n, (
E → T E’ E’ $ $, )
E ∅ ∅ n, ( n, (

E’ + + + +
E’→ + T E’ | 𝛆 T + +, $, )

T ∅ n, ( n, ( n, ( T → F T’ T’ + +, $, )

T’ * * * * T’ → * F T’ | 𝛆 F * *,+, $, )
F n, ( n, ( n, ( n, (
F→n|(E)
S→E$
E → T E’
First Follow
E’→ + T E’ | 𝛆
T → F T’ E n, ( $, )
T’ → * F T’ | 𝛆
E’ + $, )
F→n|(E)
n ( + * ) $
T n, ( $, ),+
S 0 0
E 1 1 3 3 T’ * $, ),+

E’ 2 3 3
F n, ( $, ), +,
T 4 4 *
T’ 6 5 6 6
F 7 8
// S → E $ : terminal courant est mémorisé
// dans la variable lookahead

void S () { E(); Traiter(‘$’); }

// E → T E’
void E() { T(); E’(); }

// E’→ + T E’ | 𝛆
void E’() { Traiter(‘+’); T(); E’(); }
/ / T → F T’
void T() {F(); T’();}

// T’ → * F T’ | 𝛆
void T’() { Traiter(‘*’); F(); T’(); }
//F→n|(E)
void F() {

if (looka==’n’) Traiter(‘n’);
else if (looka==(((‘) { E() ; Traiter(‘)‘);
else error();
}
Version itérative : pile explicite
Le mot à analyser : (n +n ) * n $

La dérivation :

S ⇒ E$ ⇒ TE’$ ⇒ FT’E’$ ⇒ (E)T’E’$ ⇒(TE’)T’E’$ ⇒(FT’E’)T’E’$

⇒ (nT’E’)T’E’$ ⇒ (n E’)T’E’$ ⇒ (n +TE’)T’E’$ ⇒ (n +FT’E’)T’E’$

⇒(n +nT’E’)T’E’$⇒(n + n E’)T’E’$ ⇒(n +n )T’E’$ ⇒(n +n )* F T’E’$

(n +n )* n T’E’$ ⇒ (n +n )* n E’$⇒ (n +n )* n $
Pile Entrée Action
$E (n+n)*n $ E → TE’
$E’T (n+n)*n $ T → FT’
$E’T’F (n+n)*n $ F → (E)
$E’T’)E( (n+n)*n $ dépiler
$E’T’)E n+n)*n $ E → TE’
$E’T’)E’T n+n)*n $ T → FT’’
$E’T’)E’T’F n+n)*n $ F→ n
$E’T’)E’T’n n+n)*n $ dépiler
$E’T’)E’T’ +n)*n $ T’ → 𝛆
$E’T’)E’ +n)*n $ E’ → +TE’
$E’T’)E’T+ +n)*n $ dépiler
$E’T’)E’T n)*n $ T → FT’
$E’T’)E’T’F n)*n $ F→ n
$E’T’)E’T’n n)*n $ dépiler
$E’T’F n$ F→ n
$E’T’n n$ dépiler
$E’T’ $ T’ → 𝛆
$E’ $ E’ → 𝛆
$ $ Le mot est accepté
Interprétation : Compliquée
E
Comment peut-on évaluer
une expression ?
T(1) E’
1 +2+3
+ T(2) E’

+ T(3) E’
𝛆

1 +2+3
int S () { int e = E(); Traiter(‘$’); return e; }

// E → T E’
int E() { int t = T(); int e = E’( t ); }

// E’→ + T E’ | 𝛆
int E’(int t1) { Traiter(‘+’); int t = T(); int e = E’(t ) + t1 ; }
Extended Backus Naur Form : BNF to EBNF
E → T + E | T - E |T
T→F* T|F/ T |F
F→n|(E)

⇔ E → T (+T | -T )*
T → F (* F | / F)*
F→ n|(E)
void E () {
T();
while (la {+,-})
if (la==+) { Traiter(+); T(); }
else // la ==-
{ Traiter(-); T(); }

}
int E () {

int valeur = T();


while (la {+,-})
if (la==+) { Traiter(+); valeur +=T(); }
else // la ==-
{ Traiter(-); valeur -=T(); }

return valeur
Analyse ascendante

● Analyse par décalage réduction

● Analyse LR

Vous aimerez peut-être aussi