La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Analyse lexicale Pr ZEGOUR DJAMEL EDDINE Ecole Supérieure dInformatique (ESI)

Présentations similaires


Présentation au sujet: "Analyse lexicale Pr ZEGOUR DJAMEL EDDINE Ecole Supérieure dInformatique (ESI)"— Transcription de la présentation:

1 Analyse lexicale Pr ZEGOUR DJAMEL EDDINE Ecole Supérieure dInformatique (ESI)

2 Analyse lexicale Taches dun scanner Grammaires Régulières et Automates finis Implémentation des scanners

3 Taches dun scanner 1.Délivre les symboles terminaux (unités lexicales) if(x=3)= Source scanner IF, LPAR, IDENT, EQ, NUMBER, RPAR,..., EOF Unités lexicales Les unités lexicales ont une structure syntaxique ident =letter { letter | digit }. number =digit { digit }. if ="i" "f". eql ="=" "=" Saute les caractères non significatifs blancs Caractères de tabulation Caractères de fin de lignes (CR, LF) Commentaires

4 Pourquoi la phase lexicale est séparée de la phase syntaxique? Entrainerait une analyse syntaxique plus compliquée (Ex. distinction difficile entre les mots clés et les identificateurs) Statement=ident "=" Expr ";" |"if" "(" Expr ")".... On doit écrire ceci comme suit Statement="i"("f" "(" Expr ")"... |letter {letter | digit} "=" Expr ";" ) Le scanner doit éliminer les caractères non significatifs Ces caractères peuvent apparaître partout => conduiraient vers des grammaires très complexes) Statement="if" {Blank} "(" {Blank} Expr {Blank} ")" {Blank}.... Blank = " " | "\r" | "\n" | "\t" | Comment. Les unités lexicales peuvent être decrites à laide de grammaires régulières (Plus simple et plus efficace que les grammaires à contexte libre)

5 Analyse lexicale Taches dun scanner Grammaires Régulières et Automates finis Implémentation des scanners

6 Grammaires régulières Définition Une grammaire est dite régulière si elle peut être décrite par des productions de la forme: A = a. A = b B. a, b des TS A, B des NTS Exemple Grammaire pour les identificateurs Ident=letter |letter Rest. Rest=letter |digit |letter Rest |digit Rest. Ex., dérivation de xy3 Ident => letter Rest => letter letter Rest => letter letter digit Autre définition Une grammaire est dite régulière si elle peut être décrite par une simple non récursive production EBNF. Exemple Grammaire pour les identificateurs Ident=letter { letter | digit }.

7 Exemples Peut-on transformer la grammaire suivante en une grammaire régulière? E = T { "+" T }. T = F { "*" F }. F = id. Après substitution de F dans T T = id { "*" id }. Peut-on transformer la grammaire suivante en une grammaire régulière? E = F { "*" F }. F = id | "(" E ")". Après substitution de F dans E E = ( id | "(" E ")" ) { "*" ( id | "(" E ")" ) }. Substituer E dans E ne mène à rien. Récursion centrale ne peut être éliminée. La grammaire est non régulière. Après substitution de T dans E E = id { "*" id } { "+" id { "*" id } }. La grammaire est régulière

8 Limitations des grammaires régulières Les grammaires régulières ne traitent pas les structures emboîtées Raison : ne peut éliminer la récursion centrale! La récursion centrale est importante dans les langages de programmation. Class => "class" "{"... Class... "}" Expressions emboîtées Instructions emboîtées Classes emboîtées Expr =>... "(" Expr ")"... Statement => "do" Statement "while" "(" Expr ")" Solution : utilisation des grammaires à contexte libre. Les structures lexicales sont généralement régulières nom letter { letter | digit } nombres digit { digit } chaînes "\"" { pas de quote } "\"" Mot-clés letter { letter } opérateurs ">" "=" Exception: commentaires emboîtés /*..... /*... */..... */ Le scanner doit les traiter comme cas spécial

9 Expressions régulières Autre notation pour les grammaires régulières Définition 1. (la chaîne vide) est une expression régulière 2. Un symbole terminal est une expression régulière 3. Si et sont des expressions régulières, les expressions suivantes sont régulières: ( | ) ( )? | ( )* | | | |... ( )+ | | |... Exemples "w" "h" "i" "l" "e" while letter ( letter | digit )* names digit+ numbers

10 Automate Fini Déterministique (DFA) Peut être utilisé pour analyser les langages réguliers Exemple 01 État final digit letter État initial est 0 par convention Table de transition letterdigit s0 s1 s1error s1 "fini", car Peut être défini explicitement Définition Un automate fini déterministique est un 5 tuple (S, I,, s0, F) SEnsemble des états IEnsemble des symboles dentrée : S x I SFonction de transition des états s0État initial FEnsemble des états finaux Un DFA reconnaît une phrase (sentence) Sil est dans un état final Et il ny a plus de symboles dentrée Ou il n y a pas de transition possible avec le prochain symbole dentrée Le langage reconnu par une DFA est lensemble de toutes les séquences de symboles pouvant être générées de létat initial vers lun des états finaux.

11 Le Scanner comme un DFA Le scanner peut être vu comme un grand DFA 0 " 1 letter digit 2 3 ( 4 > 5 =... Exemple Entrée: max >= 30 s0s1 m a x Pas de transition avec " " dans s1 ident reconnu > = s0s5 Saute les blancs au début Ne sarrête pas en s4 Pas de transition avec " " dans s5 geq reconnu s0s2 3 0 Saute les blancs au début Pas de transition avec " " dans s2 number reconnu Après chaque unité lexicale reconnue le scanner recommence à létat initial s0 ident number lpar gtrgeq

12 Transformation: grammaire régulière vers DFA Une grammaire régulière peut être transformée en un DFA comme suit A = b C. AC b A = d. A d stop Exemple Grammaire A = a B | b C | c. B = b B | c. C = a C | c. Automate AB a C b stop c a c b c

13 Automate Fini Non Déterministique (NDFA) Exemple 01 digit 2 hex H 3 intNum hexNum intNum =digit { digit }. hexNum =digit { hex } "H". digit ="0" | "1" |... | "9". hex =digit | "A" |... | "F". Non déterministique car Il y a 2 possibles transitions avec digit dans s0 Chaque NDFA peut être transformé en un DFA équivalent 01 digit 2 A,B,C,D,E,F digit hex H 3 intNum hexNum H

14 Implémentation dun DFA (Variante 1) Implémentation de comme une matrice int[,] delta = new int[maxStates, maxSymbols]; int lastState, state = 0; // DFA starts in state 0 do { int sym = next symbol; lastState = state; state = delta[state, sym]; } while (state != undefined); assert(lastState in F); // F is set of final states return recognizedToken[lastState]; Exemple pour 02 a 1 c b A = a { b } c. A abc F int[,] delta = { {1, -1, -1}, {-1, 1, 2}, {-1, -1, -1} }; Cette implémentation pourrait être très inefficace pour un véritable scanner

15 Implémentation dun DFA (Variante 2) 02 a 1 c b A Coder les états dans le code source int state = 0; loop: for (;;) { char ch = read(); switch (state) { case 0:if (ch == 'a') { state = 1; break; } else break loop; case 1:if (ch == 'b') { state = 1; break; } else if (ch == 'c') { state = 2; break; } else break loop; case 2: return A; } return errorToken; en Java cest plus fatiguant: char ch = read(); s0:if (ch == 'a') { ch = read(); goto s1; } else goto err; s1:if (ch == 'b') { ch = read(); goto s1; } else if (ch == 'c') { ch = read(); goto s2; } else goto err; s2:return A; err:return errorToken;

16 Analyse lexicale Taches dun scanner Grammaires Régulières et Automates finis Implémentation des scanners

17 Interface du Scanner class Scanner { static voidInit (TextReader r) {...} static TokenNext () {...} } Scanner.Init(new StreamReader("myProg.zs")); Initialisation du scanner Token t; for (;;) { t = Scanner.Next();... } Lecture des unités lexicales

18 Unités lexicales class Token { public const int NONE = 0, IDENT = 1, …. int kind;// token code int line;// token line (for error messages) int col;// token column (for error messages) int val;// token value (for number and charCon) string str;// token string (for numbers and identifiers) } PLUS= 4,/* + */ MINUS= 5,/* - */ TIMES= 6,/* * */ SLASH= 7,/* / */ REM= 8,/* % */ EQ= 9,/* == */ GE= 10,/* >= */ GT= 11,/* > */ LE= 12,/* <= */ LT= 13,/* < */ NE= 14,/* != */ AND= 15,/* && */ OR= 16,/* || */ Exemple de codage pour un langage particulier const int NONE = 0,IDENT = 1, NUMBER = 2, CHARCONST = 3, ASSIGN= 17,/* = */ PPLUS= 18,/* ++ */ MMINUS= 19,/* -- */ SEMICOLON= 20,/* ; */ COMMA= 21,/*, */ PERIOD= 22,/*. */ LPAR= 23,/* ( */ RPAR= 24,/* ) */ LBRACK= 25,/* [ */ RBRACK= 26,/* ] */ LBRACE= 27,/* { */ RBRACE= 28,/* } */ BREAK= 29, CLASS= 30, CONST= 31, ELSE= 32, IF= 33, NEW= 34, READ= 35, RETURN = 36, VOID= 37, WHILE= 38, WRITE= 39, EOF= 40; ErreurClasses des unitésOpérateurs et caractères spéciauxMot-clésFin de fichier

19 Implémentation des Scanner Variables statiques dans le scanner static TextReader input;// input stream static char ch;// next input character (still unprocessed) static int line, col;// line and column number of the character ch const int EOF = '\u0080';// character that is returned at the end of the file Init() public static void Init (TextReader r) { input = r; line = 1; col = 0; NextCh(); // reads the first character into ch and increments col to 1 } NextCh() static void NextCh() { try { ch = (char) input.Read(); col++; if (ch == '\n') { line++; col = 0; } else if (ch == '\uffff') ch = EOF; } catch (IOException e) { ch = EOF; } } ch = prochain caractère dentrée retourne EOF si fin de fichier incrémente line et col

20 Method Next() public static Token Next () { while (ch <= ' ') NextCh(); // skip blanks, tabs, eols Token t = new Token(); t.line = line, t.col = col; switch (ch) { case 'a':... case 'z': case 'A':... case 'Z': ReadName(t); break; case '0': case '1':... case '9': ReadNumber(t); break; case ';': NextCh(); t.kind = Token.SEMICOLON; break; case '.': NextCh(); t.kind = Token.PERIOD; break; case EOF: t.kind = Token.EOF; break; // no NextCh() any more... case '=':NextCh(); if (ch == '=') { NextCh(); t.kind = Token.EQ; } else t.kind = Token.ASSIGN; break; case '&':NextCh(); if (ch == '&') { NextCh(); t.kind = Token.AND; } else t.kind = NONE; break;... case '/':NextCh(); if (ch == '/') { do NextCh(); while (ch != '\n' && ch != EOF); t = Next(); // call scanner recursively } else t.kind = Token.SLASH; break; default:NextCh(); t.kind = Token.NONE; break; } return t; } // ch holds the next character that is still unprocessed nom, mot-clés nombres unité simple unités composée commentaire caractère invalide

21 Autres méthodes static void ReadName (Token t) Au début ch contient la première lettre du nom Lit les prochaines lettres, digits et '_' et les range dans t.str Chercher le nom dans la table des mots clés ( hash-code ou arbre de recherche binaire ) si trouvé: t.kind = code du mot clé; sinon: t.kind = Token.IDENT; À la fin, ch contient le premier caractère après le nom static void ReadNumber (Token t) Au début ch contient le premier chiffre du nombre Lit les prochains digits, les range dans t.str; puis convertit la chaîne en un nombre et range la valeur dans t.val. Si débordement:Erreur t.kind = Token.NUMBER; A la fin ch contient le premier caractère après le nombre

22 Considérations defficacité Taille dun programme modeste Aux environs de 1000 instructions environ 6000 unités environ caractères La phase lexicale consomme un temps important prend 20-30% du temps total de compilation Faire attention à la programmation Utiliser les variables globales : Ex.: ch est global et non un paramètre de NextCh() Pour les grands fichiers dentrée, cest judicieux dutiliser des lectures bufférisées Stream file = new FileStream("MyProg.zs"); Stream buf = new BufferedStream(file); TextReader r = new StreamReader(buf); Scanner.Init(r);


Télécharger ppt "Analyse lexicale Pr ZEGOUR DJAMEL EDDINE Ecole Supérieure dInformatique (ESI)"

Présentations similaires


Annonces Google