1 / 30

Générateurs de compilateurs

Générateurs de compilateurs. Pr ZEGOUR DJAMEL EDDINE Ecole Supérieure d’Informatique (ESI) www.zegour.uuuq.com email: d_zegour@esi.dz. Générateurs de compilateurs Introduction Yacc Lex Coco/R. générateur scanner. scanner. Spécification du scanner Ex. grammaire régulière).

minda
Download Presentation

Générateurs de compilateurs

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Générateurs de compilateurs Pr ZEGOUR DJAMEL EDDINE Ecole Supérieure d’Informatique (ESI) www.zegour.uuuq.com email: d_zegour@esi.dz

  2. Générateurs de compilateurs Introduction Yacc Lex Coco/R

  3. générateur scanner scanner Spécification du scanner Ex. grammaire régulière) générateur de l’analyseur Analyseur Spécification sémantique (Ex. grammaire d’attribut) Générateur De compilateurs Exemples Yacc générateur d’analyseur syntaxique et sémantique pour C et Java Lex générateur de scanner pour C, Java et C# Coco/R générateur de scanner et d’analyseur pour Java, C#, Modula-2, Oberon, ... ... Fonctionnement des générateurs de compilateurs Ils génèrent les parties d’un compilateur à partir d’une spécification concise (Parties générées : scanner, analyseur syntaxico-sémantique, générateur de code , ...) compilateur & éditeur de liens compilateur généré • Classes utilisateur • Table des symboles • Générateur de code • Programme principal • ...

  4. Générateurs de compilateurs Introduction Yacc Lex Coco/R

  5. Utilisation Yacc javac sample.y parser.java parser.class Versions actuelles Bison version GNU de Yacc http://www.gnu.org/software/bison/bison.html Byacc Berkeley Yacc http://byaccj.sourceforge.net/ Yacc - Yet another compiler compiler Histoire • 1975 développé aux laboratoires Bell ( ensemble avec C et Unix) • Génère des analyseurs LALR(1) • À l’origine sous Unix, Aujourd'hui aussi sous Windows, Linux • A l’origine pour C, Aujourd'hui pour Java Nous décrivons ici la version de Java

  6. class parser { ... public void yyparse() { ... parser ... } } Traduit vers Langage d’entrée pour Yacc Format général %{package Java et les lignes ‘import’ %} Déclarations Yacc (unités, règles de précédence des opérateurs, ...) %% productions %% Déclarations Java (champs, méthodes)

  7. Actions Sémantiques • Peuvent contenir des instructions Java • Peuvent apparaître seulement à la fin d’une alternative • Les attributs sont dénotés par des noms spéciaux: $$ attribut du coté gauche NTS $i attribut du i-ème symbole du coté droit ($1 = attr. du premier symbole, $2 = attr. du second symbole, ...) Yacc — Productions et actions sémantiques Productions Grammar = {Production}. Production = NT ":" Alternative {"|" Alternative} ";" Alternative = {NT | T} [SemAction]. SemAction = "{" ... arbitrary Java statements ... "}". NT = ident. T = ident | charConst. Exemple expr: term { $$ = $1; } | expr '+' term { $$.ival = $1.ival + $3.ival; } ;

  8. Pour les symboles non terminaux • Chaque NTS a un attribut $$ de type parserval ( valeurs plus complexes rangées dans $$.obj) • Chaque affectation à $$ empile l’attribut du NTS dans une pile d’attributs.Les accès à $1, $2 se font en dépilant les attributs de la pile Yacc — Attributs Pour les symboles terminaux • Sont délivrés par le scanner (scanner développé manuellement ou généré avec Lex) • Chaque unité lexicale a un attribut de type parserval class parserval { int ival; // token value if the token should have an int attribute double dval; // token value if the token should have a double attribute String sval; // token value, e.g. for ident and string Object obj; // token value for more complex tokens parserval(int val) {...} // constructors parserval(double val) {...} parserval(String val) {...} parserval(Obj val) {...} } • Le scanner retourne les attributs dans la variable globale yylval Scanner Accès dans une action sémantique yylval = new parserval(n); { ... $1.ival ... }

  9. Yacc — Variables et Méthodes Java Sont déclarées après le second %% %{ ... imports ... %} ... Unités ... %% ... Productions ... %% ... DéclarationsJava ... • Deviennent des champs et des méthodes pour l’analyseur • Peuvent être utilisées dans les actions sémantiques Au moins les méthodes suivantes doivent être implémentées dans les déclarations Java Pour afficher les messages d’erreur void yyerror(String msg) {...} Scanner (retourne les codes des unités et remplit yylval) int yylex() {...} public static void main(String[] arg) { ... initializations for yylex ... yyparse(); } Programme principal

  10. Exemple: Compilateur pour les expressions arithmétiques Conventions de codage des unités /* declaration of all tokens which are not strings */ %token number %% /* productions: first NTS is the start symbol */ input: expr { System.out.println($1.ival); } ; expr: term { $$ = $1; } | expr '+' term { $$.ival = $1.ival + $3.ival; } ; term: factor { $$ = $1; } | term '*' factor { $$.ival = $1.ival * $3.ival; } ; factor: number { $$ = $1; } | '(' expr ')' { $$ = $2; } ; %% int yylex() {...} void yyerror(string msg) {...} public static void main(String[] arg) {...} • eof == 0 • Code des unités ‘caractère’ : • leurs valeurs Ascii • (Par exemple '+' == 43) • YYERRCODE == 256 • Autres unités sont numérotées • consécutivement commençant par 257 (Par exemple. nombre == 257);elles peuvent être accédées dans les • productions et dans yylex() utilisant • leur nom déclaré.

  11. On peut aussi l’exprimer comme suit en Yacc: %token number %left '+' %left '*' %% input: expr { System.out.println($1.ival); } ; expr: number { $$ = $1; } | expr '+' expr { $$.ival = $1.ival + $3.ival; } | expr '*' expr { $$.ival = $1.ival * $3.ival; } | '(' expr ')' { $$ = $2; } %% ... • %left: l’opérateur est associatif gauchea+b+c == (a+b)+c • Les opérateurs sont déclarés en ordre • ascendant de priorité: '*' a une précédence sur '+' • Cette grammaire ne spécifie aucune • précédence d’opérateurs • La précédence est spécifiée par%left ou %right Yacc — Précédence des opérateurs La grammaire suivante spécifie explicitement la précédence des opérateurs • '*' a une précédence sur '+' • Les opérateurs sont associatifs à gauche: a*b*c == (a*b)*c expr: term | expr '+' term ; term: factor | term '*' factor ; factor: number | '(' expr ')' ;

  12. Exemple Statement = ... | error ';' ; Saute tout jusqu’au prochain ';' Yacc — Traitement des erreurs Les alternatives ‘error’ Pour certains NTS (EX: Instructions, Expression, ...) l’utilisateur doit spécifier Les alternatives ‘error’ A: ... | ... | error a {...} ; a ... Séquence quelconque de symboles T et NT • Signification: S’il existe une erreur dans A l’analyseur effectue les actions suivantes: • Il dépile des états de la pile jusqu’à l’obtention d’un état dans lequel une action ‘décaler’ avec • l’unité error est valide • ‘Décaler’ error • Il saute les unités d’entrée jusqu’à ce qu’il détecte une séquence d’unités qui peut être • réduite à a ( le sommet de pile contient alors : errora) • Il réduit errora à A et exécute l’action sémantique correspondante

  13. Générateurs de compilateurs Introduction Yacc Lex Coco/R

  14. Utilisation Nous decrivons ici la version C Lex sample.l sample.yy.c include Yacc C-Compiler sample.y sample.tab.c sample.o Versions actuelles flex version GNU de Lex (pour C) http://www.gnu.org/software/flex/ JLex version Java avec légère différence dans la syntaxe d’entrée; incompatible avec Bison ou Byacc http://www.cs.princeton.edu/~appel/modern/java/JLex/ CsLex version C# , dérivé de JLex http://www.cybercom.net/~zbrad/DotNet/Lex Lex — Générateur de scanner Histoire • 1975 développé aux laboratoires Bell • génère un scanner en forme de DFA • A l’origine un outil de Unix, aujourd'hui aussi pour Windows • A l’origine pour C, Aujourd’hui aussi pour Java • Coopère généralement avec Yacc

  15. Exemple de description Lex %{ ... e.g. include directives for token numbers exported by the parser ... %} /* macros */ delim [ \t\n] /* blank, tab, eol */ ws {delim}+ /* {...} ... use of a macro */ letter [A-Za-z] digit [0-9] id {letter} ({letter} | {digit})* number {digit}+ %% /* token declarations described as regular expressions */ {ws} {} /* no action */ if { return IF; } /* constants like IF are imported from the parser */ then { return THEN;} else { return ELSE; } {id} { yylval = storeId(yytext, yyleng); return ID; } {number} { yylval = convert(yytext, yyleng); return number; } < { return yytext[0]; } > { return yytext[0]; } . {} /* . denotes any character */ %% /* semantic routines */ int storeId(char* text, int len) {...} int convert(char* text, int len) {...}

  16. Scanner généré La spécification du scanner est convertie en une fonction int yylex() {...} qui est incluse dans l’analyseur yylex() retourne aussi les attributs d’unités comme variables globales int yylval; /* attribute if the token has a numeric value */ char* yytext; /* token text (attribute of ident, string, ...) */ int yyleng; /* lengh of the token text */ int yylineno; /* line number of the token */ L’analyseur déclare (et exporte) les codes des unités %token IF %token THEN ...

  17. Expressions régulières dans Lex Éléments des expressions régulières abc la chaîne "abc"; tout caractère sauf ()[]{}*+?|^$.\ dénote lui-même . Tout caractère sauf \n (fin de ligne) x* 0 ou plusieurs répétitions de x x+ 1 ou plusieurs répétitions de x x? 0 ou 1 occurrence de x ( occurrence optionnelle) (...|...) pour grouper des alternatives [...] ensemble de tous les caractères entre les crochets (Ex. [A-Za-z0-9$]) {...} Utilise d’une macro ^ ligne début $ ligne fin \udddd caractère en Unicode

  18. Générateurs de compilateurs Introduction Yacc Lex Coco/R

  19. Utilisation main grammaire d’attribut Coco/R parser csc scanner Classes utilisateurs (Ex. Table des symboles Coco/R – Compilateur de compilateur /Descente Récursive Histoire • 1980 développé à l’université de Linz (Rechenberg, Mössenböck) • génère un scanner et un analyseur à partir d’une grammaire d’attribut- scanner comme un DFA- Analyseur sous forme de ‘descente récursive’ • Il existe des versions pour C#, Java, C/C++, Delphi, Modula-2, Oberon, Python, ... • Publié sous GPL: http://www.ssw.uni-linz.ac.at/Research/Projects/Coco/

  20. Exemple: Compilateur pour les Expressions arithmétiques COMPILER Calc /* grammar name = start symbol */ CHARACTERS /* character sets used in token declarations */ digit = '0' .. '9'. tab = '\t'. cr = '\r'. lf = '\n'. TOKENS /* declaration of all tokens which are not literals */ number = digit {digit}. COMMENTS /* declaration of comments */ FROM "//" TO cr lf FROM "/*" TO "*/" NESTED IGNORE tab cr lf /* these characters are ignored as white space */ PRODUCTIONS Calc (. int x; .) = "CALC" Expr<out x> (. System.Console.WriteLine(x); .) . Expr<out int x> (. int y; .) = Term<out x> { '+' Term<out y> (. x = x + y; .) }. Term<out int x> (. int y; .) = Factor<out x> { '*' Factor<out y> (. x = x * y; .) }. Factor<out int x> = number (. x = Convert.ToInt32(t.val); .) | '(' Expr<out x> ')'. END Calc.

  21. Les symboles non terminaux • Les NTS peuvent avoir des attributs d’entrée Attr. formels: Attr réels.: A<int x, char c> = ... . ... A<y, 'a'> ... • Les NTS peuvent avoir des attributs de sortie B<outint x, outint y> = ... . ... B<out z, out n> ... Coco/R — les attributs Les symboles terminaux • Les symboles terminaux n’ont pas d’attribut explicite • Leurs valeurs peuvent être accédées dans les actions sémantiques utilisant les variables suivantes Token t; l’unité la plus récente reconnue Token la; la prochaine unité (lookahead) (non encore reconnue) Exemple Factor<out int x> = number (. x = Convert.ToInt32(t.val); .) class Token { int kind; // token code string val; // token value int pos; // token position in the source text (starting at 0) int line; // token line (starting at 1) int col; // token column (starting at 0) }

  22. Déclarations sémantiques • Apparaissent au début de la spécification du compilateur • Sont utilisées pour déclarer les champs et les méthodes de l’analyseur • Les ‘import’ peuvent aussi être spécifiés COMPILER Sample using System.Collections; static IList myList; static void AddToList (int x) {...} CHARACTERS ... Bien sûr, les actions sémantiques peuvent aussi accéder aux champs et méthodes de classes autre que ceux de l'analyseur. Coco/R — Traitement sémantique Actions sémantiques • code Java entre (. et .) • Peuvent apparaître n’importe où dans les productions • Dans le coté gauche d’une production elles sont considérée comme des déclarations déclaration Term<out int x> (. int y; .) = Factor<out x> { '*' Factor<out y> (. x = x * y; .) }. action sémantique

  23. Coco/R – les méthodes d’analyse Chaque production est traduite en une méthode de l’analyseur Expr<out int x>(. int y; .) = Term<out x> { '+' Term<out y>(. x += y; .) }. devient static void Expr (out int x) { int y; Term(out x); while (la.kind == plus) { Scan(); Term(out y); x += y; } }

  24. Séparateurs faibles Les séparateurs au début d’une itération peuvent être marqués comme Weak (faibles) FormalPars = "(" Param { WEAK ',' Param } ')'. Si le séparateur manque ou est mal écrit, la boucle n'est pas terminée prématurément, mais l'analyseur synchronise avec Premier(Param) Inter Suivant({...}) Inter {eof} Coco/R – Traitement des erreurs syntaxiques L’analyseur utilise la technique des ‘ancres spéciaux’ Point de synchronisation Doivent être marqués par SYNC Statement = SYNC ( Assignment | IfSatement | ... ). if la.kind dans Suivant(SYNC) une erreur est reportée et des unités sont sautées jusqu’à la.kind dans Suivant(SYNC) Inter {eof} Les faux messages d'erreur sont supprimés si moins de 3 unités ont été reconnues depuis la dernière erreur.

  25. Coco/R — Tests de grammaire Test LL(1) Coco/R affiche les avertissements suivants A = a [B] C d | B a. B = a b. C = a [d]. LL1 warning in A: a is start & successor of deletable structure LL1 warning in A: a is start of several alternatives LL1 warning in C: d is start & successor of deletable structure Test de complétude Existe-il une production pour chaque NTS? Test de non-redondance Est-ce que que la grammaire contient des productions non atteintes? Test de Dérivabilité Est-ce que chaque NTS peut être dérivé en une chaîne de symboles terminaux? Test de Non-circularité Y a t-il des NTS qui peuvent être dérivé (directement ou indirectement)en eux-mêmes?

  26. Coco/R — Pragmas (Directives de compilation) • Pragmas sont des symboles terminaux • Qui peuvent apparaître n’importe où dans l’entrée • Qui ne font pas partie de la syntaxe • Qui doivent être traités sémantiquement • Ex. options du compilateur COMPILER X CHARACTERS ... TOKENS ... PRAGMAS PrintOption = "$print". (. option[print] = true; .) DbgOption = "$debug". (. option[debug] = true; .) ... Quand la string $print apparaît dans le texte d’entrée l’action sémantique option[print] = true; est exécutée

  27. Dans les productions Il décrit tout unité qui ne peut être produite par les autres alternatives PlaceHolder = ident | ANY. Tout unité qui n’est pas ident ou eof Tout unité qui n’est pas ".)" ou eof SemAction = "(." { ANY } ".)". Coco/R — le symbole ‘ANY’ Dans la déclaration des ensembles de caractères Il décrit des ensemble de caractères complémentaires CHARACTERS letter = 'A' .. 'Z' + 'a' .. 'z'. noLetter = ANY - letter. ... Tous les caractères qui ne sont pas des lettres

  28. Résolution de conflit par une vérification sémantique Factor = IF (IsCast()) '(' ident ')' Factor /* type cast */ | '(' Expr ')' /* nested expression */ | ... . static boolean IsCast () { Token x = Scanner.Peek(); if (x.kind == _ident) { Symbol s = Tab.Find(x.val); return s.kind == Symbol.Kinds.Type; } else return false; } Coco/R — Résolution des conflits LL(1) Résolution de conflit par un by a multi-symbol lookahead Statement = IF (IsAssignment()) Designator "=" Expr ";" | Designator "(" ActualParams ")" ";" | ... . static boolean IsAssignment () { Token x = la; while (x.kind != _assign && x.kind != _lpar) x = Scanner.Peek(); return x.kind == _assign; } Scanner.Peek() ... Lit les unités sans les enlever de l’entrée Les noms d’unités (_assign, _lpar, ...) sont générés à partir des sections TOKENS

  29. Coco/R — les frames Le scanner et l’analyseur sont générés à partir de frames (fichier texte ordinaire) Ex. Scanner.frame public class Scanner { const char EOL = '\n'; const int eofSym = 0; -->declarations ... static Token NextToken () { while (ignore[ch]) NextCh(); -->scan1 t = new Token(); t.pos = pos; t.col = pos - lineStart + 1; t.line = line; int state = start[ch]; StringBuilder buf = new StringBuilder(16); -->scan2 ... } ... } Coco/R insère le code à ces positions En modifiant les frames le scanner et l’analyseur peuvent être adaptés aux besoins de l’utilisateur (à un certain degré)

  30. Coco/R — Interfaces Scanner public class Scanner { public static void Init (string sourceFileName) {...} public static void Init (Stream s) {...} public static Token Scan () {...} public static Token Peek () {...} public static void ResetPeek () {...} } Parser public class Parser { public static Token t; public static Token la; public static void Parse () {...} public static void SemErr (string msg) {...} } Error message class public class Errors { public static int count = 0; public static string errMsgFormat = "-- line {0} col {1}: {2}"; public static void SynErr (int line, int col, int n); public static void SemErr (int line, int col, int n); public static void Error (int line, int col, string msg); public static void Exception (string msg); }

More Related