Annexes

Transcription

Annexes
Annexes
pour le cours de
Compilation
2013 - 2014
M1 Informatique
Anne BERRY
Table des matières de l'Annexe :
• Petit cours de Théorie des Langages
• Exemples d'exécutions avec YACC avec code source généré
• Sorties YACC pour les exercices
• Support pour LEX et YACC pour les TP
Annexe 1 : Petit cours de théorie des langages
Support de cours : rappels de théorie des langages
Anne Berry
13 janvier 2009
1
Langages et grammaires
1.1
Définitions inductives
Idée : on procède en 3 étapes :
1. On se donne une base d’objets appartenant à l’ensemble que l’on veut définir (on n’exige
pas que la base soit minimale).
2. On se donne des règles pour construire d’autres objets de l’ensemble à partir d’objets
de la base ou d’objets déjà construits.
3. On déclare que les seuls objets de l’ensemble sont ceux construits en appliquant un
nombre fini de fois les règles.
(souvent on donne une définition inductive sous la forme base+règles)
Exemple :
Définissons l’ensemble PAIR des entiers pairs positifs
1. Base : 2 appartient PAIR
2. Règle : Si x est dans PAIR, alors x+2 est dans PAIR
Pour montrer qu’un nombre est dans PAIR, on exhibera une suite d’application des règles.
La définition inductive d’un ensemble n’est pas unique.
Exemple :
On peut définir PAIR par :
1. Base : 2 est dans PAIR
2. Règle : si x et y sont dans PAIR, alors x+y est dans PAIR
Avantage de la 2ème définition : les preuves qu’un nombre appartient à PAIR sont plus
courtes.
Définition formelle de la fermeture inductive :
Soit U un univers et B ⊂ U une base, soit Ω une famille d’opérations sur U . On appelle
fermeture inductive de B par Ω la partie E de U définie par :
1
1 LANGAGES ET GRAMMAIRES
2
- initialisation : B ⊂ E.
- construction : ∀f ∈ Ω et ∀x1 , x2 , ...xn ∈ E, si n est l’arité de f, si x=f(x1 , x2 , ...xn ) est
défini, alors x ∈ E.
- fermeture : E est la plus petite partie de U qui contienne B et qui soit stable par Ω.
On utilisera ce principe pour décrire de langage (qui est un ensemble de mots) par une grammaire, procédé formel de construction inductive du langage, sous la forme d’un axiome (la
base) et d’un ensemble de règles (appelées règles de production).
1.2
Langages
Un langage est un ensemble de mots, qui peut être défini de plusieurs façons :
- En extension : on donne la liste exhaustive de tous les mots du langage
- En compréhension : on commence une énumération
Exemple :
L={ab, aabb, aaabbb, ...}
- En intension : on se donne des règles
Exemple :
Tous les mots formés de ’a’ et de ’b’ qui comportent autant d’occurences de ’a’ que d’occurences de ’b’ et dont tous les ’a’ sont en début de mot.
1.3
Définitions
Définition 1 : Un alphabet Σ est un ensemble fini de caractères.
Définition 2 : Un mot (appelé aussi une chaı̂ne) ω sur Σ est une suite finie de symboles
de Σ juxtaposés. Sa longueur est notée |ω|, et |ω|a dénote le nombre d’occurences de
la lettre ’a’ de Σ dans le mot ω.
Exemple :
Σ = {a, b}
ω=abaab est un mot sur Σ
|ω|=5
|ω|a =3
Le mot vide, ne contenant aucun symbole, est noté ², avec |²| = 0.
Attention : ² peut être un mot d’un langage, mais n’est pas une lettre de l’alphabet.
Définition 3 : Si α et β sont 2 mots sur Σ, on appelle concaténation de α et β le mot αβ,
noté aussi α · β.
Exemple :
α = ab, β = cd, α · β = abcd
1 LANGAGES ET GRAMMAIRES
3
Concaténation avec le mot vide : α · ² = ² · α = α.
On notera an la concaténation de n occurences de a.
a0 dénotera le mot vide ².
Définition 4 : On appelle facteur ou sous-mot d’un mot ω un mot α tel qu’il existe 2 mots
β et γ tels que ω = β · α · γ.
Exemple :
ω = abccdx : cc est un facteur de ω.
Définition 5 : Si ω = β · α · γ, on dira que α est un préfixe de ω et
Exemple :
abc est un préfixe propre du mot abccdx ; abccdx est préfixe (mais pas propre) du mot
abccdx ; dx est suffixe du mot abccdx.
Définition 6 : Soit Σ un alphabet, on appelle fermeture de Kleene de Σ, noté Σ∗ , l’ensemble défini inductivement de la façon suivante :
base : tous les caractères de Σ ainsi que le mot vide ² sont dans Σ∗ .
règle : si x et y sont dans Σ∗ , alors xy est dans Σ∗ .
Σ∗ est l’ensemble des mots sur Σ, de longueur finie, plus le mot vide.
On note Σ+ = Σ∗ − ².
Définition 7 : On appelle langage (souvent noté L) sur un alphabet Σ un sous-ensemble
de Σ∗ .
Définition 8 : L1 (complémentaire de L1 ) est l’ensemble des mots de Σ∗ qui ne sont pas
dans L1 .
1.4
Opérations sur les langages
Soient L1 et L2 2 langages sur l’alphabet Σ
L1 ∪ L2 = {ω | ω ∈ L1 ou ω ∈ L2 }
L1 ∩ L2 = {ω | ω ∈ L1 et ω ∈ L2 }
Produit de 2 langages :
Soient L1 un langage sur l’alphabet Σ1 et L2 un langage sur l’alphabet Σ2
L1 L2 ={ω1 ω2 ∈ (Σ1 ∪ Σ2 )∗ , ω1 ∈ L1 et ω2 ∈ L2 }
Exemple :
On peut définir la fermeture de Kleene d’un langage de la façon suivante :
1 - L0 ={²}
2 - Ln =LLn−1 , ∀n≥1
3 - L∗ =∪Ln , n≥0
L+ =L∗ -{²}
L∗ est l’ensemble de tous les mots obtenus en concaténant un nombre fini de mots de L.
1 LANGAGES ET GRAMMAIRES
1.5
1.5.1
4
Grammaires
Backus-Naur Form
Méta-langage introduit par ALGOL60 qui est un moyen simple et élégant de décrire toutes
les phrases permises d’un langage de programmation.
Exemple (en langage naturel) :
<phrase > : := <sujet ><verbe ><objet >
<sujet > : := <déterminant ><nom >
<objet > : := <déterminant ><nom >
<verbe > : := mangent | voient
<déterminant > : := les | des
<nom > : := chats | lions | souris | jambons
Exemple de phrase permise : les jambons mangent des lions
On représentera une phrase par un arbre syntaxique.
phrase
sujet
déterminant
les
verbe
nom
jambons
objet
déterminant
mangent
des
nom
lions
Cet arbre constitue une preuve que la phrase appartient bien au langage.
1.5.2
Définition formelle des grammaires
Une grammaire est un quadruplet G = (N,T,P,S), où :
N = ensemble des symboles non terminaux, que l’on notera (habituellement) en utilisant des majuscules
T = ensemble des symboles terminaux, notés avec des minuscules
P = ensemble fini de règles de production de la forme α → β ou α → β | γ , avec
α ∈(N ∪T)+ , β ∈(N ∪T)∗
1 LANGAGES ET GRAMMAIRES
5
S = symbole de départ appelé l’axiome, c’est la racine de tout arbre de dérivation valide
Exemple :
On veut traduire le langage sur Σ = {a,b} où tous les mots sont de la forme ω = α · aa · β.
Voici une grammaire G = (N, T, P, S) correspondante :
S→AaaB(1)
A→aA(2) | bA(3) | ²(4)
B→aB(5) | bB(6) | ²(7)
S
A
a
aa
B
b
A
b
b
A
b
B
B
ε
A
ε
Un arbre syntaxique du mot ω = abbaabb pour la grammaire G.
Remarques :
1 - Il existe en général plusieurs grammaires différentes possibles pour décrire un même langage.
Définition : On notera L(G) le langage défini par la grammaire G. On dira que 2 grammaires
G1 et G2 sont équivalentes (noté G1 ∼ G2 ) si L(G1 ) = L(G2 ).
Exemple :
S→AaaA(1), A→aA(2) | bA(3) | ²(4) décrit une grammaire équivalente à la précédente.
2 - Une production comportant | comme A→aA | bA | ² est la même que A→aA, A→bA,
A→ ² ; la première forme est dite ’factorisée’.
3 - L’ordre dans lequel les règles de production sont données définit une numérotation
(implicite) des règles.
4 - On peut avoir des règles de production dont la partie droite est réduite à ² ; on appelera
ces règles ²-productions.
1.5.3
Dérivations
Considérons une grammaire G = (N, T, P, S).
Si α→β est une production de P, on note γ1 αγ2 ⇒ γ1 βγ2 .
1 LANGAGES ET GRAMMAIRES
6
On dit que γ1 βγ2 se dérive de γ1 αγ2 .
∗
Pour un nombre fini de dérivations successives γ1 αγ2 ⇒ γ1 βγ2 ⇒ ω, on écrit γ1 αγ2 ⇒ ω.
Le facteur ω est obtenable à partir de γ1 αγ2 avec la grammaire G.
Exemple :
∗
S⇒AaaA⇒aAaaA ou S⇒aAaaA
∗
S⇒abbaabb
On peut décrire un arbre syntaxique par une suite d’application des règles.
Exemple :
ω=abbaabb
(1)
(2)
(6)
(3)
(3)
(6)
(4)
(7)
S⇒AaaB⇒aAaaB⇒aAaabB⇒abAaabB⇒abbAaabB⇒abbAaabbB⇒abbaabbB⇒abbaabb
(1,2,6,3,3,6,4,7)
Définition : On appelle dérivation gauche une suite de dérivations obtenues en choisissant à chaque étape le symbole non terminal le plus à gauche. On définit de façon similaire
la dérivation droite.
Exemple de dérivation gauche :
(1,2,3,3,4,6,6,7) décrit le mot ω.
Définition : On appelle langage engendré par une grammaire G, noté L(G), l’en∗
semble des mots ω de T ∗ tels que S⇒ ω.
On dit qu’un mot ω est engendré par une grammaire G si ω ∈ L(G).
Remarque :
Les problèmes suivants sont indécidables, ie il n’existe pas (il ne peut pas exister) d’algorithme générique pour les résoudre.
- Deux grammaires G1 et G2 sont-elles équivalentes ?
- Deux grammaires engendrent-elles des langages ayant un mot en commun ?
- Y a-t-il des mots qu’une grammaire n’engendre pas ?
1.5.4
Grammaires ambiguës
Une grammaire G est dite ambiguë s’il existe un mot ω de L(G) qui admet au moins deux
arbres de dérivation différents. (Cela correspond à deux dérivations droites différentes, ou à
deux dérivations gaucehs différentes, mais PAS à deux dérivations quelconques différentes.)
Exemple :
S→AaA
2 LES LANGAGES RATIONNELS
7
A→aA | bA | ²
ω = aa
S
A
a
S
a
A
A
ε
A
a
ε
A
a
Α
ε
ε
Un langage est ambigü si toutes les grammaires qui l’engendrent sont ambiguës.
1.6
La hiérarchie de Chomsky
Chomsky était linguiste (1957).
Type
Nom
0
Langages
récursivement
énumérables
1
Langages contextuels
2
Langages context-free ou
algébriques
3
Langages
(réguliers)
rationnels
Type de production
X→Y
X ∈ N + , Y∈(N∪T)*
X→Y
X ∈ N + , Y∈(N∪T)* , |Y|≥|X|
X→Y
X ∈ N , Y∈(N∪T)*
X→Y
X ∈ N , Y=tA ou Y=t
Machines acceptant ce langage
Machines de Turing
Automates à plusieures piles
Machines de Turing bornées
Automates à piles
Automates d’états finis
les plus faciles → 3⊂2⊂1⊂0 ← les plus difficiles et les plus génériques
2
Les langages rationnels
2.1
Introduction
Les langages rationnels (en anglais : ’regular languages’) sont les langages de type 3 de la
hiérarchie de Chomsky ; ce sont les langages les plus simples et les moins puissants.
Ils servent
- en compilation à assurer l’analyse lexicale,
- pour la recherche de motifs, etc.
Ces langages sont caractérisés de plusieurs façons :
1. ils sont décrits par une expression régulière.
2. ils sont engendrés par un automate d’états finis.
2 LES LANGAGES RATIONNELS
8
3. ils sont engendrés par une grammaire régulière.
Quelques propriétés des langages rationnels :
Si L1 et L2 sont deux langages rationnels, alors
- L∗1 , L+
1 , L1 +L2 , L1 L2 , L1 ∩L2 sont des langages rationnels
- le complémentaire L1 de L1 est rationnel
Théorème : Les langages rationnels sont non ambigüs.
2.2
Les expressions régulières
Une expression régulière est une expression algébrique qui permet de décrire un langage rationnel.
Définition inductive des expressions régulières :
- Base : ∅, ² et les caractères de Σ sont des expressions régulières, représentant respectivement les langages ∅,{²}, {x} si x ∈ Σ.
- Règles : si r et s sont des expressions régulières représentant les langages R et S, alors
(r+s), r.s, r∗ et r+ sont des expressions régulières représentant respectivement les langages R∪S, R.S, R∗ et R+ .
Remarques :
- r+s est aussi r|s.
- r.s se note aussi rs.
Notation :
On notera L(r) le langage (rationnel) décrit par l’expression régulière r.
Exemple :
- Sur Σ={a,b}
(a + b)∗ est l’ensemble des mots sur {a,b}.
(a + b)∗ aa(a + b)∗ .
- Sur Σ={0,1}
0 + 1(0 + 1)∗ décrit les nombres binaires sans zéro inutile.
Remarques :
- On considère (souvent) dans les expressions régulières que * a précédence sur +.
2 LES LANGAGES RATIONNELS
9
Exemple :
a + b∗ s’interprète comme (a + (b∗ )).
- Un même langage rationnel peut être décrit par plusieurs expressions régulières différentes.
Exemple :
s=(a + b)∗ a(a + b)∗ a(a + b)∗
r=b∗ ab∗ a(a + b)∗
On a L(r)=L(s)
Notation :
Si L(r)=L(s), on dira que r et s sont des expressions régulières équivalentes, noté r∼s.
Propriétés :
- (r∗ )∗ = r∗ .
- r(r∗ ) = (r∗ )r = r+ .
- (a∗ b∗ )∗ = (a + b)∗ .
2.3
Les automates d’états finis (AEF)
(en anglais : ”Finite State Automata” ou FA)
2.3.1
Définition
Un système à états finis est un modèle mathématique ”discret”. Il est composé d’un nombre
fini de configurations, appelées des états, et d’actions permettant de passer d’un état à un
autre.
Les automates d’états finis sont des systèmes à états finis particuliers. On les représente par
un graphe orienté (fini) dont les arcs sont étiquetés.
Un automate d’états finis est composé de :
- un nombre fini d’états Q, qui sont les sommets du graphe.
- un alphabet Σ.
- un ensemble fini δ de transitions, qui sont les arcs du graphe, étiquetés chacun par une
(ou plusieurs) lettre(s) de Σ.
Parmi les états de Q, on distingue :
- l’état initial q0 (il y a un et un seul état initial).
- les états finaux (il peut y avoir plusieurs ou même aucun état final), qui constituent
l’ensemble F.
2 LES LANGAGES RATIONNELS
10
Formellement, un automate d’états finis est un quintuplet A = (Q, Σ, δ, q0 , F).
Exemple classique (voir Hopcroft et Ullman) :
Le passeur (M - Man), le loup (W - Wolf ), la chèvre (G - Goat) et le chou (C - Cabbage).
Quel est l’ensemble des solutions qui permettent au passeur d’emmener de la rive droite à
la rive gauche le chou, la chèvre et le loup, avec une barque ne pouvant contenir que l’un des
trois, sans laisser seuls ensemble le loup et la chèvre, ni la chèvre et le chou ?
G
G
C
W
M
C−MWG
W
MWGC−0
WC−MG
MWC−G
M
G
MGC−W
G
C
C
G−MWC
MG−WC
0−MWGC
W
W−MGC
C
G
M
G
MWQ−C
W
M
G
G
On peut déduire de cette modélisation par automate d’états finis :
1. qu’il y a une solution au problème.
2. qu’il y a deux plus courtes solutions étiquetées GMWGCMG et GMCGWMG.
3. qu’il existe une infinité de solutions (le langage engendré par l’automate est infini).
On peut étiqueter les arcs d’un automate d’états finis par le mot vide ² ; ces transitions s’appellent ²-transitions.
On dit qu’un automate d’états finis A = (Q, Σ, δ, q0 , F) accepte un mot ω de Σ∗ si et seulement si il existe (au moins) un chemin dans A allant de q0 à un état final, étiqueté par les
lettres successives de ω, entre lesquelles on a éventuellement intercalé des occurrences de ².
Le langage L(A) reconnu par A est l’ensemble des mots que A accepte.
Exemple 1 :
a
q0
b,c
q1
q2
q3
un état final
une epsilon−transition
état initial
signalé par une flèche
langage reconnu : L(A)={ab,ac}
on peut utiliser
b XOR c
2 LES LANGAGES RATIONNELS
11
Exemple 2 :
b
a
a
q1
q3
a
q0
q4
q2
b
b
b
langage reconnu : L(aab∗ a+bb∗ b)
On définit la table de transitions d’un automate d’états finis A = (Q, Σ, δ, q0 , F) qui décrit
la fonction de transition δ.
Sur l’exemple 2 :
q0
q1
q2
q3
q4
a
{q1}
{q3}
{∅}
{q4 }
{∅}
On utilise parfois un ”état poubelle”, noté
non définies.
2.3.2
b
{q2}
{∅}
{q2 , q4 }
{q3 }
{∅}
, vers lequel on envoie toutes les transitions
Le problème du déterminisme
Le définition d’un automate d’états finis n’interdit pas les ”conflits”.
Exemple :
L = aab∗ a + ab∗ b
b
a
a
q2
q1
q0
q4
q3
a
b
a
b
2 LES LANGAGES RATIONNELS
12
Comment doit-on interpréter δ(q0 , a) ?
Le choix est non-déterministe.
On définit 3 sortes d’automates d’états finis :
1. Les automates d’états finis déterministes (AEFD)
(en anglais : Deterministic Finite Automata (DFA) )
Ce sont des automates d’états finis tels que, de chaque état q∈Q, il part au plus 1 transition pour chacune des lettres de l’alphabet Σ.
Les transitions absentes partent vers l’état poubelle
représenté.
, qui souvent n’est même pas
Exemple :
La modélisation en automate d’états finis du problème du passeur est un automate d’états
finis déterministe avec un état poubelle implicite.
2. Les automates d’états finis non-déterministes (AEFND)
(en anglais : Non-deterministic Finite Automata (NFA) )
Ils comprennent :
- Les automates d’états finis non-déterministes sans ²-transition (NFA-W, W pour”Without”)
- Les automates d’états finis non-déterministes avec ²-transition (NFA-²)
Théorème fondamental :
La classe des langages reconnus par :
- Les automates d’états finis déterministes
- Les automates d’états finis non-déterministes sans ²-transition
- Les automates d’états finis non-déterministes avec ²-transition
est la même, celle des langages rationnels.
Preuve de ce théorème :
Elle est constructive, sous forme d’algorithmes de passage d’un type d’automates d’états
finis à un autre.
Principe de la détermination d’un automate d’états finis non-déterministe :
On se donne un automate d’états finis non-déterministe A1 = (Q, Σ, δ, q0 , F )
On calcule un automate d’états finis déterministe A2 = (Q0 , Σ, δ 0 , q00 , F 0 ), avec q00 ={q0 }
Principe :
On construit la table de transition de δ 0 et en même temps, on construit F’ :
1. On construit la table de transition de δ, comprenant des ensembles d’états
2. Construction de δ 0
2 LES LANGAGES RATIONNELS
13
- on commence par q00 ={q0 }
- on applique chaque lettre x de Σ à q00
- on obtient un ensemble d’états de Q qui est un état de Q’
- on continue jusqu’à stabilité
- les états finaux de A2 sont ceux qui contiennent au moins un état de F
Exemple :
L={ab,ac}
b
a
A1
q1
q2
q3
q4
q0
a
c
b
a
A2
Q0’
δ
q0
q1
q2
q3
q4
b
{∅}
{q2 }
{∅}
{∅}
{∅}
c
{∅}
{∅}
{∅}
{q4 }
{∅}
Q2’
Q1’
δ0
c
a
{q1 ,q3 }
{∅}
{∅}
{∅}
{∅}
Q3’
Q00 ={q0 }
Q01 ={q1 ,q3 }
Q02 =q2
Q03 =q4
a
{q1 ,q3 }=Q01
{∅}
{∅}
{∅}
b
{∅}
{q2 }=Q02
{∅}
{∅}
c
{∅}
{q4 }=Q03
{∅}
{∅}
Détermination d’un automate détats finis non-déterministe avc ²-transition :
On étend cette technique en étendant la fonction de transition δ 0 (Qi , x) à une fonction
donnée par les mots ²∗ x²∗
²-fermeture :
On appelle ²-fermeture d’un état q l’ensemble des états qi atteignables à partir de q par
un chemin étiqueté uniquement par ²
2 LES LANGAGES RATIONNELS
14
Exemple :
a∗ b∗ c∗
b
c
a
q1
q2
q0
On appelle ²-fermeture d’un ensemble Q d’états comme l’union des ²-fermetures des états
appartenant à Q
Exemple (sur l’automate traité précédemment) :
²-ferm(q0 )={q0 ,q1 ,q2 }
²-ferm(q1 )={q1 , q2 }
²-ferm(q2 )={q2 }
Principe :
On part de l’²-fermeture de Q00 .
On calcule δ(Q00 ), puis son ²-fermeture → on obtient un état de A2 .
Exemple :
δ
q0
q1
q2
a
{q0 }
{∅}
{∅}
b
{∅}
{q1 }
{∅}
c
{∅}
{∅}
{q2 }
²
{q0 ,q1 }
{q1 ,q2 }
{q2 }
Construction de δ 0 , Q00 =²-fermeture(q0 )={q0 ,q1 ,q2 }
δ0
Q00
Q01
Q02
a
{q0 } → Q00
{∅}
{∅}
b
{q1 } → {q1 ,q2 }=Q01
{Q01 }
{∅}
Tous les états sont finaux, on obtient l’automate :
c
{q2 } → {q2 }=Q02
{Q02 }
{Q02 }
2 LES LANGAGES RATIONNELS
15
b
b
a
Q1’
Q0’
c
c
Q2’
c
2.3.3
Minimisation d’un automate d’états finis déterministe
Théorème (Nérode - Myhill) :
Pour un langage rationnel donné L, il existe un automate d’états finis déterministe A canonique (c’est-à-dire uniquement défini, à un isomorphe de graphe près), et qui comporte un
nombre minimum d’états, reconnaissant L. De plus, il existe un algorithme efficace de minimisation.
Principe de minimisation d’un automate d’états finis déterministe :
Nous utiliserons le principe algorithmique d’éclatement de partitions.
Initialisation :
1. on retire les états non atteignables.
2. on partitionne l’ensemble Q des états en deux classes, les états finaux et les états non
finaux.
Principe d’éclatement de partition :
- prendre une classe Ci
- lui appliquer une transition x ∈ Σ
- séparer les éléments de Ci qui n’aboutissent pas à une même classe
On répète jusqu’à ce qu’il n’y ait plus d’éclatement possible.
A la fin, on a pour tout Ci une classe obtenue :
∀x ∈ Σ, ∀q, q 0 ∈ Ci , δ(x, q) = δ(q 0 , x) appartiennent à une même classe Cj .
On obtient la description d’un nouvel automate d’états finis déterministe, dont l’état initial
est l’état contenant q et dont les états finaux sont les états contenant un état final de F de
l’automate de départ.
2 LES LANGAGES RATIONNELS
16
Exemple :
L={ab, ac}
b
q3
a
q0
q2
q4
c
automate
a
Q3 Q4 |Q0 Q2 →Q3 Q4 |Q0 |Q2
On obtient un automate d’états finis déterministe à trois états.
b,c
a
q0
q2
q3,q4
Théorème :
Pour un langage raionnelL donné, il existe un unique automate détat fini déterministe
minimum engandrant L.
Conséquence fondamentale :
Les langages rationnels sont non ambigüs.
Lemme de la pompe :
Soit L un langage rationnel, soit A l’automate détat fini déterministe minimum reconnaissant L, soit k le nombre détats de A et soit ω ∈L tel que |ω| ≤k.
Alors il existe une décomposition de ω en ω=uvz respectant les conditions suivantes :
- |uv| ≤k
- |v| ≥ 1
- et telle que ∀i > 0 uviz∈L
u
q0
z
qi
qi+1
qj
qj+1
F
2 LES LANGAGES RATIONNELS
17
0
Passage d’une expression régulière à un automate d étatsf ininondéterministesans ²
transition
2.3.4
On utilise la définition inductive des expressions régulières :
- base :
r=²
q0
∅
q0
’a’
F
a
q0
F
- règles :
r1 + r2
r1
q0
r2
F
r1 r2
r1
r2
q0
F
r∗
r
q0
q1
F1
F
3 LES LANGAGES ALGÉBRIQUES
2.3.5
18
Grammaires régulières
Définition :
On dit qu’une grammaire est régulière à droite (respectivement à gauche) si et seulement si
toutes les règles de production de la forme A→ αB (respectivement A→Bα) avec α ∈ T ∗ , A,B
⊂ N.
Exemple :
Le langage 0(10)∗ est engendré par :
grammaire régulière à droite :
Base : S → 0A
Règle : A → 10A|²
grammaire régulière à gauche :
Base : S → S10|0
Théorème :
Les grammaires engendrent la classe des langages rationnels (un langage est rationnel si
et seulement si il existe une grammaire régulière qui l’engendre).
Un langage rationnel peut aussi être engendré par une grammaire non régulière.
Exemple :
0(10)∗ est aussi engendré par :
S → 0A
A → A10|²
Il existe des algorithmes de passage entre DFA et grammaire régulière.
Conclusion
Les langages rationnels sont une classe d’essence déterministe avec des algorithmes très
performants et de nombreuses applications, mais néanmoins insuffisante pour assurer toutes
les étapes de traduction nécessaires à la compilation.
3
3.1
Les langages algébriques
Existence de langages non rationnels
Pour prouver qu’un langage est non rationnel, on peut (parfois) se servir du lemme de la
pompe.
3 LES LANGAGES ALGÉBRIQUES
19
On utilise la contraposée de ce lemme :
Soit L un langage tel que, quel que soit n une constante, il existe un mot ω de L tel que,
pour toute décomposition de w en w=uvz (avec |uv |≤n et |v |≥1), il existe i fini positif tel
que uv i z n’est pas dans L, alors L n’est pas rationnel.
Exemple :
Soit L le langage des mots ”bien parenthésés” sur {a, b}∗ .
L={ω ∈{a, b}∗ / |ω|a =|ω|b et pour tout suffixe propre α |α|a ≥|α|b }
On veut montrer que L n’est pas rationnel.
On impose une constante n.
Soit ω=an+1 bn+1 .
ω est bien dans L et |ω|≥n.
On impose ω=uvz avec |uv|≤n et |v|≥1.
On remarque que u et v ne contiennent que des ’a’.
On a v 6= ².
Choisissons i=0.
Le mot ω’=uv 0 z a strictement moins de ’a’ que de ’b’, donc ω’∈L.
/
On peut en conclure que L est non rationnel.
Exemple :
Soit L l’ensemble des mots sur {a, b}∗ de la forme ω=an bn .
Montrer que L n’est pas rationnel.
Soit n une constante.
Soit ω=an bn .
Soit une décomposition (quelconque) ω=uvz avec |uv|≤n et |v|≥1.
Comme u et v ne comportent que des ’a’ et que v6= ², le mot ω’=uv0 z ∈L.
/
Par la contraposée du lemme de la pompe, L n’est pas rationnel.
Pour reconnaı̂tre si un mot est bien parenthésé, on peut utiliser une pile : lorsqu’on rencontre
une parenthèse ouvrante, on empile, et lorsqu’on rencontre une parenthèse fermante, on dépile
et on vérifie si le type de parenthèse est compatible.
Le principe de pile va permettre d’élargir les automates d’états finis à des ”automates à pile”
qui reconnaı̂tront la classe des langages algébriques.
3.2
Les automates à pile (AAP)
(en anglais : Push-Down Automata (PDA))
Définition : Un AAP est un système (Q,Σ, Γ, δ,q0 ,Z0 ,F,$) où :
Q un ensemble fini d’états ;
Σ un alphabet fini ;
Γ un alphabet de pile ;
3 LES LANGAGES ALGÉBRIQUES
20
δ une fonction de transition ;
q0 l’état initial ;
Z0 le symbole de fond de pile ;
F un ensemble d’états finaux ;
$ le symbole de fin de mot.
Etats possibles :
START
état initial
REJECT
un état poubelle (souvent implicite)
ACCEPT
un état final
READ
où b est une lettre de Σ
On lit le carctère suivant (x) du mot ω que l’on cherche à faire accepter par l’AAP, et on est
”guidé” par l’étiquetage des arcs sortants pour effectuer une transition.
POP
b
Z0
On dépile une lettre de Γ.
3 LES LANGAGES ALGÉBRIQUES
21
PUSH a
On empile une lettre de Γ.
Exemple :
Un AAP reconnaissant les mots bien parenthésés sur {a,b}∗ :
ω=²
ω=$
ω=aababb$
START
a
POP
Z0
REJECT
b
READ
$
a
PUSH a
POP
Z0
ACCEPT
a
REJECT
On représente souvent le fonctionnement de l’analyseur (ici un AAP) par un tableau.
Exemple :
ω=ab
caractères de ω restant à analyser
ab$
b$
b$
$
$
Etat de la pile
Z0
Z0 a
Z0 a
Z0
Z0
Action
READ
PUSH a
READ
POP
READ
POP
ACCEPT
Théorème
Les automates à pile reconnaissent la classe des langages algébriques.
3 LES LANGAGES ALGÉBRIQUES
3.3
22
Le problème du non-déterminisme
Il existe des langages algébriques qui sont non déterministes.
Définition : On appelle automate à pile déterministe un automate à pile n’admettant pas,
pour un état donné, 2 transitions différentes étiquetées par une même lettre.
Définition : On dit qu’un langage algébrique est déterministe si et seulement si il existe un
automate à pile détermniste qui reconnait ce langage.
Définition : Le langage des palindromes sur {a, b}∗ est l’ensemble des mots de la fomre ω = β,
αxβ(x ∈ Σ) telle que β lu de droite à gauche définit α.
Exemple :
NON
TOT
ESOPERESTEICIETSEREPOSE
Propriété :
Le langages des palindromes sur {a, b}∗ est algébrique et non déterministe.
Exemple :
Trouver un automate à pile reconnaissant le langage des palindromes de longueur impaire.
a,b
b
POP
b
START
READ
b
a
PUSH a
PUSH b
READ
$
POP
Z0
a
a
POP
Exemple :
Utiliser le lemme de la pompe pour montrer que palindrome impaire est non rationel.
Soit n une constante
ω=an+1 ban+1
ω=uvz, |uv|≤n
u et v sont formés de ’a’
uv 3 z ∈
/ palindrome impair
ACCEPT
3 LES LANGAGES ALGÉBRIQUES
23
Donc palindrome impair est non rationnel
3.4
3.4.1
Les grammaires algébriques
Définition
Définition caractérisante : Une grammaire G est dite algébrique (ou ’hors-context’ par
analogie avec le terme anglais : context-free) si et seulement si toutes les règles de production
sont de la forme :
A→ α, A∈N, α ∈ (N ∪ T )∗
Définition : Un langage L est dit algébrique si et seulement si il existe une grammaire
algébrique G qui l’engendre.
Exemple :
Soit G la grammaire définissant les mots bien perenthésés.
G : S→aSb |SS |²
3.4.2
Réécritures d’une grammaire algébrique
Il existe plusieurs algorithmes qui transforment une grammaire algébrique G1 en une grammaire algébrique G2 équivalente.
Ce procédé s’appelle la réécriture.
On verra par exemple pour les langages dits ’LL’ l’élimination de la récursivité gauche et la
factorisation gauche.
3.5
Quelques propriétés des langages algébriques
1. L est rationnel ⇒ L est algébrique.
2. Il existe des langages algébriques qui ne sont pas rationnels.
3. Il existe des langages algébriques qui sont déterministes et qui ne sont pas rationnels.
4. Il existe des langages algébriques qui ne sont pas déterministes.
(En compilation, on utilise des langages déterministes.)
5. Tout langage déterministe est non-ambigü.
6. Il existe des langages algébriques qui sont non ambigüs et non déterministes (ex : ’palindrome’).
7. Pour un langage algébrique L, les problèmes suivants sont indécidables :
- répondre à la question ”L est-il déterministe ?”
- répondre à la question ”L est-il ambigü ?”
8. Pour G1 , G2 des grammaires algébriques, les problèmes suivants sont indécidables :
3 LES LANGAGES ALGÉBRIQUES
- répondre à la question ”G1
24
G2 ?”
- répondre à la question ”L(G1 ) ∩ L(G2 ) = ∅ ?”
- répondre à la question ”existe-t-il ω, ω ∈
/ L(G1 ) ?”
9. Si G est une grammaire algébrique, on sait répondre aux questions :
- L(G) est-il vide ?
- L(G) est-il infini ?
- est-ce qu’un mot donné ω appartient à L(G) ?
10. Soient L1 et L2 des langages algébriques, alors
- L1 ∩ L2 n’est pas forcément un langage algébrique.
- L
à 1 n’est pas forcément un langage algébrique.
11. Si L1 est un langage algébrique et L2 est un langage rationnel, alors L1 ∩ L2 est un
langage algébrique.
12. Lemme de la pompe version langage algébrique :
Soit L un langage algébrique.
Il existe une constante n telle que, si ω ∈ L, |ω |≥ n, ω se décompose en ω=uvzxy avec
|vx |≥ 1, |vzx |≤ n, ∀ i ≥ 0 uvi zxi y ∈ L.
Contraposée :
Soit L un langage tel que, pour tout n, il existe ω ∈ L (|ω |≥ n) tel que, pour toute
décomposition ω=uvzxy respectant |vx |≥ 1 et |vzx |≤ n, alors il existe i tel que uvi zxi y
∈
/ L.
13. Il existe des langages non algébriques.
Exemple : an bn an , an bn cn , an bn cn dn ...
Annexe 2 : exemples d'exécutions avec YACC
sudo apt-get install byacc
Exemple : Grammaire G1 des expressions arithmétiques
r1 : E → E + T
r2 : E → T
r3 : T → T * F
r4 : T → F
r5 : F → (E)
r6 : F → 0|1|2|3|4|5|6|7|8|9
ou :
r6 : F → nb
fichier G1_exp
%%
E : E '+' T
|T
T : T '*' F
|F
F : '(' E ')'
| 'n'
;
%%
Bureau$ yacc -v G1_exp.yac
génère la création des fichiers :
y.output
y.tab.c
Le fichier y.output décrit la table LALR(1)
y.output
0 $accept : E $end
1 E : E '+' T
2 |T
3 T : T '*' F
4 |F
5 F : '(' E ')'
6 | 'n'
state 0
$accept : . E $end (0)
'(' shift 1
'n' shift 2
. error
E goto 3
T goto 4
F goto 5
state 1
F : '(' . E ')' (5)
'(' shift 1
'n' shift 2
. error
E goto 6
T goto 4
F goto 5
state 2
F : 'n' . (6)
. reduce 6
state 3
$accept : E . $end (0)
E : E . '+' T (1)
$end accept
'+' shift 7
. error
state 4
E : T . (2)
T : T . '*' F (3)
'*' shift 8
$end reduce 2
'+' reduce 2
')' reduce 2
state 5
T : F . (4)
. reduce 4
state 6
E : E . '+' T (1)
F : '(' E . ')' (5)
'+' shift 7
')' shift 9
. error
state 7
E : E '+' . T (1)
'(' shift 1
'n' shift 2
. error
T goto 10
F goto 5
state 8
T : T '*' . F (3)
'(' shift 1
'n' shift 2
. error
F goto 11
state 9
F : '(' E ')' . (5)
. reduce 5
state 10
E : E '+' T . (1)
T : T . '*' F (3)
'*' shift 8
$end reduce 1
'+' reduce 1
')' reduce 1
state 11
T : T '*' F . (3)
. reduce 3
7 terminals, 4 nonterminals
7 grammar rules, 12 states
Fichier y.tab.c :
#ifndef lint static const char yysccsid[] = "@(#)yaccpar1.9 (Berkeley) 02/21/93"; #endif #define YYBYACC 1 #define YYMAJOR 1 #define YYMINOR 9 #define YYPATCH 20100610 #define YYEMPTY (­1) #define yyclearin (yychar = YYEMPTY) #define yyerrok (yyerrflag = 0) #define YYRECOVERING() (yyerrflag != 0) #define YYPREFIX "yy" #define YYPURE 0 #ifndef YYSTYPE typedef int YYSTYPE; #endif /* compatibility with bison */ #ifdef YYPARSE_PARAM /* compatibility with FreeBSD */ # ifdef YYPARSE_PARAM_TYPE # define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM) # else # define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM) # endif #else # define YYPARSE_DECL() yyparse(void) #endif /* Parameters sent to lex. */ #ifdef YYLEX_PARAM # define YYLEX_DECL() yylex(void *YYLEX_PARAM) # define YYLEX yylex(YYLEX_PARAM) #else # define YYLEX_DECL() yylex(void) # define YYLEX yylex() #endif extern int YYPARSE_DECL(); extern int YYLEX_DECL(); #define YYERRCODE 256 static const short yylhs[] = { ­1, 0, 0, 1, 1, 2, 2, }; static const short yylen[] = { 2, 3, 1, 3, 1, 3, 1, }; static const short yydefred[] = { 0, 0, 6, 0, 0, 4, 0, 0, 0, 5, 0, 3, }; static const short yydgoto[] = { 3, 4, 5, }; static const short yysindex[] = { ­40, ­40, 0, ­39, ­36, 0, ­38, ­40, ­40, 0, ­36, 0, }; static const short yyrindex[] = { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, }; static const short yygindex[] = { 6, 3, 4, }; #define YYTABLESIZE 70 static const short yytable[] = { 1, 2, 1, 9, 7, 7, 8, 6, 0, 0, 10, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, }; static const short yycheck[] = { 40, 0, 0, 41, 43, 43, 42, 1, ­1, ­1, 7, ­1, 8, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, 41, 41, 43, 43, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, ­1, 110, }; #define YYFINAL 3 #ifndef YYDEBUG #define YYDEBUG 0 #endif #define YYMAXTOKEN 110 #if YYDEBUG static const char *yyname[] = { "end­of­
file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,"'('","')'","'*'","'+'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
,0,0,0, 0,0,0,0,"'n'", }; static const char *yyrule[] = { "$accept : E", "E : E '+' T", "E : T", "T : T '*' F", "T : F", "F : '(' E ')'", "F : 'n'", }; #endif /* define the initial stack­sizes */ #ifdef YYSTACKSIZE #undef YYMAXDEPTH #define YYMAXDEPTH YYSTACKSIZE #else #ifdef YYMAXDEPTH #define YYSTACKSIZE YYMAXDEPTH #else #define YYSTACKSIZE 500 #define YYMAXDEPTH 500 #endif #endif #define YYINITSTACKSIZE 500 int yydebug; int yynerrs; typedef struct { unsigned stacksize; short *s_base; short *s_mark; short *s_last; YYSTYPE *l_base; YYSTYPE *l_mark; } YYSTACKDATA; int yyerrflag; int yychar; YYSTYPE yyval; YYSTYPE yylval; /* variables for the parser stack */ static YYSTACKDATA yystack; #line 10 "G1_exp.yac" #line 151 "y.tab.c" #if YYDEBUG #include <stdio.h>
#endif #include <stdlib.h>
#include <string.h>
/* needed for printf */ /* needed for malloc, etc */ /* needed for memset */ /* allocate initial stack or double stack size, up to YYMAXDEPTH */ static int yygrowstack(YYSTACKDATA *data) { int i; unsigned newsize; short *newss; YYSTYPE *newvs; if ((newsize = data­>stacksize) == 0) newsize = YYINITSTACKSIZE; else if (newsize >= YYMAXDEPTH) return ­1; else if ((newsize *= 2) > YYMAXDEPTH) newsize = YYMAXDEPTH; i = data­>s_mark ­ data­>s_base; newss = (data­>s_base != 0) ? (short *)realloc(data­>s_base, newsize * sizeof(*newss)) : (short *)malloc(newsize * sizeof(*newss)); if (newss == 0) return ­1; data­>s_base = newss; data­>s_mark = newss + i; newvs = (data­>l_base != 0) ? (YYSTYPE *)realloc(data­>l_base, newsize * sizeof(*newvs)) : (YYSTYPE *)malloc(newsize * sizeof(*newvs)); if (newvs == 0) return ­1; data­>l_base = newvs; data­>l_mark = newvs + i; data­>stacksize = newsize; data­>s_last = data­>s_base + newsize ­ 1; return 0; } #if YYPURE || defined(YY_NO_LEAKS) static void yyfreestack(YYSTACKDATA *data) { free(data­>s_base); free(data­>l_base); memset(data, 0, sizeof(*data)); } #else #define yyfreestack(data) /* nothing */ #endif #define YYABORT goto yyabort #define YYREJECT goto yyabort #define YYACCEPT goto yyaccept #define YYERROR goto yyerrlab int YYPARSE_DECL() { int yym, yyn, yystate; #if YYDEBUG const char *yys; if ((yys = getenv("YYDEBUG")) != 0) { yyn = *yys; if (yyn >= '0' && yyn <= '9') yydebug = yyn ­ '0'; } #endif yynerrs = 0; yyerrflag = 0; yychar = YYEMPTY; yystate = 0; #if YYPURE memset(&yystack, 0, sizeof(yystack)); #endif if (yystack.s_base == NULL && yygrowstack(&yystack)) goto yyoverflow; yystack.s_mark = yystack.s_base; yystack.l_mark = yystack.l_base; yystate = 0; *yystack.s_mark = 0; yyloop: if ((yyn = yydefred[yystate]) != 0) goto yyreduce; if (yychar < 0) { if ((yychar = YYLEX) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal­symbol"; printf("%sdebug: state %d, reading %d (%s)\n", YYPREFIX, yystate, yychar, yys); } #endif } if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { #if YYDEBUG if (yydebug) printf("%sdebug: state %d, shifting to state %d\n", YYPREFIX, yystate, yytable[yyn]); #endif if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack)) { goto yyoverflow; } yystate = yytable[yyn]; *++yystack.s_mark = yytable[yyn]; *++yystack.l_mark = yylval; yychar = YYEMPTY; if (yyerrflag > 0) ­­yyerrflag; goto yyloop; } if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { yyn = yytable[yyn]; goto yyreduce; } if (yyerrflag) goto yyinrecovery; yyerror("syntax error"); goto yyerrlab; yyerrlab: ++yynerrs; yyinrecovery: if (yyerrflag < 3) { yyerrflag = 3; for (;;) { if ((yyn = yysindex[*yystack.s_mark]) && (yyn += YYERRCODE) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) { #if YYDEBUG if (yydebug) printf("%sdebug: state %d, error recovery shifting\ to state %d\n", YYPREFIX, *yystack.s_mark, yytable[yyn]); #endif if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack)) { goto yyoverflow; } yystate = yytable[yyn]; *++yystack.s_mark = yytable[yyn]; *++yystack.l_mark = yylval; goto yyloop; } else { #if YYDEBUG if (yydebug) printf("%sdebug: error recovery discarding state %d\n", YYPREFIX, *yystack.s_mark); #endif if (yystack.s_mark <= yystack.s_base) goto yyabort; ­­yystack.s_mark; ­­yystack.l_mark; } } } else { if (yychar == 0) goto yyabort; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal­symbol"; printf("%sdebug: state %d, error recovery discards token %d (%s)\n", YYPREFIX, yystate, yychar, yys); } #endif yychar = YYEMPTY; goto yyloop; } yyreduce: #if YYDEBUG if (yydebug) printf("%sdebug: state %d, reducing by rule %d (%s)\n", YYPREFIX, yystate, yyn, yyrule[yyn]); #endif yym = yylen[yyn]; if (yym) yyval = yystack.l_mark[1­yym]; else memset(&yyval, 0, sizeof yyval); switch (yyn) { } yystack.s_mark ­= yym; yystate = *yystack.s_mark; yystack.l_mark ­= yym; yym = yylhs[yyn]; if (yystate == 0 && yym == 0) { #if YYDEBUG if (yydebug) printf("%sdebug: after reduction, shifting from state 0 to\ state %d\n", YYPREFIX, YYFINAL); #endif yystate = YYFINAL; *++yystack.s_mark = YYFINAL; *++yystack.l_mark = yyval; if (yychar < 0) { if ((yychar = YYLEX) < 0) yychar = 0; #if YYDEBUG if (yydebug) { yys = 0; if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; if (!yys) yys = "illegal­symbol"; printf("%sdebug: state %d, reading %d (%s)\n", YYPREFIX, YYFINAL, yychar, yys); } #endif } if (yychar == 0) goto yyaccept; goto yyloop; } if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && yyn <= YYTABLESIZE && yycheck[yyn] == yystate) yystate = yytable[yyn]; else yystate = yydgoto[yym]; #if YYDEBUG if (yydebug) printf("%sdebug: after reduction, shifting from state %d \ to state %d\n", YYPREFIX, *yystack.s_mark, yystate); #endif if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack)) { goto yyoverflow; } *++yystack.s_mark = (short) yystate; *++yystack.l_mark = yyval; goto yyloop; yyoverflow: yyerror("yacc stack overflow"); yyabort: yyfreestack(&yystack); return (1); yyaccept: yyfreestack(&yystack); return (0); }
Exemple 2 : une grammaire engendrant des conflits
%%
S : 'a' S 'b'
|SS
|
;
%%
0 $accept : S $end
1 S : 'a' S 'b'
2 |SS
3 |
0: shift/reduce conflict (shift 1, reduce 3) on 'a'
state 0
$accept : . S $end (0)
S : . (3)
'a' shift 1
$end reduce 3
S goto 2
1: shift/reduce conflict (shift 1, reduce 3) on 'a'
state 1
S : 'a' . S 'b' (1)
S : . (3)
'a' shift 1
'b' reduce 3
S goto 3
2: shift/reduce conflict (shift 1, reduce 3) on 'a'
state 2
$accept : S . $end (0)
S : S . S (2)
S : . (3)
$end accept
'a' shift 1
$end reduce 3
S goto 4
3: shift/reduce conflict (shift 1, reduce 3) on 'a'
3: shift/reduce conflict (shift 5, reduce 3) on 'b'
state 3
S : 'a' S . 'b' (1)
S : S . S (2)
S : . (3)
'a' shift 1
'b' shift 5
S goto 4
4: reduce/reduce conflict (reduce 2, reduce 3) on $end
4: shift/reduce conflict (shift 1, reduce 2) on 'a'
4: shift/reduce conflict (shift 1, reduce 3) on 'a'
4: reduce/reduce conflict (reduce 2, reduce 3) on 'b'
state 4
S : S . S (2)
S : S S . (2)
S : . (3)
'a' shift 1
$end reduce 2
'b' reduce 2
S goto 4
state 5
S : 'a' S 'b' . (1)
. reduce 1
State
State
State
State
State
0
1
2
3
4
contains
contains
contains
contains
contains
1
1
1
2
2
shift/reduce
shift/reduce
shift/reduce
shift/reduce
shift/reduce
conflict.
conflict.
conflict.
conflicts.
conflicts, 2 reduce/reduce conflicts.
4 terminals, 2 nonterminals
4 grammar rules, 6 states
REMARQUE
Ce langage est LR ! Mias on a des conflits.
Le meme langage, avec une grammaire mieux ecrite ne genere pas de conflit!
%%
S : 'a' S 'b' S
| 'a' S 'b'
| 'a' 'b' S
| 'a' 'b'
;
%%
0 $accept : S $end
1 S : 'a' S 'b' S
2 | 'a' S 'b'
3 | 'a' 'b' S
4 | 'a' 'b'
state 0
$accept : . S $end (0)
'a' shift 1
. error
S goto 2
state 1
S
S
S
S
:
:
:
:
'a'
'a'
'a'
'a'
.
.
.
.
S 'b' S (1)
S 'b' (2)
'b' S (3)
'b' (4)
'a' shift 1
'b' shift 3
. error
S goto 4
state 2
$accept : S . $end (0)
$end accept
state 3
S : 'a' 'b' . S (3)
S : 'a' 'b' . (4)
'a' shift 1
$end reduce 4
'b' reduce 4
S goto 5
state 4
S : 'a' S . 'b' S (1)
S : 'a' S . 'b' (2)
'b' shift 6
. error
state 5
S : 'a' 'b' S . (3)
. reduce 3
state 6
S : 'a' S 'b' . S (1)
S : 'a' S 'b' . (2)
'a' shift 1
$end reduce 2
'b' reduce 2
S goto 7
state 7
S : 'a' S 'b' S . (1)
. reduce 1
4 terminals, 2 nonterminals
5 grammar rules, 8 states
Annexe 3 : Sorties YACC pour la feuille d'exercices 2:
l'analyseur LALR
1. Grammaire G1 des expressions arithmétiques (voir annexe 2)
2. Grammaire régulière engendrant le langage (aa + bb) +
Grammaire
1 S: 'a' A
2 | 'b' B
3 A: 'a' S
4 | 'a'
5 B: 'b' S
6 | 'b'
état 0
0 $accept: . S $end
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
S aller à l'état 3
état 1
1 S: 'a' . A
'a' décalage et aller à l'état 4
A aller à l'état 5
état 2
2 S: 'b' . B
'b' décalage et aller à l'état 6
B aller à l'état 7
état 3
0 $accept: S . $end
$end décalage et aller à l'état 8
état 4
3 A: 'a' . S
4 | 'a' .
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
$défaut réduction par utilisation de la règle 4 (A)
S aller à l'état 9
état 5
1 S: 'a' A .
$défaut réduction par utilisation de la règle 1 (S)
état 6
5 B: 'b' . S
6 | 'b' .
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
$défaut réduction par utilisation de la règle 6 (B)
S aller à l'état 10
état 7
2 S: 'b' B .
$défaut réduction par utilisation de la règle 2 (S)
état 8
0 $accept: S $end .
$défaut accepter
état 9
3 A: 'a' S .
$défaut réduction par utilisation de la règle 3 (A)
état 10
5 B: 'b' S .
$défaut réduction par utilisation de la règle 5 (B)
3. Mots bien parenthésés sur {a,b}
État 0 conflits: 1 décalage/réduction
État 1 conflits: 1 décalage/réduction
État 2 conflits: 2 décalage/réduction
État 3 conflits: 2 décalage/réduction
État 5 conflits: 1 décalage/réduction, 3 réduction/réduction
Grammaire
0 $accept: S $end
1 S: 'a' S 'b'
2 |SS
3 | /* vide */
état 0
0 $accept: . S $end
'a' décalage et aller à l'état 1
'a'
[réduction par utilisation de la règle 3 (S)]
$défaut réduction par utilisation de la règle 3 (S)
S aller à l'état 2
état 1
1 S: 'a' . S 'b'
'a' décalage et aller à l'état 1
'a'
[réduction par utilisation de la règle 3 (S)]
$défaut réduction par utilisation de la règle 3 (S)
S aller à l'état 3
état 2
0 $accept: S . $end
2 S: S . S
$end décalage et aller à l'état 4
'a' décalage et aller à l'état 1
$end [réduction par utilisation de la règle 3 (S)]
'a' [réduction par utilisation de la règle 3 (S)]
S aller à l'état 5
état 3
1 S: 'a' S . 'b'
2 |S.S
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 6
'a' [réduction par utilisation de la règle 3 (S)]
'b' [réduction par utilisation de la règle 3 (S)]
S aller à l'état 5
état 4
0 $accept: S $end .
$défaut accepter
état 5
2 S: S . S
2 |SS.
'a' décalage et aller à l'état 1
$end
réduction par utilisation de la règle 2 (S)
$end
[réduction par utilisation de la règle 3 (S)]
'a'
[réduction par utilisation de la règle 2 (S)]
'a'
[réduction par utilisation de la règle 3 (S)]
'b'
réduction par utilisation de la règle 2 (S)
'b'
[réduction par utilisation de la règle 3 (S)]
$défaut réduction par utilisation de la règle 2 (S)
S aller à l'état 5
état 6
1 S: 'a' S 'b' .
$défaut réduction par utilisation de la règle 1 (S)
4. Langage 'EQUAL' (autant de 'a' que de 'b')
État 5 conflits: 2 décalage/réduction
État 7 conflits: 2 décalage/réduction
Grammaire
0 $accept: S $end
1 S: 'a' B
2 | 'b' A
3 A: 'a'
4 | 'a' S
5 | 'b' A A
6 B: 'b'
7 | 'b' S
8 | 'a' B B
état 0
0 $accept: . S $end
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
S aller à l'état 3
état 1
1 S: 'a' . B
'a' décalage et aller à l'état 4
'b' décalage et aller à l'état 5
B aller à l'état 6
état 2
2 S: 'b' . A
'a' décalage et aller à l'état 7
'b' décalage et aller à l'état 8
A aller à l'état 9
état 3
0 $accept: S . $end
$end décalage et aller à l'état 10
état 4
8 B: 'a' . B B
'a' décalage et aller à l'état 4
'b' décalage et aller à l'état 5
B aller à l'état 11
état 5
6 B: 'b' .
7 | 'b' . S
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
'a'
[réduction par utilisation de la règle 6 (B)]
'b'
[réduction par utilisation de la règle 6 (B)]
$défaut réduction par utilisation de la règle 6 (B)
S aller à l'état 12
état 6
1 S: 'a' B .
$défaut réduction par utilisation de la règle 1 (S)
état 7
3 A: 'a' .
4 | 'a' . S
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
'a'
[réduction par utilisation de la règle 3 (A)]
'b'
[réduction par utilisation de la règle 3 (A)]
$défaut réduction par utilisation de la règle 3 (A)
S aller à l'état 13
état 8
5 A: 'b' . A A
'a' décalage et aller à l'état 7
'b' décalage et aller à l'état 8
A aller à l'état 14
état 9
2 S: 'b' A .
$défaut réduction par utilisation de la règle 2 (S)
état 10
0 $accept: S $end .
$défaut accepter
état 11
8 B: 'a' B . B
'a' décalage et aller à l'état 4
'b' décalage et aller à l'état 5
B aller à l'état 15
état 12
7 B: 'b' S .
$défaut réduction par utilisation de la règle 7 (B)
état 13
4 A: 'a' S .
$défaut réduction par utilisation de la règle 4 (A)
état 14
5 A: 'b' A . A
'a' décalage et aller à l'état 7
'b' décalage et aller à l'état 8
A aller à l'état 16
état 15
8 B: 'a' B B .
$défaut réduction par utilisation de la règle 8 (B)
état 16
5 A: 'b' A A .
$défaut réduction par utilisation de la règle 5 (A)
5. Grammaire de anbn
Grammaire
1 S: 'a' S 'b'
2 | 'a' 'b'
état 0
0 $accept: . S $end
'a' décalage et aller à l'état 1
S aller à l'état 2
état 1
1 S: 'a' . S 'b'
2 | 'a' . 'b'
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 3
S aller à l'état 4
état 2
0 $accept: S . $end
$end décalage et aller à l'état 5
état 3
2 S: 'a' 'b' .
$défaut réduction par utilisation de la règle 2 (S)
état 4
1 S: 'a' S . 'b'
'b' décalage et aller à l'état 6
état 5
0 $accept: S $end .
$défaut accepter
état 6
1 S: 'a' S 'b' .
$défaut réduction par utilisation de la règle 1 (S)
6. Trailing Count
État 1 conflits: 1 décalage/réduction
État 2 conflits: 1 décalage/réduction
Grammaire
0 $accept: S $end
1 S: 'a' S 'a'
2 | 'b' S 'a'
3 | /* vide */
état 0
0 $accept: . S $end
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
$défaut réduction par utilisation de la règle 3 (S)
S aller à l'état 3
état 1
1 S: 'a' . S 'a'
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
'a' [réduction par utilisation de la règle 3 (S)]
S aller à l'état 4
état 2
2 S: 'b' . S 'a'
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
'a' [réduction par utilisation de la règle 3 (S)]
S aller à l'état 5
état 3
0 $accept: S . $end
$end décalage et aller à l'état 6
état 4
1 S: 'a' S . 'a'
'a' décalage et aller à l'état 7
état 5
2 S: 'b' S . 'a'
'a' décalage et aller à l'état 8
état 6
0 $accept: S $end .
$défaut accepter
état 7
1 S: 'a' S 'a' .
$défaut réduction par utilisation de la règle 1 (S)
état 8
2 S: 'b' S 'a' .
$défaut réduction par utilisation de la règle 2 (S)
7. Even-Even (un nombre pair de 'a' et un nombre pair de 'b') version régulière
Grammaire
1 S: 'a' 'a' S
2 | 'b' 'b' S
3 | 'a' 'b' X
4 | 'b' 'a' X
5 | /* vide */
6 X: 'a' 'a' X
7 | 'b' 'b' X
8 | 'a' 'b' S
9 | 'b' 'a' S
état 0
0 $accept: . S $end
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
$défaut réduction par utilisation de la règle 5 (S)
S aller à l'état 3
état 1
1 S: 'a' . 'a' S
3 | 'a' . 'b' X
'a' décalage et aller à l'état 4
'b' décalage et aller à l'état 5
état 2
2 S: 'b' . 'b' S
4 | 'b' . 'a'
'a' décalage et aller à l'état 6
'b' décalage et aller à l'état 7
état 3
0 $accept: S . $end
$end décalage et aller à l'état 8
état 4
1 S: 'a' 'a' . S
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
$défaut réduction par utilisation de la règle 5 (S)
S aller à l'état 9
état 5
3 S: 'a' 'b' . X
'a' décalage et aller à l'état 10
'b' décalage et aller à l'état 11
X aller à l'état 12
état 6
4 S: 'b' 'a' . X
'a' décalage et aller à l'état 10
'b' décalage et aller à l'état 11
X aller à l'état 13
état 7
2 S: 'b' 'b' . S
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
$défaut réduction par utilisation de la règle 5 (S)
S aller à l'état 14
état 8
0 $accept: S $end .
$défaut accepter
état 9
1 S: 'a' 'a' S .
$défaut réduction par utilisation de la règle 1 (S)
état 10
6 X: 'a' . 'a' X
8 | 'a' . 'b' S
'a' décalage et aller à l'état 15
'b' décalage et aller à l'état 16
état 11
7 X: 'b' . 'b' X
9 | 'b' . 'a' S
'a' décalage et aller à l'état 17
'b' décalage et aller à l'état 18
état 12
3 S: 'a' 'b' X .
$défaut réduction par utilisation de la règle 3 (S)
état 13
4 S: 'b' 'a' X .
$défaut réduction par utilisation de la règle 4 (S)
état 14
2 S: 'b' 'b' S .
$défaut réduction par utilisation de la règle 2 (S)
état 15
6 X: 'a' 'a' . X
'a' décalage et aller à l'état 10
'b' décalage et aller à l'état 11
X aller à l'état 19
état 16
8 X: 'a' 'b' . S
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
$défaut réduction par utilisation de la règle 5 (S)
S aller à l'état 20
état 17
9 X: 'b' 'a' . S
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
$défaut réduction par utilisation de la règle 5 (S)
S aller à l'état 21
état 18
7 X: 'b' 'b' . X
'a' décalage et aller à l'état 10
'b' décalage et aller à l'état 11
X aller à l'état 22
état 19
6 X: 'a' 'a' X .
$défaut réduction par utilisation de la règle 6 (X)
état 20
8 X: 'a' 'b' S .
$défaut réduction par utilisation de la règle 8 (X)
état 21
9 X: 'b' 'a' S .
$défaut réduction par utilisation de la règle 9 (X)
état 22
7 X: 'b' 'b' X .
$défaut réduction par utilisation de la règle 7 (X)
8. Even-Even (un nombre pair de 'a' et un nombre pair de 'b') version non régulière
État 0 conflits: 2 décalage/réduction
État 3 conflits: 3 décalage/réduction
État 4 conflits: 2 décalage/réduction
État 5 conflits: 2 décalage/réduction
État 11 conflits: 2 décalage/réduction, 3 réduction/réduction
État 12 conflits: 2 décalage/réduction, 3 réduction/réduction
État 13 conflits: 2 décalage/réduction, 3 réduction/réduction
État 14 conflits: 2 décalage/réduction
État 15 conflits: 2 décalage/réduction, 2 réduction/réduction
Grammaire
1 S: S S
2 |BS
3 |SB
4 | /* vide */
5 |USU
6 B: 'a' 'a'
7 | 'b' 'b'
8 U: 'a' 'b'
9 | 'b' 'a'
état 0
0 $accept: . S $end
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
'a'
[réduction par utilisation de la règle 4 (S)]
'b'
[réduction par utilisation de la règle 4 (S)]
$défaut réduction par utilisation de la règle 4 (S)
S aller à l'état 3
B aller à l'état 4
U aller à l'état 5
état 1
6 B: 'a' . 'a'
8 U: 'a' . 'b'
'a' décalage et aller à l'état 6
'b' décalage et aller à l'état 7
état 2
7 B: 'b' . 'b'
9 U: 'b' . 'a'
'a' décalage et aller à l'état 8
'b' décalage et aller à l'état 9
état 3
0 $accept: S . $end
1 S: S . S
3 |S.B
$end décalage et aller à l'état 10
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
$end [réduction par utilisation de la règle 4 (S)]
'a' [réduction par utilisation de la règle 4 (S)]
'b' [réduction par utilisation de la règle 4 (S)]
S aller à l'état 11
B aller à l'état 12
U aller à l'état 5
état 4
2 S: B . S
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
'a'
[réduction par utilisation de la règle 4 (S)]
'b'
[réduction par utilisation de la règle 4 (S)]
$défaut réduction par utilisation de la règle 4 (S)
S aller à l'état 13
B aller à l'état 4
U aller à l'état 5
état 5
5 S: U . S U
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
'a' [réduction par utilisation de la règle 4 (S)]
'b' [réduction par utilisation de la règle 4 (S)]
S aller à l'état 14
B aller à l'état 4
U aller à l'état 5
état 6
6 B: 'a' 'a' .
$défaut réduction par utilisation de la règle 6 (B)
état 7
8 U: 'a' 'b' .
$défaut réduction par utilisation de la règle 8 (U)
état 8
9 U: 'b' 'a' .
$défaut réduction par utilisation de la règle 9 (U)
état 9
7 B: 'b' 'b' .
$défaut réduction par utilisation de la règle 7 (B)
état 10
0 $accept: S $end .
$défaut accepter
état 11
1 S: S . S
1 |SS.
3 |S.B
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
$end
réduction par utilisation de la règle 1 (S)
$end
[réduction par utilisation de la règle 4 (S)]
'a'
[réduction par utilisation de la règle 1 (S)]
'a'
[réduction par utilisation de la règle 4 (S)]
'b'
[réduction par utilisation de la règle 1 (S)]
'b'
[réduction par utilisation de la règle 4 (S)]
$défaut réduction par utilisation de la règle 1 (S)
S aller à l'état 11
B aller à l'état 12
U aller à l'état 5
état 12
2 S: B . S
3 |SB.
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
$end
réduction par utilisation de la règle 3 (S)
$end
[réduction par utilisation de la règle 4 (S)]
'a'
[réduction par utilisation de la règle 3 (S)]
'a'
[réduction par utilisation de la règle 4 (S)]
'b'
[réduction par utilisation de la règle 3 (S)]
'b'
[réduction par utilisation de la règle 4 (S)]
$défaut réduction par utilisation de la règle 3 (S)
S aller à l'état 13
B aller à l'état 4
U aller à l'état 5
état 13
1 S: S . S
2 |BS.
3 |S.B
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
$end
réduction par utilisation de la règle 2 (S)
$end
[réduction par utilisation de la règle 4 (S)]
'a'
[réduction par utilisation de la règle 2 (S)]
'a'
[réduction par utilisation de la règle 4 (S)]
'b'
[réduction par utilisation de la règle 2 (S)]
'b'
[réduction par utilisation de la règle 4 (S)]
$défaut réduction par utilisation de la règle 2 (S)
S aller à l'état 11
B aller à l'état 12
U aller à l'état 5
état 14
1 S: S . S
3 |S.B
5 |US.U
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
'a' [réduction par utilisation de la règle 4 (S)]
'b' [réduction par utilisation de la règle 4 (S)]
S aller à l'état 11
B aller à l'état 12
U aller à l'état 15
état 15
5 S: U . S U
5 |USU.
'a' décalage et aller à l'état 1
'b' décalage et aller à l'état 2
'a'
[réduction par utilisation de la règle 4 (S)]
'a'
[réduction par utilisation de la règle 5 (S)]
'b'
[réduction par utilisation de la règle 4 (S)]
'b'
[réduction par utilisation de la règle 5 (S)]
Annexe 4 : Transparents des TP de LEX et de YACC
Master 1 informatique : TP de compilation
Analyse lexico-syntaxique avec LEX et YACC
1. Lex : générateur d'analyseur lexical (+variante Flex)
2. Yacc : générateur d'analyseur syntaxique
3. Lex avec Yacc
ENT : cours en ligne (Clarotice)
 Analyse lexicale et syntaxique avec Lex et Yacc
• Formation Lex & Yacc
• Exercices de TP
• (Solutions)
d examen)
• (Sujet d'examen)
Lex & Yacc
© A. Sigayret 2011-02-18
1
Lex
•
Utilitaire Unix (Linux: Flex)
•
Flux d'entrée  suite de motifs
1. Définir les motifs
 méta-langage (E.R.)
2. Préciser les actions associées
 code C/C++ (E.R. aug.)
3. Générer le code source
 en C/C++
4. Compiler
 librairie Lex
fichier.lex
lex fichier.lex
lex.yy.c
cc lex
lex.yy.c
yy c -ll
ll
a.out
utiliser –lfl avec Flex !
Lex & Yacc
2
Le fichier-lex
4 parties (3 facultatives):
1. Code utilisateur préalable
{%
int v=0;
%}}
2. Définitions opératoires
- définitions opératoires
- expressions prédéfinies
%s config
voyelle [aeiou]
3. Règles de production
seul sur ligne !
%%
{voyelle} tab
%%
%% obligatoire avec Flex
4. Code utilisateur final
v++
main()
{yylex(); printf("voyelles:%d",v);}
attention! espaces et tabulations
Lex & Yacc
3
Les E.R. vues par Lex
Méta-caractères:
{ } 1. utilisation d'expressions
2 nombre
2.
b d'
d'occurrences
% initiateur (p. 3 et 4)
< > configurations (p. 3)
" " délimiteur de texte brut
( ) délimiteur de motif
\
\n,, \s,, \t,, …
[ ] délimiteur ensembliste
+ * ?
# occurrences
/
suivi de
|
ou
^
début de ligne
$
fin de ligne
.
tout caractère sauf \n
Lex & Yacc
$
^
-
négation (après [)
intervalle (entre 2 caractères)
 erlex.htm
4
LEX : ordre des motifs ?
%%
a
aa
aaa
{simple++;}
{d bl
{double++;}
}
{triple++;}
%%
aaa
aa
a
{triple++;}
{double++;}
{simple++;}
%%
aaa
aa
a
{triple++; REJECT;}
{double++; REJECT;}
{simple++;}
Lex & Yacc
aaaaaaaaaaa
 triple=0, double=0, simple=11
aaaaaaaaaaa
 triple=3, double=1, simple=0
aaaaaaaaaaa
 ?! triple=9, double=10, simple=11
N.B. Les solutions de TD ont été compilées avec Lex ...
5
FLEX : longueurs des motifs
%%
a
aa
aaa
%%
{simple++;}
{d bl
{double++;}
}
{triple++;}
%%
aaa
aa
a
%%
{triple++;}
{double++;}
{simple++;}
%%
aaa
aa
a
%%
{triple++; REJECT;}
{double++; REJECT;}
{simple++;}
Lex & Yacc
aaaaaaaaaaa
 triple=3, double=1, simple=0
aaaaaaaaaaa
 triple=3, double=1, simple=0
aaaaaaaaaaa
 ?! triple=9, double=10, simple=11
... Adaptez les solutions de TD à Flex !
6
Variables et fonctions lex
yytext
yyleng
yylval
yy
tableau contenant le motif reconnu
taille de yytext
"last value" de type
yp YYTYPE ((cf Yacc))
ECHO
BEGIN(conf)
REJECT
yymore()
affiche yytext
place l'analyseur dans la configuration indiquée
replace le motif reconnu dans le flot d'entrée
conserve dans yytext le motif
(le motif suivant sera rajouté en suffixe - au lieu d'écraser yytext)
yyless(n)
comme yymore() mais
supprime d'abord les n premiers caractères du motif
Lex & Yacc
7
Configurations d'analyse
%%
<INITIAL,condition1>^C$
INITIAL,condition1 C$
<INITIAL,condition2>^V$
<condition1>voyelle
<condition2>consonne
<condition1,condition2>^I$
{BEGIN (condition2);}
{BEGIN (condition1);}
{printf("-");}
{printf("+");}
{printf(
+ );}
{BEGIN(INITIAL);}
Au début de chaque règle de production
Valeur par défaut: INITIAL
Lex & Yacc
8
Compilation
Sous Unix ((Lex)) :
Sous Linux ((Flex)) :
Librairie Lex : –ll
librairie Flex : -lfl
code C ↔ compilation C
code C++ ↔ compilation C++
Lex & Yacc
9
Exécution
Origine
g
et destination du flux d'analyse:
y
par défaut  stdin (clavier) et  stdout (écran)
+ Redirigeable (Unix: <
<, >)
+ Reprogrammable (Lex: yyin)
Lex & Yacc
10
Yacc
•
Utilitaire Unix (GNU: Bison)
•
analyse syntaxique (grammaire algébrique)
1. Définir les règles de production
 méta-langage
fichier.yacc
2. Préciser les actions associées
 code C/C++ (gram. aug.)
yacc fichier.yacc
3. Générer le code source
 en C/C++
y.tab.c
cc y
y.tab.c
tab c -ly
ly
4. Compiler
 librairie Yacc
a.out
Lex & Yacc
11
Le fichier Yacc
4 parties (3 facultatives):
1 C
1.
Code
d utilisateur
tili t
préalable
é l bl
{%
%}
2. Définitions opératoires
- définitions opératoires
- définitions de lexèmes
- table de précédence
3. Règles de production
4. Code utilisateur final
%token plus
[aeiou] return voyelle
%left plus
%%
S : voyelle
ll S voyelle
ll
|
;
%%
int yylex() {…}
attention! espaces et tabulations
Lex & Yacc
12
Les règles de production
S:LS
|L
|
;
L : consonne
| voyelle
;
$$=$1+$2;
$$
$ $ ;
$$=$1;
$$=0;
$$=0;
$$=1;
Grammaire correspondante: SLS|L|ε, Lc|v
Convention: NON-TERMINAL / terminal (AT&T: convention inverse)
Variables $ pour transmettre des valeurs dans l'arbre d'analyse
Lex & Yacc
13
S : nombre plus S
| nombre mult S
| nombre
;
$$=$1+$3;
$$=$1*$3;
$$=yylval
yylval: valeur attribuée au token nombre (par défaut type int)
type de yylval redéfinissable dans le code préalable (cf ymf.htm)
symbole
b l d
de dé
départ:
t lle premier
i ttrouvé
é
ou choisi dans la partie 2: %start symbole
Table de précédence (des opérateurs)
%left
%right
%nonassoc
 CM de compilation
p
et de théorie des langages
g g
Lex & Yacc
14
Variables et fonctions prédéfinies
error : token qui récupère une impasse dans la table d’analyse
YYABORT : équivalent à return 1
YYACCEPT : équivalent
é i l t à return
t
0
YYERROR : équivalent à return 1
main() {yyparse();}
code prédéfini
prédéfini, ajouté dans la partie 4 par –ly
ly
return met fin à l'analyseur yyparse
main(){while
i (){ hil yyparse()=0}
() 0}
code à placer dans la partie 4
pour relancer l'analyseur après un return nul
Lex & Yacc
15
Interfacer Lex et Yacc
Pour utiliser Yacc sans Lex, on peut:
1. remplacer les tokens par des caractères
(ppexp:
p 'a', 'e', 'i', 'o', 'u' p
pour voyelles
y
)
2. définir la fonction yylex
(pexp: yylex(){char c=getchar(); return c;})
Sinon il faut "interfacer" les deux applications…
Lex & Yacc
16
…avec des tokens
fichier-lex :
fichier-yacc
y
:
%{
#include yy.tab.h
tab h
%}
%%
[aeiou]+
{return v;}
[b-df-hj-np-tv-z] {return c;}
.|\n
{return autre;}
...
...
%token v
%token c
%token autre
...
%%
S:Sv
$$=$1+1;
|Sc
$$ $1
$$=$1;
| S autre $$=$1;
;
...
Lex & Yacc
17
transmission des valeurs
fichier-lex :
fichier-yacc
y
:
%{
extern int yylval;
…
%}
…
[0-9]+ {yylval=atoi(yytext); return n;}
[+] {return p;}
...
...
%token n
...
%%
S:Spn
|n
;
...
{$$=$1+$3;}
{$$=yylval;}
typage des valeurs (#define YYSTYPE)  inter_ly.htm
Lex & Yacc
18
Interfacer et compiler
Dépendances:
• yylex() défini avant yyparse()
• yyparse() défini avant main()
• -ly -ll (main de Yacc prioritaire)
• tokens définis dans fichier-yacc et utilisés dans fichier-lex.
Procédé de base:
• Construire fichier-lex et fichier-yacc
• yacc -d fichier.yacc (créer y.tab.h)
• Ajouter #define y.tab.h dans fichier-lex
• lex
l fifichier.lex
hi l
• Compiler dans le bon ordre : gcc lex.yy.c y.tab.c -ly -ll
Lex & Yacc
19

Documents pareils