Slides Cours1
Slides Cours1
Slides Cours1
Christine Paulin
Christine.Paulin@universite-paris-saclay.fr
2023–24
1 Motivations
2 Organisation du cours
3 Etapes de l’interprétation
4 Langages formels
modélisation
algorithmique
données
calcul
1 Motivations
2 Organisation du cours
3 Etapes de l’interprétation
Analyse lexicale
Analyse syntaxique
Arbre de syntaxe abstraite
Analyse sémantique et évaluation
4 Langages formels
Vocabulaire
Opérations sur les mots
Opérations sur les langages
Site
https://ecampus.paris-saclay.fr/course/view.php?id=122122
TD/TP
8 séances de TD, 3 séances de TP
dernière séance : TP noté (a priori le 23 avril)
Evaluation
partiel (semaine du 27 février ou du 5 mars) : 30%
TP(s) et tests notés : 10%
examen final : 60%
Une feuille A4 (recto-verso) manuscrite autorisée au partiel et à l’examen
1 Motivations
2 Organisation du cours
3 Etapes de l’interprétation
Analyse lexicale
Analyse syntaxique
Arbre de syntaxe abstraite
Analyse sémantique et évaluation
4 Langages formels
Vocabulaire
Opérations sur les mots
Opérations sur les langages
programme transformations
source
arbre(s)
suite
suite de arbre de de
d’unités résultat
caractères dérivation syntaxe
lexicales
abstraite
Statique Dynamique
def f i b ( n ) :
return f i b a u x (0 , 1 , n )
# une ou p l u s i e u r s i n s t r u c t i o n s
p r i n t ( " quelques v a l e u r s : " )
f o r n i n [ 0 , 1 , 11 , 4 2 ] :
print ( f i b (n ) )
Python :
lexical : https://docs.python.org/fr/3/reference/lexical_analysis.html
expressions : https://docs.python.org/fr/3/reference/expressions.html
Ocaml :
lexical : https://v2.ocaml.org/releases/5.0/htmlman/lex.html
expressions : https://v2.ocaml.org/releases/5.0/htmlman/expr.html
Erreurs détectées
suite de caractères ne correspondant à aucune unité lexicale :
caractère non accepté dans un identifiant,
chaîne de caractère non fermée,
symbole inconnu. . .
Outils
Les unités lexicales sont décrites par des expressions régulières
L’analyse du texte se fait en utilisant des automates finis (associés à des
actions de calcul à chaque étape de reconnaissance)
Unités lexicales :
en nombre fini, possiblement associées à des valeurs (identifiant, constante)
l’unité lexicale est différente de la chaîne de caractère associé, mais on
utilisera des notations similaires pour faciliter la lecture (en utilisant des
fontes spéciales ou des quotes pour éviter les confusions)
Exemple mini-python
commentaire : commence par le symbole # et se termine au retour à la ligne
mots-clés : def if else return print for in and or not
opérations arithmétiques (avec quotes) : ’+’ ’-’ ’*’ ’//’ ’%’
comparaisons : CMP (une seule unité, associée à l’opérateur de
comparaison)
symboles associés à l’indentation BEG END NL EOF
autres symboles spéciaux (avec quotes) :
’(’ ’)’ ’[’ ’]’ ’,’ ’=’ ’:’
constantes : CST (associé à une valeur entière, flottante ou chaîne de
caractères)
identifiants : ID associé à une représentation de l’identifiant (par exemple
chaîne)
NL
# dé f i n i t i o n s de f o n c t i o n s def ID ’(’ ID ’,’ ID ’,’ ID ’)’ ’:’ NL
def f i b a u x ( a , b , k ) : BEG if ID CMP CST ’:’ NL
i f k == 0 : BEG return ID NL
return a END else ’:’ NL
else :
BEG return ID ’(’ ID ’,’ ID ’+’ ID ’,’ ID ’-’ CST ’)’ NL
r e t u r n f i b a u x ( b , a+b , k −1)
Décrire par des règles (récursives) comment les entités sont construites
à partir des unités lexicales
deffun ::= def ID ’(’ lident ’)’ ’:’ suiteinstr
Il y a en général plusieurs règles pour la même entité
expr ::= ID
expr ::= CST
expr ::= unop expr
expr ::= expr binop expr
expr ::= ’(’ expr ’)’
expr ::= ID ’(’ lexpr ’)’
expr ::= expr ’[’ expr ’]’
expr ::= ’[’ lexpr ’]’
...
On utilise une notation générale pour couvrir l’ensemble des cas en les
séparant par des barres verticales
expr ::= ID | CST | unop expr | expr binop expr | ’(’ expr ’)’
| ID ’(’ lexpr ’)’ | expr ’[’ expr ’]’ | ’[’ lexpr ’]’
La suite d’unités lexicales est acceptée comme une entité valide si on peut
construire un arbre de dérivation dont la racine est le nom de l’entité, dont
chaque nœud interne correspond à une règle et dont les feuilles lues de
gauche à droite correspondent à la suite d’unités lexicales.
for ID in ’[’ CST ’,’ CST ’,’ CST ’,’ CST ’]’ ’:’ NL BEG print ’(’ ID ’(’ ID ’)’ ’)’ NL END
instr
simpleinstr
ID
CST ’+’ expr binop expr expr binop expr ’*’ CST
for ID in ’[’ CST ’,’ CST ’,’ CST ’,’ CST ’]’ ’:’ NL BEG print ’(’ ID ’(’ ID ’)’ ’)’ NL END
Sfor
[CST(0),CST(1),CST(11),CST(42)] Ecall
ID("fib") ID("n")
1 Motivations
2 Organisation du cours
3 Etapes de l’interprétation
Analyse lexicale
Analyse syntaxique
Arbre de syntaxe abstraite
Analyse sémantique et évaluation
4 Langages formels
Vocabulaire
Opérations sur les mots
Opérations sur les langages
Soit A un alphabet (ensemble fini) dont les éléments sont des caractères
un mot est une suite finie de caractères
un mot peut se modéliser par un entier naturel n ∈ N qui est la longueur du
mot et une application de [1 . . . n] dans A qui associe à un entier k tel que
1 ≤ k ≤ n la k -ème lettre du mot
d’un point de vue informatique, un mot est un tableau de caractères (mais
indicé à partir de 1)
si w est un mot, on note |w| la longueur du mot et pour k tel que
1 ≤ k ≤ |w|, on note w[k ] la k -ème lettre du mot w.
le mot aabb est de longueur 4, on a aabb[1] = aabb[2] = a et
aabb[3] = aabb[4] = b
si on se donne n caractères a1 , . . . , an ∈ A alors on peut former un mot de
longueur n tel que la k -ème lettre de ce mot est ak . On note cette suite
comme une juxtaposition des caractères qui la composent : a1 . . . an .
On utilisera si nécessaire des espaces pour séparer les caractères entre
eux.
Les langages sont des ensembles de mots finis ou infinis qui peuvent se
combiner pour former de nouveaux langages.
Les constructions usuelles d’ensembles s’appliquent aux langages.
union : w ∈ (L1 ∪ L2 ) ssi w ∈ L1 ou w ∈ L2
intersection : w ∈ (L1 ∩ L2 ) ssi w ∈ L1 et w ∈ L2
différence : w ∈ (L1 \L2 ) ssi w ∈ L1 et w ̸∈ L2
complémentaire : w ∈ ∁L1 ssi w ̸∈ L1
ε ∈ L∗
L ⊆ L∗
Si le langage L contient au moins un mot non vide, alors le langage L∗
contient des mots de longueur arbitrairement grande et est donc infini.
Soit A l’alphabet. A peut se voir comme un langage (ensemble des mots
formés d’un seul caractère).
On montre facilement que An est l’ensemble des mots sur l’alphabet A de
longueur n et A∗ est donc l’ensemble de tous les mots sur l’alphabet A.
2 Automates finis
5 Déterminiser un automate
2 Automates finis
5 Déterminiser un automate
Pour montrer qu’un langage (non vide) est régulier, il faut donc le
décomposer en des langages plus simples en utilisant les opérations
d’union, de concaténation ou d’étoile jusqu’à obtenir une lettre de
l’alphabet ou bien un langage réduit au mot vide.
Par convention le langage vide est également considéré comme un
langage régulier.
def
Soit w un mot sur l’alphabet A alors le langage L = {w} est régulier.
Si w est le mot vide ou un mot de longueur 1 c’est par définition des
langages réguliers (cas 1 et 2)
def
Sinon on a w = a1 . . . an avec ai ∈ A et n ≥ 2 on pose Li = {ai } qui est
régulier et on a L = L1 L2 . . . Ln
Tout ensemble fini de mots est régulier
vrai pour l’ensemble vide par définition
vrai pour un langage avec un seul mot par le résultat précédent
def def
si L = {w1 , . . . , wn } avec n ≥ 2 on pose Li = {wi } qui est régulier (résultat
précédent) et on a L = L1 |L2 . . . |Ln (union finie d’ensembles réguliers)
L’opération d’étoile est celle qui va permettre de construire des langages
réguliers infinis.
Donner des expressions régulières pour chacun des langages suivants sur
l’alphabet {a, b, c}
1 ensemble des mots qui commencent par abc
2 ensemble des mots qui ne contiennent pas de b
3 ensemble des mots qui commencent par abc ou ac
4 intersection des deux langages précédents
Solution
Solution
2 Automates finis
5 Déterminiser un automate
2 3
a b
c
0 1
b
a
4 5
c
a b c
0 1
1 2, 4
2 2 3
3
4 5
5 1
δ = {(0, c, 1), (1, a, 2), (1, a, 4), (2, a, 2), (2, c, 3), (4, c, 5), (5, c, 1)}
Plusieurs entrées possibles entre deux états (représentées par une seule
flèche étiquetée par les entrées)
C. Paulin (Université Paris-Saclay) PIL 2023–24 82 / 303
Automates avec ε-transition
Transitions δ 1
a b
a b c ε
0 1 2
1 3 2 0 ε 3
2 3
3 b c
2
Chaque automate définit un langage, celui des mots reconnus entre l’état
initial et un état final.
Définitions préalables des notions de chemin et de trace
Automate A = (A, Q, q0 , F , δ)
Transition : {(q, x, q ′ ) ∈ Q × (A ∪ {ε}) × Q|q ′ ∈ δ(q, x)}
Chemin : suite de transitions consécutives (l’état d’arrivée d’une
transition est l’état de départ de la suivante)
Un mot u ∈ A∗ est reconnu (on dit aussi accepté) par un automate A s’il
existe un chemin C d’origine l’état initial, dont la destination est un état
final et dont la trace est le mot u.
Le langage reconnu par l’automate A est l’ensemble des mots reconnus
par A. Il est noté L(A)
Un langage L est dit reconnaissable s’il existe un automate fini A tel que
L = L(A)
Théorème de Kleene : les langages reconnaissables sont exactement les
langages réguliers
Description par une expression régulière (étendue)
Reconnaissance par un automate fini
construire un automate fini déterministe qui reconnait tous les mots dans
lesquels apparait le mot abc :
un tel mot s’écrit uabcv
on dit que abc est un facteur du mot
(à ne pas confondre avec un sous-mot qui peut effacer des lettres
intermédiaires)
Solution
b
b
a 2
a 2
c
1 a
c b, c b
1 a
b
4(⊥) 3
a, c
3
a, b, c
Retour
Retour
Retour
a, b, c
a b c
0 1 2 3
Retour
a, b, c
a b c
0 1 2 3
b, c a, b, c
b, c
a a a
0 1 2 3
b, c
Retour
a, b, c
0 1
a, b, c
Retour
b, c a, b, c
b
a b c
0 1 2 3
c a
a
Retour
2 Automates finis
5 Déterminiser un automate
Objectif
Reconnaître dans une suite de caractères des mots tels que décrits par
des expressions régulières
En fonction de l’expression régulière et du mot reconnu, effectuer une
action
Fonctionnalité
Engendrer un automate (déterministe) à partir d’une expression régulière
Fonction de lecture d’une suite de caractères et de reconnaissance
successive des mots
%%
%i n c l u d e . . / TP / J f l e x . i n c l u d e
%s ta n da l o n e
%c l a s s M a i l
%{
v o i d ECHOL( S t r i n g c a t )
{ System . o u t . p r i n t l n ( " [ " + c a t + " : " + y y t e x t ( ) + " ] " ) ; }
%}
AL = [ a−zA−Z ]
OK = { AL } | [ 0 − 9 . − ]
%%
{ AL } {OK} * @ { AL } {OK} * \ . { AL}+
{ ECHOL( " MAIL " ) ; }
[^] { }
%%
%{
void ECHOL( S t r i n g c a t )
{ System . o u t . p r i n t l n ( " [ " + c a t + " : " + y y t e x t ( ) + " ] " ) ; }
%}
Code Java entre %{ ... %} inséré dans la classe, utilisé dans les
actions
Le code utilise la fonction yytext() qui renvoie dans l’action la chaîne
de caractère reconnue correspondant à l’expression régulière (type
String)
AL = [ a−zA−Z ]
OK = { AL } | [ 0 − 9 . − ]
%%
Séparateur entre la partie déclarations Jflex et les règles lexicales
{ AL } {OK} * @ { AL } {OK} * \ . { AL}+
{ ECHOL( " MAIL " ) ; }
[^] { }
Règles de priorité
les opérateurs postfixes *, + et ? sont plus prioritaires que la concaténation
elle-même plus prioritaire que l’union
ab*|c+ correspond à (a(b*))|(c+)
des parenthèses pour des articulations différentes comme ((ab)*|c)+
Caractères réservés
<>{}()[]|!~*+?"^$/.\,-
à protéger dans une chaîne "..." ou avec le caractère d’échappement \
comme dans \.
échappement non nécessaire dans certains contextes comme les classes
de caractères (à l’exception du tiret) ou les caractères ^$ lorsqu’ils ne sont
pas en début ou fin d’expression.
exemples : "(.)" \.\.\. \".*\" [+*/-] [+*-/]
%%
%i n c l u d e . . / TP / J f l e x . i n c l u d e
/ / i n t y y l i n e , yycolumn ; l o n g yychar ;
%l i n e
%column
%char
%s t a n d a lo n e / / Programme autonome
%cup / / Programme c o u p l é avec CUP
%i n i t { / * code dans l e c o n s t r u c t e u r : a c t i o n i n i t i a l e * /
System . o u t . p r i n t l n ( " Analyse L e x i c a l e Sample0 ( t y p e any t e x t ) : " ) ;
%i n i t }
%e o f { / * code en a c t i o n f i n a l * /
System . o u t . p r i n t l n ( " Bye ! " ) ;
%e o f }
%c a s e l e s s / * confondre minuscules / majuscules */
%s t a t e ETAT , ETAT2 / * É t a t s i n c l u s i f s du super −automate * /
%x s t a t e STATE / * É t a t s e x c l u s i f s du super −automate * /
Grace aux actions, on peut se servir d’un outil comme Jflex pour
reconnaître des langages qui ne sont pas réguliers.
Exemple : compter les parenthèses ouvrantes et fermantes
(commentaires imbriqués)
%%
<YYINITIAL > \ " { s t r i n g . s e t L e n g t h ( 0 ) ; yybegin ( STRING ) ; }
<STRING> {
\" { System . o u t . p r i n t l n ( s t r i n g . t o S t r i n g ( ) ) ;
yybegin ( YYINITIAL ) ; }
[^\n\ r \"\\]+ { s t r i n g . append ( y y t e x t ( ) ) ; }
\\ t { s t r i n g . append ( ’ \ t ’ ) ; }
\\n { s t r i n g . append ( ’ \ n ’ ) ; }
\\ r { s t r i n g . append ( ’ \ r ’ ) ; }
\\\" { s t r i n g . append ( ’ \ " ’ ) ; }
\\ { s t r i n g . append ( ’ \ \ ’ ) ; }
}
[^] { }
2 Automates finis
5 Déterminiser un automate
Alphabet A :
mot vide : ε
caractère : a ∈ A
concaténation : e1 e2
union : e1 | e2
étoile : e1∗
Construction par récurrence sur la structure de l’expression régulière :
On construit les automates pour les cas de base ε et a ∈ A
On suppose construits des automates pour e1 et e2 qui reconnaissent les
langages associés,
on construit alors l’automate pour e1 e2 , e1 | e2 et e1∗
Restrictions (invariant à préserver):
un seul état final
pas de transition qui arrive sur l’état initial ou sort de l’état final
mot vide
expression régulière ε
langage {ε}
automate : ({0}, 0, {0}, ∅)
caractère a ∈ A
expression régulière : a
langage {a}
automate : ({0, 1}, 0, {1}, {(0, a, 1)})
a
0 1
Déjà construits :
expressions régulières ei (i = 1, 2)
langages associés Li (i = 1, 2)
def
automates associés Ai = (Si , 0i , {fi }, Ti ) (i = 1, 2) avec S1 ∩ S2 = ∅
expression régulière : e1 e2
langage L1 L2
automate : (S1 ∪ S2 , 01 , {f2 }, T1 ∪ T2 ∪ {(f1 , ε, 02 )})
ε
01 A1 f1 02 A2 f2
01 A1 f1
ε ε
0 f
ε ε
02 A2 f2
Déjà construit
expression régulière e1
langage associé L1
def
automate associé A = (S1 , 01 , f1 , T1 )
expression régulière : e∗
langage L∗
def
automate : A1 = (S ∪ {0, f }, 0, {f },
T ∪ {(0, ε, 01 ), (f1 , ε, f ), (01 , ε, f1 ), (f1 , ε, 01 )})
ε
ε ε
0 01 A1 f1 f
2 Automates finis
5 Déterminiser un automate
a, b
a b
0 0 0, 1 b b
0 1 2
1 2
2
q0 = 0, F = {2}
b
a
b
a b b
{0} {0} {0, 1} {0} {0, 1} {0, 1, 2}
{0, 1} {0} {0, 1} ∪ {2} a
{0, 1, 2} {0} {0, 1} ∪ {2}
q0 = {0}, F = {{0, 1, 2}} a
Présence de ε-transition
Possibilité de passer d’un état à l’autre de manière “silencieuse” (sans
entrée)
On associe à un état tous ceux atteignables par une ou plusieurs
ε-transitions
Définition de l’ε-cloture d’un état q ∈ Q : l’ensemble des états q ′ pour
lesquels il existe un chemin de q à q ′ dont la trace est le mot vide ε
b a
b
a b ε ε b b
0 0 1 0 1 2 3 4
1 4
2 1, 4 0 ε a ε
3 1
4 3 2
q0 = 0, F = {4}
Etat ε − cloture
0 {0, 1}
1 {1}
2 {0, 1, 2}
3 {3}
4 {0, 1, 2, 4}
On fait l’union des ε-clotures des suites possibles des états de la source
pour le caractère x
Etats terminaux : contiennent un état terminal de F
a, b
a b ε
ε−clot
0 0 0 1 ε b b
0 1 2 2 0 0, 1
1 2
1 1
2 3
2 2
3
3 3
q0 = 0, F = {3}
b
a
a b a
{0, 1} {0, 1} {0, 1, 2} b b
{0, 1} {0, 1, 2} {0, 1, 2, 3}
{0, 1, 2} {0, 1} {0, 1, 2, 3}
{0, 1, 2, 3} {0, 1} {0, 1, 2, 3}
q0 = {0, 1}, F = {{0, 1, 2, 3}} a
b 1
4 6
ε
0
ε a c a a
a c ε a
2 3 5 7
c
a
Solution
l e t t e r = [ a−z ]
d i g i t = [0 −9]
id = l e t t e r ( l e t t e r | d i g i t )*
if = " if "
i n t = ( d i g i t )+
f l o a t = ( d i g i t )+ " . " ( d i g i t )+
dot = " . "
bl = (" ")+
ε ε ε ε ε ε
1 3 6 8 12 14
2 7 9 0-9
13 15
id 4 int dot
.
f ’ ’
a-z0-9 0-9 10
5
if 0-9
11 0-9
float
Calcul de l’ε-clotûre
1 Etat initial {0, 2} : transitions possibles a, b, c
a : état {0, 2}
b : état {0, 1, 2}
c : état {3, 5}
0 0, 2
1 1, 0, 2
2 Etat {0, 1, 2} : mêmes transitions que {0, 2}
2 2 3 Etat {3, 5}: transition possible a vers {4, 6, 7}
3 3, 5 4 Etat {4, 6, 7}: transitions possibles a, c
4 4 a : état {5}
5 5 c : état {3, 5}
6 6 5 Etat {5}: transition possible a vers {6, 7}
7 7 6 Etat {6, 7}: transitions possibles a, c
a : état {5}
c : état {3, 5}
7 Etats terminaux : {6, 7} et {4, 6, 7}
{0, 1, 2} b
b
a
{0, 2} c
c c
a a a a
{3, 5} {4, 6, 7} {5} {6, 7}
c a
Retour
(0, 1)
b a
b a
(0, 0) (1, 1)
a b
a b
(1, 0)
Retour
2 Automates finis
5 Déterminiser un automate
Par définition
L’union et la concaténation de deux langages réguliers est un langage
régulier
L’étoile d’un langage régulier est un langage régulier
Le complémentaire d’un langage régulier est un langage régulier
L’intersection de deux langages réguliers est un langage régulier
a a
0 1 2 a
b b b
a a
b 3 4 5 a
b
b
6 a, b
Solution
2 Automates finis
5 Déterminiser un automate
Preuve: La preuve vient de l’existence d’une boucle dans tout chemin qui
permet de reconnaître le mot m de longueur strictement supérieure au
nombre d’états de l’automate. □
Proposition
Le langage L = {an bn |n ∈ N} n’est pas régulier.
Preuve:
Si le langage était régulier, soit N la constante du lemme d’itération
Soit m = aN bN on a m = xyz mais comme |xy | ≤ N on a y = ap avec
p>0
On aurait xy 2 z = aN+p bN ∈ L ce qui est contradictoire.
□
Le même argument permet de montrer que le langage formé des mots qui ont
le même nombre de a et de b n’est pas régulier.
2 Automates finis
5 Déterminiser un automate
e1 e2
s1 s s2
e1 (e)∗ e2
b b
a
ε ε
0 1 2 f
a
b b ε
ε a ε b ε
0 1 2 3 4 f
a a
a
Solution
2 Automates finis
5 Déterminiser un automate
Complémentaire
1 Prendre un automate déterministe et le compléter avec des entrées pour
toutes les entrées à l’aide d’un état puits
2 Prendre comme états terminaux de l’automate du complémentaire tous les
états qui ne sont pas terminaux dans l’automate initial (en particulier l’état
puits)
Intersection de deux langages reconnaissables
1 Construire un automate déterministe pour chacun des langages
def
Ai = (Si , 0i , Fi , Ti ) (i = 1, 2)
2 L’automate pour l’intersection a pour état des couples (s1 , s2 ) avec si ∈ Si
3 Etat initial : (01 , 02 )
4 Transition : ((s1 , s2 ), a, (t1 , t2 )) si et seulement si (si , a, ti ) ∈ Ti
5 Etat final : (s1 , s2 ) avec si ∈ Fi
Retour
A∗ \ L2
a a b
b
b
0 1 2
a
b a
a
(2, 0) a
Retour
Automate minimisé :
a
a
0 1, 2
b b
a b
b 3 4, 5 6 a, b
a Retour
b b
a
ε ε
0 1 2 f
a
b|ab∗ a
b∗ a ε
0 2 f
b∗ a(b|ab∗ a)∗
0 f
Retour
Définition
Vocabulaire : automates déterministes, complets, (a)synchrones
Répondre à la question si un mot est reconnu ou non par un automate
Construire un automate correspondant à un langage donné
Opérations sur les automates (union, concaténation, étoile,
complémentaire, intersection)
Calculer des ε-clotures, rendre un automate déterministe
Enoncé du théorème de Kleene : langages réguliers = langages
reconnaissables,
Exemple(s) de langage non régulier