Chapitre 4 Réalisation d un analyseur lexical Jean Privat Université du Québec à Montréal INF5000 Théorie et construction des compilateurs Automne 2013 Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 1 / 29
Analyse lexicale Analyseur lexical Donnée : une séquence de caractères Résultat : une séquence de jetons (lexèmes) Un jeton : un type (étiquette) & un texte & une position (ligne/colonne) for i = 1 to 10 do print i... for id eq int to Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 2 / 29
Génération d analyseur lexical Générateur d analyseur lexical Donnée : une description d un langage Résultat : le code source d un analyseur Exemple : SableCC4 Génère du Java (entre autres) Description langage SableCC4 Source Java Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 3 / 29
Description de langage Grammar demo ; Lexer l e t t e r = a.. z ; d i g i t = 0.. 9 ; i d e n t i f i e r = l e t t e r ( l e t t e r d i g i t ) ; comma =, ; b l a n k = ( #9 #10 #13)+; i f = i f ; e l s e = e l s e ; Parser i d e n t i f i e r, comma, i f, e l s e ; Ignored b l a n k ; Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 4 / 29
Sélection de jetons Plusieurs séquençages en jetons sont souvent possibles Séquence de caractères : ify 1 jeton : id ify 2 jetons : id if, id y 2 jetons : if if, id y 2 jetons : id i, id fy 3 jetons : id i, id f, id y Pas de place à l ambiguïté Il faut des règles! Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 5 / 29
Règles de l analyse lexicale Règle 1 Le jeton le plus long gagne toujours Exercice : Traitez les séquences suivantes toto,,i iiff iff i f Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 6 / 29
Règles de l analyse lexicale Règle 1 Le jeton le plus long gagne toujours Exercice : Traitez les séquences suivantes toto,,i 4 jetons : id toto, comma,, comma,, id i iiff iff i f 4 jetons : id iiff, id iff, id i, id f Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 6 / 29
Règles de l analyse lexicale Règle 2 Des jetons de même taille ne peuvent gagner ensemble Exemple Séquence de caractères : if 1 jeton, deux choix : id if ou if if Solutions Lex, SableCC3 : Ordre des déclarations importe SableCC4 : Priorité d inclusion Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 7 / 29
Priorité lexicale d inclusion en SableCC4 Règle de l inclusion lexicale Une expression régulière strictement inclue dans une autre gagne la priorité Remarque : fait en général la bonne chose Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 8 / 29
Priorité lexicale d inclusion en SableCC4 Grammar p r i o r i t e d i n c l u s i o n : Lexer i d e n t i f i e r = ( a.. z )+; i f = i f ; Token i d e n t i f i e r, i f ; Ignored, #9, #10, #13; if identifier donc if à la priorité sur identifier pour une chaîne de même taille Exercice : Traitez les séquences suivantes i f if iffy Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 9 / 29
Priorité lexicale d inclusion en SableCC4 Grammar p r i o r i t e d i n c l u s i o n : Lexer i d e n t i f i e r = ( a.. z )+; i f = i f ; Token i d e n t i f i e r, i f ; Ignored, #9, #10, #13; if identifier donc if à la priorité sur identifier pour une chaîne de même taille Exercice : Traitez les séquences suivantes i f 2 jetons : id i, id f if 1 jeton : if if (priorité d inclusion) iffy 1 jeton : id iffy Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 9 / 29
Déclarer les inclusions lexicales en SableCC4 Déclaration de priorités La directive Precedence permet de déclarer des priorités Attention : on a en rarement besoin Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 10 / 29
Forcer la priorité lexicale en SableCC4 Grammar p r i o r i t e f o r c e e ; Lexer l e t t e r = a.. z ; d i g i t = 0.. 9 ; i d e n t i f i e r = l e t t e r ( l e t t e r d i g i t ) ; h e x i n t e g e r = ( d i g i t a.. f )+ Except Token i d e n t i f i e r, h e x i n t e g e r ; Exercice : traitez les séquences suivantes z10 00ff1 h e x i n t e g e r fff 00fg1 Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 11 / 29
Forcer la priorité lexicale en SableCC4 Grammar p r i o r i t e f o r c e e ; Lexer l e t t e r = a.. z ; d i g i t = 0.. 9 ; i d e n t i f i e r = l e t t e r ( l e t t e r d i g i t ) ; h e x i n t e g e r = ( d i g i t a.. f )+ Except Token i d e n t i f i e r, h e x i n t e g e r ; Exercice : traitez les séquences suivantes z10 1 jeton : identifier z10 00ff1 1 jeton : hexinteger 00ff1 fff 1 jeton : identifier fff (priorité déclarée) 00fg1 2 jetons : hexinteger 00f, identifier g1 h e x i n t e g e r Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 11 / 29
Fonctionnement d un analyseur lexical Éléments de base Expressions régulières Automates Particularité Ne plus reconnaître les mot d un langage (simple algorithme de décision oui/non) Mais extraire des jetons d une séquence de caractères (possiblement seulement connue au fur et à mesure, voire infinie) Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 12 / 29
Un seul automate fini déterministe Un automate fini déterministe unique Un automate pour les reconnaître tous Un automate pour les trouver Un automate pour les extraire tous et en jetons les séquencer Forger l automate unique Transformer l expression régulière de chaque jeton en NFA Marquer les états d acceptation des NFA par le jeton Regrouper tous les états de départ Transformer en DFA Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 13 / 29
Exemple d automate unique Grammar automate : Lexer l e t t e r = a.. z ; d i g i t = 0.. 9 ; i d = l e t t e r ( l e t t e r d i g i t ) ; i f = i f ; i n t = ( d i g i t )+; f l o a t = ( d i g i t )+. ( d i g i t )+; dot =. ; b l = ; Token id, i f, i n t, f l o a t, dot ; Ignored b l ; Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 14 / 29
Exemple d automate unique (NFA) 0 ε ε ε ε ε ε 1 3 6 8 12 14 a..z i 0..9 0..9. ' ' 2 id a..z,0..9 4 7 int 0..9 9 0..9 13 dot 15 bl ' ' f. 5 if 10 0..9 11 float 0..9 Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 15 / 29
Exemple d automate unique (DFA) a..h,j..z a..z,0..9 2,4 id f a..e,g..z,0..9 a..z,0..9 2 id i 0..9 2,5 if 0..9 0,1, 3,6,8 12,14 0..9. 7,9 int. 0..9 10 11 float ' ' 13 dot ' ' 15 bl Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 16 / 29
Gestion des priorités Définition de conflit Un état d acceptation du DFA unique est annoté de plusieurs jetons Résolution de conflit Par priorité d inclusion Erreur sinon Calcul des inclusions des tokens Déduit de l inclusion des états d acceptations Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 17 / 29
Principe d extraction de jetons Avancer Le plus loin possible dans l automate En mémorisant le dernier état d acceptation rencontré Si avancer est impossible, alors Retourner le jeton du dernier état d acceptation rencontré Repartir de l état de départ de l automate Commencer au caractère qui suit le jeton retourné Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 18 / 29
Algorithme d extraction de jetons Données : Un DFA D, une séquence de caractères S Résultat : Une séquence de jetons J debut = pos = 0 ; candidat = null ; E = départ(d); Boucler c = caractère numéro pos de S (ou EOF sinon); pos + +; E = successeur de E par la transition c (ou null sinon); si E == null alors si candidat == null alors retourner erreur lexicale; si candidat n est pas ignoré alors ajouter candidat à J; si c == EOF alors retourner J; E = départ(d) ; pos = debut = caractère après candidat; candidat = null; sinon si E accepte jeton j alors candidat = new Jeton(j, debut, pos-1); fin fin Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 19 / 29
Algorithme d extraction Exercice : Traitez les séquences suivantes if cond iffy10 iffy 11 12.13 14. 15 1.2.3.4.5 1a2b3c4 1.a Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 20 / 29
Algorithme d extraction Exercice : Traitez les séquences suivantes if cond iffy10 iffy 11 12.13 14. 15 9 jetons : if if, id cond, id iffy10, id iffy, int 11, float 12.13, int 14, dot., int 15 1.2.3.4.5 5 jetons : float 1.2, dot., float 3.4, dot., int 5 1a2b3c4 2 jetons : int 1, id a2b3c4 1.a 3 jetons : int 1, dot., id a Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 20 / 29
Coût algorithmique En pratique Linéaire en la taille de la séquence de caractères Au pire Quadratique en la taille de la séquence de caractères Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 21 / 29
Pire coût algorithmique Exemple de langage du pire coût Grammar p i r e c o u t : Lexer a = a ; b = a b ; Token a, b ; Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 22 / 29
Pire coût algorithmique (NFA) ε 1 a 2 a 0 ε a 3 b 4 b Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 23 / 29
Pire coût algorithmique (DFA) a 0,1,2 a 2,3 a b 3 4 a b b b Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 24 / 29
Pire coût algorithmique Exercice : Traitez les séquences suivantes & comptez les tours de boucle aaab aaa aaaaa mille a suivis d un b ( aa..ab ) mille a ( aa..a ) Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 25 / 29
Pire coût algorithmique Exercice : Traitez les séquences suivantes & comptez les tours de boucle aaab 1 jeton b aaab ; 5 tours de boucle aaa 3 jetons a a ; 9 tours de boucle aaaaa 5 jetons a a ; 21 tours de boucle mille a suivis d un b ( aa..ab ) 1 gros jeton b ; 1002 tours de boucles mille a ( aa..a ) 1000 jetons a ; 501501 tours de boucles Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 25 / 29
Utilisation du générateur d analyseur SableCC4 Invocation de SableCC4 $ sablecc4 langage.sablecc -p pack.age langage.sablecc est le fichier de description de langage pack.age est le package racine des classes Java générées les fichiers sont crées à partir du répertoire pack/age Fichiers générées pack/age/language_xxx/lexer.java la classe qui fait l analyse lexicale pack/age/language_xxx/token.java la classe racine des jetons Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 26 / 29
API principale des classes générées Classe Lexer Constructeur Lexer(Reader) Initialise un nouvel analyseur syntaxique à partir d une séquence de caractères. Méthode Token next() throws LexerException, IOException Retourne le jeton suivant ou un jeton de type spécial TEnd à la fin de la séquence Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 27 / 29
API principale des classes générées Classe Token Méthode String gettext() Retourne la chaîne de caractère du jeton Méthode Type gettype() Retourne le type du jeton du jeton Exemple : T_Integer pour le jeton integer Attention, le type spécial TEnd n a pas de souligné. Méthodes int getline() et int getpos() Retournent la ligne et la colonne du jeton Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 28 / 29
Exemple d utilisation d un analyseur p u b l i c c l a s s Demo { p u b l i c s t a t i c void main ( S t r i n g [ ] a r g s ) { t r y { F i l e R e a d e r f r = new F i l e R e a d e r ( a r g s [ 0 ] ) ; L e x e r l e x e r = new L e x e r ( f r ) ; Token t ; do { t = l e x e r. next ( ) ; System. out. p r i n t l n ( [ +t. g e t L i n e ()+, + t. getpos ()+ ] +t. gettype ()+ + t. gettext ()+ ) ; } while ( t. gettype ( )!= Node. Type. TEnd ) ; } catch ( E x c e p t i o n e ) { System. e r r. p r i n t l n ( e. getmessage ( ) +. ) ; }}} Jean Privat (UQAM) 04 Analyseur lexical INF5000 Automne 2013 29 / 29