analyse lexicale n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Analyse lexicale PowerPoint Presentation
Download Presentation
Analyse lexicale

Loading in 2 Seconds...

play fullscreen
1 / 22

Analyse lexicale - PowerPoint PPT Presentation


  • 121 Views
  • Uploaded on

Analyse lexicale. Pr ZEGOUR DJAMEL EDDINE Ecole Supérieure d’Informatique (ESI) www.zegour.uuuq.com email: d_zegour@esi.dz. Analyse lexicale Taches d‘un scanner Grammaires Régulières et Automates finis Implémentation des scanners. 2. Saute les caractères non significatifs. blancs

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Analyse lexicale' - lore


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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
analyse lexicale

Analyse lexicale

Pr ZEGOUR DJAMEL EDDINE

Ecole Supérieure d’Informatique (ESI)

www.zegour.uuuq.com

email: d_zegour@esi.dz

slide2

Analyse lexicale

Taches d‘un scanner

Grammaires Régulières et Automates finis

Implémentation des scanners

taches d un scanner

2. Saute les caractères non significatifs

  • blancs
  • Caractères de tabulation
  • Caractères de fin de lignes (CR, LF)
  • Commentaires

Les unités lexicales ont une structure syntaxique

ident = letter { letter | digit }.

number = digit { digit }.

if = "i" "f".

eql = "=" "=".

...

Taches d’un scanner

1. Délivre les symboles terminaux (unités lexicales)

scanner

IF, LPAR, IDENT, EQ, NUMBER, RPAR, ..., EOF

i

f

(

x

=

=

3

)

Source

Unités lexicales

pourquoi la phase lexicale est s par e de la phase syntaxique

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.

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 ";"

)

Les unités lexicales peuvent être decrites à l‘aide de grammaires régulières

(Plus simple et plus efficace que les grammaires à contexte libre)

slide5

Analyse lexicale

Taches d‘un scanner

Grammaires Régulières et Automates finis

Implémentation des scanners

grammaires r guli res

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

Exemple Grammaire pour les identificateurs

Ident = letter { letter | digit }.

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, b des TS

A, B des NTS

A = a.

A = b B.

Autre définition

Une grammaire est dite régulière si elle peut être décrite par une simple non récursive

production EBNF.

exemples

Après substitution de F dans T

T = id { "*" id }.

Après substitution de T dans E

E = id { "*" id } { "+" id { "*" id } }.

La grammaire est régulière

Peut-on transformer la grammaire suivante en une grammaire régulière?

Après substitution de F dans E

E = F { "*" F }.

F = id | "(" 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.

Exemples

Peut-on transformer la grammaire suivante en une grammaire régulière?

E = T { "+" T }.

T = F { "*" F }.

F = id.

limitations des grammaires r guli res

Les structures lexicales sont généralement régulières

Exception:commentaires emboîtés

nom letter { letter | digit }

/* ..... /* ... */ ..... */

Le scanner doit les traiter comme cas

spécial

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.

  • Expressions emboîtées
  • Instructions emboîtées
  • Classes emboîtées

Expr => ... "(" Expr ")" ...

Statement => "do" Statement "while" "(" Expr ")"

Class => "class" "{" ... Class ... "}"

Solution : utilisation des grammaires à contexte libre.

nombres digit { digit }

chaînes "\"" { pas de quote } "\""

Mot-clés letter { letter }

opérateurs ">" "="

expressions r guli res

Exemples

"w" "h" "i" "l" "e" while

letter ( letter | digit )* names

digit+ numbers

Expressions régulières

Autre notation pour les grammaires régulières

Définition

1. e (la chaîne vide) est une expression régulière

2. Un symbole terminal est une expression régulière

3. Si a et b sont des expressions régulières, les expressions suivantes sont régulières:

a b

(a | b)

(a)? e | a

(a)* e | a | aa | aaa | ...

(a)+ a | aa | aaa | ...

automate fini d terministique dfa

Table de transition

d

"fini", car d

Peut être défini

explicitement

letter

digit

s0

s1

error

s1

s1

s1

Définition

  • Un automate fini déterministique est un 5 tuple (S, I, d, s0, F)
  • S Ensemble des états
  • I Ensemble des symboles d‘entrée
  • d: S x I  S Fonction de transition des états
  • s0 État initial
  • F Ensemble des états finaux
Automate Fini Déterministique (DFA)

Peut être utilisé pour analyser les langages réguliers

Exemple

État final

letter

letter

0

1

État initial est 0

par convention

digit

Le langage reconnu par une DFA est

l‘ensemble de toutes les séquences de

symboles pouvant être générées de l‘état

initial vers l‘un des états finaux.

  • Un DFA reconnaît une phrase (sentence)
  • S‘il est dans un état final
  • Et il n‘y a plus de symboles d‘entrée Ou il n‘ y a pas de transition possible
  • avec le prochain symbole d‘entrée
le scanner comme un dfa

Exemple

Entrée:max >= 30

m a x

  • Pas de transition avec " " dans s1
  • ident reconnu

s0

s1

> =

  • Saute les blancs au début
  • Ne s‘arrête pas en s4
  • Pas de transition avec " " dans s5
  • geq reconnu

s0

s5

3 0

  • Saute les blancs au début
  • Pas de transition avec " " dans s2
  • number reconnu

s0

s2

Le Scanner comme un DFA

Le scanner peut être vu comme un grand DFA

" "

letter

letter

0

1

ident

digit

digit

digit

2

number

(

3

lpar

>

=

4

5

gtr

geq

...

Après chaque unité lexicale reconnue le scanner recommence à l‘état initial s0

transformation grammaire r guli re vers dfa

Exemple

Grammaire

Automate

A = a B | b C | c.

B = b B | c.

C = a C | c.

b

c

a

A

B

a

b

c

C

c

stop

Transformation: grammaire régulière vers DFA

Une grammaire régulière peut être transformée en un DFA comme suit

b

A = b C.

A

C

d

A = d.

A

stop

automate fini non d terministique ndfa

Chaque NDFA peut être transformé en un DFA équivalent

H

intNum

digit

A,B,C,D,E,F

H

0

1

2

3

hexNum

hex

digit

Automate Fini Non Déterministique (NDFA)

Exemple

intNum

Non déterministique car

Il y a 2 possibles transitions

avec digit dans s0

intNum = digit { digit }.

hexNum = digit { hex } "H".

digit = "0" | "1" | ... | "9".

hex = digit | "A" | ... | "F".

digit

digit

0

1

digit

H

2

3

hexNum

hex

impl mentation d un dfa variante 1

Exemple pour d

d a b c

0 1 - -

1 - 1 2

2 - - - F

A = a { b } c.

a

c

0

1

2

int[,] delta = { {1, -1, -1}, {-1, 1, 2}, {-1, -1, -1} };

A

b

Cette implémentation pourrait être très inefficace pour un véritable scanner

Implémentation d‘un DFA (Variante 1)

Implémentation de d 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];

impl mentation d un dfa variante 2

en Java c‘est plus fatiguant:

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;

Implémentation d‘un DFA (Variante 2)

a

c

0

1

2

A

b

Coder les états dans le code source

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;

slide16

Analyse lexicale

Taches d‘un scanner

Grammaires Régulières et Automates finis

Implémentation des scanners

interface du scanner

Initialisation du scanner

Scanner.Init(new StreamReader("myProg.zs"));

Lecture des unités lexicales

Token t;

for (;;) {

t = Scanner.Next();

...

}

Interface du Scanner

class Scanner {

static void Init (TextReader r) {...}

static Token Next () {...}

}

unit s lexicales

Exemple de codage pour un langage particulier

Erreur

Classes des unités

Opérateurs et caractères spéciaux

Mot-clés

Fin de fichier

const int

NONE = 0,

IDENT = 1,

NUMBER = 2,

CHARCONST = 3,

BREAK = 29,

CLASS = 30,

CONST = 31,

ELSE = 32,

IF = 33,

NEW = 34,

READ = 35,

RETURN = 36,

VOID = 37,

WHILE = 38,

WRITE = 39,

EOF = 40;

ASSIGN = 17, /* = */

PPLUS = 18, /* ++ */

MMINUS = 19, /* -- */

SEMICOLON = 20, /* ; */

COMMA = 21, /* , */

PERIOD = 22, /* . */

LPAR = 23, /* ( */

RPAR = 24, /* ) */

LBRACK = 25, /* [ */

RBRACK = 26, /* ] */

LBRACE = 27, /* { */

RBRACE = 28, /* } */

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, /* || */

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)

}

impl mentation des scanner

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()

  • ch = prochain caractère d‘entrée
  • retourne EOF si fin de fichier
  • incrémente line et col

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; }

}

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

method next
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

autres m thodes

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 lavaleur dans t.val.Si débordement: Erreur
  • t.kind = Token.NUMBER;
  • A la fin ch contient le premier caractère après le nombre
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
consid rations d efficacit

Faire attention à la programmation

Utiliser les variables globales :

Ex.: ch est global et non un paramètre de NextCh()

Pour les grands fichiers d‘entrée, c‘est judicieux d‘utiliser des lectures bufférisées

Stream file = new FileStream("MyProg.zs");

Stream buf = new BufferedStream(file);

TextReader r = new StreamReader(buf);

Scanner.Init(r);

Considérations d‘efficacité

Taille d‘un programme modeste

Aux environs de 1000 instructions

 environ 6000 unités

 environ 60000 caractères

La phase lexicale consomme un temps important

prend 20-30% du temps total de compilation