IFT313
Introduction aux langages formels
Froduald Kabanza
Département d’informatique Université de Sherbrooke
planiart.usherbrooke.ca/kabanza/cours/ift313
Grammaires
IFT313 © Froduald Kabanza
2
Sujets
• Rappel : langages, expressions régulières, automates finis.
• C’est quoi une grammaire ?
• C’est quoi le langage généré par une grammaire ?
• C’est quoi une dérivation ?
• C’est quoi un arbre d’analyse ?
• C’est quoi une grammaire ambiguë ?
• Quelles sont les différentes types de grammaires
• C’est quoi une grammaire hors-contexte ?
IFT313 © Froduald Kabanza
3
Objectifs
• Savoir reconnaître et expliquer les différentes types de grammaires.
• Pouvoir donner une grammaire qui génère un langage donné.
• Pouvoir décrire le langage généré par une grammaire donnée.
• Connaître le rapport entre les grammaires et les automates finis.
• Pouvoir expliquer le concept d’arbre d’analyse.
• Pouvoir expliquer ce qu’une grammaire ambiguë.
IFT313 © Froduald Kabanza
4
Références
[1] Sudkamp, T. A.. Languages and Machines. Third Edition Edition.
Addison-Wesley, 2005.
– Sections 3.1 à 3.6, 4.5
[2] Appel, A. and Palsberg. J. Modern Compiler Implementation in Java.
Second Edition. Cambridge, 2004.
– Section 3.1
[3] Wolper, P. Introduction à la calculabilité, 3è édition. Dunod, 2006 – Sections 3.1 à 3.3
[4] Aho, A., Lam, M., Sethi R., Ullman J. Compilers: Principles, Techniques, and Tools, 2nd Edition. Addison Wesley, 2007.
– Sections 4.1 à 4.2
IFT313 © Froduald Kabanza
5
Rappel
- Nous avons vu qu’un langage est un ensemble de mots où un mot est une chaîne de symboles (caractères) d’un alphabet fini.
- Pour les langages réguliers (par exemple, le langage de tokens d’un lan- gage de programmation),
- plutôt que d’énumérer les mots explicitement,
- on spécifie une expression régulière décrivant le langage - ou on donne un automate fini acceptant le langage.
- Les expressions régulières décrivent un langage de manière déclarative en indiquant des patterns qui sont matchés par des mots du langage.
- Les automates finis décrivent le langage de manière analytique par un modèle simple d’un programme reconnaissant les mots du langages.
IFT313 © Froduald Kabanza
6
Rappel (suite)
- Ces deux formes de description d’un langage sont complémentaire et il est utile d’avoir les deux.
- Le style déclaratif des expressions régulières est utile lorsqu’on veut décrire le langage plutôt que de le reconnaître.
C’est le cas lorsqu’on définit une spécification JFlex.
- Le style analytique des automates est utile lorsqu’on veut reconnaître le langage.
Par exemple, si on veut implémenter un analyseur lexical directement, ou programmer un générateur d’analyseurs lexicaux.
IFT313 © Froduald Kabanza
7
Rappel (suite)
- Il y a une autre approche pour décrire les langages : approche générative.
- Avec une approche générative on décrit comment le langage est généré en donnant une grammaire.
IFT313 © Froduald Kabanza
9
Rappel (suite)
- On peut décrire le langage des expressions arithmétiques par les règles syn- taxiques suivantes:
1 Une expression est un nombre, ou 2 l’addition de deux expressions, ou
3 la multiplication de deux expressions, ou 4 une expression entre parenthèses.
- Pour garder les choses simples, nous considérons uniquement des expres- sions avec les opérations d’addition et de multiplication.
IFT313 © Froduald Kabanza
10
Rappel (suite)
- Les programmeurs vont spécifier de telles règles syntaxique dans une forme d’écri- ture dite de Backus-Naur :
Exp ® num Exp ® ( Exp ) Exp ® Exp + Exp Exp ® Exp * Exp
- Ces règles décrivent le langage des expressions arithmétiques, c-à-d., le langage dont l’ensemble de mots sont les chaînes formés uniquement des symboles ter- minaux num, (, ), + et * , et respectant la syntaxe indiquée par les règles.
- Une règle de la grammaire est aussi appelé une règle de production ou une règle de réécriture.
IFT313 © Froduald Kabanza
12
En résumé
- Nous allons utiliser une grammaire pour décrire un langage de pro- grammation :
Elle permet de tenir compte de la syntaxe mieux que les expres- sions régulières.
Nous pouvons décrire plus de langages en utilisant les grammaires qu’avec les expressions régulières.
Les expressions régulières sont juste bon pour décrire un langage de tokens.
- Toutefois, pour implémenter un analyseur syntaxique (parser) pour le langage, une fois de plus nous utiliserons un automate.
Mais pas un automate fini.
Nous utiliserons un type d’automate plus puissant, appelé “au- tomate à pile”, ayant un nombre fini d’états et une pile de taille arbitraire.
IFT313 © Froduald Kabanza
13
Grammaires
- Le principe de base derrière les grammaires est de spécifier des règles de réécriture des mots d’un langage.
- Les règles de réécriture indiquent comment des séquences de symboles peuvent être remplacée par d’autres séquences de symboles pour obtenir des mots du langage.
- Les mots du langage sont ceux pouvant être obtenus en appliquant les règles de réécriture, à partir d’un symbole spécial appelé le symbole de départ.
IFT313 © Froduald Kabanza
14
Définition formelle
- Une grammaire G est un quadruple G=(V,A,R,S) tel que :
+ V est un ensemble fini de symboles non-terminaux, appelé aussi variables.
+ A est un ensemble fini de symboles terminaux, appelé aussi l’alphabet.
+ R dans ((V U A)+ × (V U A)*) est un ensemble fini de règles de réécriture, ap- pelés aussi règle de productions
+ S dans V est le symbole de départ.
- Les ensembles de symboles V et A doivent être disjoints.
- Seuls les symboles terminaux formes les mots du langage.
- Les symboles non-terminaux sont là juste pour aider à générer le langage.
- La génération du langage commence toujours par le symbole de départ S.
IFT313 © Froduald Kabanza
15
Exemple
- Nous avons déjà vu la grammaire du langage des expressions arithmétiques avec les opérations + et *.
- La voici cette fois-ci de manière précise : G = (V, A, R, Exp), tel que :
V = {Exp}
A = {(, ), +, *, num}
R = {
Exp ® num Exp ® ( Exp ) Exp ® Exp + Exp Exp ® Exp * Exp }
IFT313 © Froduald Kabanza
16
Exemple (suite)
- La chaine (36+4)*50
ou plus exactement (num+num)*num,
fait partie du langage généré par la grammaire précédente.
- En effet, elle est générée comme suit :
Exp
Symbole de départ Productions
1. Exp → num 2. Exp → ( Exp ) 3. Exp → Exp + Exp 4. Exp → Exp * Exp
Exp * Exp Exp * num
(Exp + Exp) * num (Exp + num) * num (num + num) * num (Exp) * num
IFT313 © Froduald Kabanza
17
Un autre exemple
- En général, on peut avoir plusieurs grammaires générant le même langage.
- Par exemple, la grammaire suivante génère le même langage que la précé- dente :
- G = (V, A, R, Exp), tel que : V = {Exp, Op}
A = {(, ), +, *, num}
R = {
Exp ® Exp Op Exp Exp ® ( Exp )
Exp ® num Op ® + Op ® * }
IFT313 © Froduald Kabanza
18
Conventions
- S dénote souvent le symbole de départ dans des exemples artificiels.
- Les lettres en majuscule sont des non-terminaux.
- Les lettres en minuscule sont des terminaux.
- Les lettres grecs en minuscules tels que a, b,g,d et s representent des
mots (chaînes) de symboles de grammaires (possiblement avec des
terminaux et des non-terminaux).
IFT313 © Froduald Kabanza
19
Conventions
- Lorsque nous avons plusieurs productions avec la même partie de gauche, comme par exemple:
X ® a X ® b
X ® s
On les écrit en utilisant une seule production-multiple comme suit:
X ® a | b | s
IFT313 © Froduald Kabanza
20
Exemple
- Les productions
Exp ® Exp Op Exp Exp ® ( Exp )
Exp ® num Op ® + Op ® * peuvent aussi s’écrire
Exp ® Exp Op Exp | (Exp) | num
Op ® + | *
IFT313 © Froduald Kabanza
21
Dérivation
- Le processus de générer une chaîne de symboles d’une grammaire en appliquant une production est appelé une dérivation de la chaîne.
- Si une seule production est appliqué, une seule fois, pour produire une chaîne, on parle de dérivation en une étape.
- Si plusieurs productions sont utilisées ou une production plusieurs fois, on parle de dérivation en plusieurs étapes.
- La dérivation en zéro étapes donne la chaîne elle-même.
IFT313 © Froduald Kabanza
22
Dérivation en une étape
- Soit G = (V,A,R,S) et u une chaîne dans (VUA)+ et v dans (VUA)*.
- La grammaire G dérive v de u en une étape (noté u Þ v, ou u Þ v lorsque G est sous-entendu) si et seulement si il y a des chaînes x et y dans V* telles que:
u = xu’y
v=xv’y
u’ ® v’ est une production dans R
G
IFT313 © Froduald Kabanza
23
Exemple
- Soit la grammaire G = (V, A, R, Exp) telle que:
V = {Exp}
A = {(, ), +, *, num}
R = {
Exp ® num Exp ® (Exp)
Exp ® Exp + Exp Exp ® Exp * Exp }
- En une étape, on peut seulement dériver des chaînes qui sont des parties droites des règles de production, à partir du symbole de départ Exp.
num Exp Þ num ( Exp ) Exp Þ (Exp) Exp + Exp Exp Þ Exp + Exp Exp * Exp Exp Þ Exp * Exp
IFT313 © Froduald Kabanza
24
Dérivation en plusieurs étapes
- Soit G = (V,A,R,S) et u dans (VUA)+ et v dans (VUA)*.
- La grammaire G dérive v de u en zéro ou plusieurs étapes (noté u Þ v ou u Þ v si G est sous-entendu) si et seulement si il existe des chaînes v0, …,vk dans (VU)* pour k³0, telle que :
u = v0
v=vk
vi Þ vi+1 for 0£ i £ k.
G*
*
IFT313 © Froduald Kabanza
25
Exemple
- Soit encore une fois la grammaire G = (V, A, R, Exp), telle que:
V = {Exp}
A = {(, ), +, *, num}
R = {
Exp ® num Exp ® ( Exp ) Exp ® Exp + Exp Exp ® Exp * Exp }
- En plusieurs étapes on peut dériver la chaîne (num+num)*num à partir du symbole de départ: Exp Þ (num+num)*num
- Dépendamment du texte scanné pour les tokens num, cette chaîne pourrait représen- ter l’expression (234 + 10)*81
*
IFT313 © Froduald Kabanza
26
Exemple (suite)
- Dérivation de la chaîne (num+num)*num.
Exp
Symbole de départ Productions
1. Exp → num 2. Exp → ( Exp ) 3. Exp → Exp + Exp 4. Exp → Exp * Exp
Exp * Exp Exp * num
(Exp + Exp) * num (Exp + num) * num (num + num) * num (Exp) * num
Þ
Þ Þ
Þ
Þ Þ
IFT313 © Froduald Kabanza
27
Langage généré par une grammaire
- Les mots générés par une grammaire G = (V, A, R, S), sont les chaînes v dans A* (c-à-d., composés seulement de terminaux) dérivables à partir du sym- bole de départ
c-à-d., les chaînes v telles que S Þ v
- Le langage généré par une grammaire G = (V, A, R, S), (noté L(G)) est l’en- semble de mots générés par G :
L(G) = {v dans A* | S Þ v }
G*
G*
IFT313 © Froduald Kabanza
28
Exemple 1
- Soit encore une fois la grammaire G = (V, A, R, Exp), telle que:
V = {Exp}
A = {(, ), +, *, num}
R = {
Exp ® num Exp ® ( Exp )
Exp ® Exp + Exp Exp ® Exp * Exp }
- L(G) est l’ensemble dont les mots sont des expressions arithmétiques en no- tation infixée, avec seulement les entiers, l’addition et la multiplication.
IFT313 © Froduald Kabanza
29
Exemple 2
- G = ({S}, {a,b}, R, S) telle que R = {S ® ε, S ® aSb}
- L(G) est l’ensemble de chaînes de la forme a
nb
n, avec n≥0.
IFT313 © Froduald Kabanza
30
Dérivation la plus à gauche (lefttmost)
- Une dérivation la plus à gauche est une dérivation dont chaque étape rem- place le non-terminal le plus à gauche.
- Exemple :
Exp
Symbole de départ Productions
1. Exp → num 2. Exp → ( Exp ) 3. Exp → Exp + Exp 4. Exp → Exp * Exp
Exp * Exp (Exp) * Exp
(num + Exp) * Exp (num + num) * Exp (num + num) * num (Exp + Exp) * Exp
Þ
Þ Þ
Þ Þ
Þ
IFT313 © Froduald Kabanza
31
Dérivation la plus à droite ( rightmost)
- Une dérivation la plus à droite est une dérivation dont chaque étape rem- place le non-terminal le plus à droite.
- Exemple :
Exp
Symbole de départ Productions
1. Exp → num 2. Exp → ( Exp ) 3. Exp → Exp + Exp 4. Exp → Exp * Exp
Exp * Exp Exp * num
(Exp + Exp) * num (Exp + num) * num (num + num) * num (Exp) * num
Þ
Þ Þ
Þ
Þ Þ
IFT313 © Froduald Kabanza
32
Notion de forme sententielle
- Étant donné une grammaire G = (V, A, R, S), une chaine v dans (VUA)* est appelée une forme sentantielle (sentatial form) si et seulement si S Þ v.
En d’autres mots, v est dérivable de la grammaire.
- Si v est une forme sententielle constitué uniquement de terminaux, on dit aussi que c’est une phrase (sentence).
- Si v est dérivé par une dérivation la plus à gauche, on parle de forme sentielle gauche (left sentential form).
- De manière analogue, si v est dérivé par une dérivation la plus à gauche, on parle de forme sententielle droite (right sentential form).
G*
IFT313 © Froduald Kabanza
33
Parsers LL et LR
- Les analyseurs syntaxiques utilisent soit la dérivation la plus à gauche ou la dériva- tion la plus à droite.
- Les parsers qui utilisent la dérivation la plus à gauche sont appelés des parsers LL pour “Left-to-right scan and Leftmost derivation of the input”.
- Les parsers qui utilisent la dérivation la plus à droite sont appelés des parsers LR pour “Left-to-right scan and Rightmost derivation of the input”.
IFT313 © Froduald Kabanza
34
Parsers LL (Top-down)
- Les parsers LL (appelés aussi top-down parsers) valident la syntaxe d’une chaîne de to- kens (le code d’un programme) en cherchant la dérivation de la plus à gauche de la chaine.
- La recherche de la dérivation se fait en partant du symbole de départ (d’où le
« top »), en allant vers la chaîne à dériver, c-à-d., vers le bas (d’où le « down »).
- Par exemple, avec la grammaire précédente et la chaîne num + num * num, un analyseur LL produirait la dérivation:
Exp => Exp * Exp =>Exp + Exp * Exp=> num + Exp * Exp =>num + num * Exp
=> num + num * num
- Les parsers sont définis de tel sorte que si une dérivation ne peut être obtenue, une erreur syn- taxique sera indiquée.
IFT313 © Froduald Kabanza
35
Analyse syntaxique LR (ou Bottom-up)
- Les analyseurs LR ( appelés aussi bottom-up) valident la syntaxe d’une chaîne de tokens (le code d’un programme) en cherchant la dérivation de la plus à droite de la chaine.
- La recherche de la dérivation se fait en partant de la chaîne à dériver (d’où le « bot- tom »), en allant vers le symbole de départ de la grammaire, c-à-d., vers le haut (d’où le « up »).
- Par exemple, avec la grammaire précédente et la chaine num + num * num, on pourrait avoir la dérivation la plus à droute suivante :
Exp => Exp * Exp =>Exp * num => Exp + Exp * num =>Exp + num * num =>num + num * num
- Toutefois, un parseur LR va déterminer cette dérivation en sens inverse, comme suit:
num+num * num <= Exp + num * num <= Exp + Exp * num <= Exp * num <= Exp * Exp <= Exp
IFT313 © Froduald Kabanza
36
Arbres d’analyses
- Un arbre d’analyse est un arbre obtenu à partir d’une dérivation en connec- tant chaque symbole au symbole à partir du quel il est dérivé.
- Exemple:
Exp Symbole de départ
Productions 1. Exp → num 2. Exp → ( Exp ) 3. Exp → Exp + Exp 4. Exp → Exp * Exp
Exp * Exp Exp * num
(Exp + Exp) * num (Exp + num) * num (num + num) * num (Exp) * num
Þ
Þ Þ
Þ
Þ Þ
Exp
Exp * Exp
num
num
num Exp
( )
Exp + Exp
Grammaire Dérivation Arbre d’analyse
IFT313 © Froduald Kabanza
37
Grammaires ambiguës
- Une grammaire est ambiguë si on peut en dériver une chaîne avec deux ar- bres d’analyse différents.
- Exemple : Grammaire:
G = ({Exp}, A, R, Exp), telle que:
A = {(, ), +, *, num}
R = {
Exp ® num Exp ® ( Exp )
Exp ® Exp + Exp Exp ® Exp * Exp }
Chaîne à dériver : num + num * num
Arbre d’analyse 1
Exp
Exp * Exp Exp +
num
Exp num num
Arbre d’analyse 2
Exp
Exp + Exp
num * Exp
num Exp
num
IFT313 © Froduald Kabanza
38
Grammaires ambiguës
- Plus tard nous verrons que les grammaires ambiguës sont problématiques
puisqu’elles donnent naissance à plusieurs interprétations différentes d’une même entrée.
- Nous allons les éviter en :
- Définissant des grammaires non-ambiguës qui acceptent le même lan- gage.
- Utilisant des règles de priorité dans l’application des règles de la gram- maire.
IFT313 © Froduald Kabanza
39
Types de grammaires
- Il existe plusieurs types de grammaires avec un pouvoir d’expressivité différent.
- Les différents types de grammaires résultent de différentes restrictions sur les pro- ductions autorisées.
- En général, une production d’une grammaire est de la forme
a ® b .
- Grammaires de Type 0 :
Pas de restriction sur les productions.
- Grammaires de Type 1 (sensibles au contexte – contexte-sensitive) : Les productions doivent avoir la forme
a -> b
telle que|a| ≤ |b|
C-à-d., la partie droite d’une production doit contenir au moins autant de symboles que la partie gauche, excepté pour la production S ® ε.
IFT313 © Froduald Kabanza
40
Types de grammaires (suite)
- Grammaires de Type 2 (hors-contexte - context-free) :
Les productions sont de la forme A -> b tel que A est un non-terminal.
- Grammaires de Type 3 (régulières - regular) :
Les productions sont de la forme A -> w B, A -> Bw , ou A -> ε tels que A et B sont des non-terminaux et w est une chaîne de terminaux ou la chaîne vide.
- Les grammaires de type 3 sont un sous-ensemble de ceux de type 2, qui sont un sous-ensemble de ceux de type 1, qui sont un sous-ensemble de ceux de type 0.
- Un langage généré par une grammaire de type de 3 est aussi décrit par une expres- sion régulière et accepté par un automate-fini et vice-versa.
IFT313 © Froduald Kabanza
41
Types de grammaires (suite)
- Pour l’analyse syntaxique, nous allons utiliser seulement des grammaires de type 2 (hors-contexte).
- Plus précisément, nous allons étudier des sous-ensembles de grammaires hors-contexte qui permettent une analyse syntaxique déterministe: LL(k) et LR(k) .
- Tous les exemples de grammaires vu jusqu’ici sont des grammaires hors- contexte.
IFT313 © Froduald Kabanza
42