Lexikální analýza Miroslav Beneš Dušan Kolář
Rozhraní lexikálního analyzátoru Lexikální analýza 2
Úkoly Čtení zdrojového textu Sestavování symbolů Odstranění mezer a poznámek Normalizace symbolů (velká/malá písmena, spec. znaky,...) Interpretace direktiv překladače Uchovávání informací pro hlášení chyb Zobrazení protokolu o překladu Lexikální analýza 3
Proč řešit lexikální analýzu samostatně? Jednodušší návrh překladače Konvence pro mezery a poznámky Vyšší efektivita Specializované algoritmy Lepší přenositelnost Zvláštnosti vstupní abecedy??( = [ Lexikální analýza 4
Základní pojmy Lexém slovo nad abecedou Kategorie symbolů identifikátor, číslo, relační operátor, levá závorka,... Atributy symbolu řetězec, hodnota, kód operátoru,... Reprezentace symbolu dvojice (kategorie, atribut) Lexikální analýza 5
Příklady lexikálních symbolů Symbol Lexém Vzor const const const relation <, <=,, >= <> id {ltr}({ltr} {dig})* pi, D2 num {dig}+ 0, 123 Lexikální analýza 6
Reprezentace symbolů // kategorie symbolů enum Symbol { IdSym, NumSym, RelOpSym, DotSym,... }; // kategorie operátorů enum Oper { LthOp, GthOp, LeqOp,... }; // atributy symbolů union LexAttr { char* id; int num; Oper relop;... }; // reprezentace lexikálního symbolu struct Token { Symbol sym; // kategorie LexAttr attr; // atribut }; Lexikální analýza 7
Problémy se zdrojovým jazykem Pevný/volný formát (FORTRAN) 12 X=7 * +12*K C poznámka Zpracování mezer (FORTRAN, Basic) DO5I=1.25 / DO5I=1,25 Klíčová slova (PL/I) IF THEN THEN THEN=ELSE; ELSE ELSE=THEN Lexikální analýza 8
Příklad 1 INTEGER FUNCTIONA 2 PARAMETER(A=6,B=2) 3 IMPLICIT CHARACTER*(A-B)(A-B) 4 INTEGER FORMAT(10),IF(10),DO9E1 5 100 FORMAT(4H)=(3) 6 200 FORMAT(4 )=(3) 7 DO9E1=1 8 DO9E1=1,2 9 IF(X)=1... Lexikální analýza 9
Příklad (pokr.) 10 IF(X)H=1 11 IF(X)300,200 12 300 CONTINUE 13 END C this is a comment $FILE(1) 14 END Lexikální analýza 10
Specifikace symbolů Popis běžným jazykem identifikátor je posloupnost písmen a číslic začínající písmenem Regulární (lineární) gramatika I -> p X X-> p X c X p c Regulární výrazy a definice p (p c)* Lexikální analýza 11
Specifikace symbolů Graf přechodů konečného automatu (syntaktický graf) Lexikální analýza 12
Specifikace symbolů Lexikální symboly lze obvykle popsat regulárními jazyky (typ 3) Co nedokážeme popsat? Zanořené konstrukce (závorky) Opakované konstrukce {wcw w {a,b}*} Zadaný počet opakování nha 1 a 2 a n (FORTRAN) Lexikální analýza 13
Regulární výrazy nad Σ RE ε označuje {ε} Je-li a Σ, pak a označuje {a} (prázdný řetězec) Je-li a,b,c, Σ, pak [abc ] označuje množinu {a, b, c, } [aeiouy] [a-za-z] [^0-9] všechno kromě [0-9] Lexikální analýza 14
Regulární výrazy Jsou-li s, t reg. výrazy označující jazyky L(s) a L(t), pak (s) (t) L(s) L(t) (s) (t) L(s) L(t) (s)* (L(s))* (s)+ (L(s))+ = L(s) (L(s))* (s)? L(s) {ε} (s) L(s) Lexikální analýza 15
Příklad [A-Z]([A-Z] [0-9])* [A-Z][A-Z0-9]* [0-9]+.[0-9]+(E[-+]?[0-9]+)? [0-9]+E[-+]?[0-9]+ Lexikální analýza 16
Regulární definice Pojmenované regulární výrazy d 1 -> r 1 d 2 -> r 2... d n -> r n různá reg. výrazy nad jména Σ {d 1, d 2,, d i-1 } Lexikální analýza 17
Regulární definice letter -> [A-Za-z] digit -> [0-9] id -> letter (letter digit)* Použití: konstruktory lex. analyzátorů Lexikální analýza 18
Konečné automaty (Q, Σ, f, q 0, F) Q konečná množina stavů Σ - vstupní abeceda f přechodová funkce q 0 počáteční stav F množina koncových stavů f: Q x (Σ {e}) -> 2 Q f: Q x Σ -> Q rozšířený NKA DKA Lexikální analýza 19
Konečné automaty desítkové číslo šestnáctkové číslo Lexikální analýza 20
Konečné automaty NKA Lexikální analýza 21
Konečné automaty deterministický konečný automat Lexikální analýza 22
Algoritmy pro transformaci Reg. gramatika konečný automat korespondence pravidel gramatiky a přechodové funkce Reg. výraz konečný automat skládání primitivních KA, převod na DKA, minimalizace stromová reprezentace důležité pro konstruktory lex. analyzátorů Lexikální analýza 23
Algoritmy pro transformaci Konečný automat reg. výraz soustava algebraických rovnic X = a X + b X = a* b derivace reg. výrazu Lexikální analýza 24
Konečný automat pro lexikální analýzu Zpracování začíná vždy prvním dosud nezpracovaným znakem ze vstupu Zpracování končí, je-li automat v koncovém stavu a pro další vstupní znak již neexistuje žádný přechod (maximal match): 123 není 12 následované 3 Není-li v nekoncovém stavu přechod možný, vrací se automat do posledního dosaženého koncového stavu nebo je chyba: < <= << 1. 1.2 1..5 Lexikální analýza 25
Speciální případy akce po přijetí symbolu samostatný koncový stav pro každou kategorii výpočet hodnot atributů z lexému klíčová slova koncový stav pro každé klíčové slovo mnoho stavů obvykle jako id, pak následuje rozlišení tabulkou klíč. slov Lexikální analýza 26
Speciální případy komentáře uzavřená cesta procházející poč. stavem diagnostika neukončený komentář dokumentační komentář Javadoc zanořené komentáře znakové řetězce escape sekvence \n ukončení řádku v řetězci je obvykle chyba Unicode Lexikální analýza 27
Implementace lexikálního analyzátoru Přímá Efektivita na úkor složitosti návrhu Stav je reprezentován pozicí v programu Simulace konečného automatu Vhodné spíš pro konstruktory Využití konstruktoru Snadná modifikovatelnost Především v počátečních fázích implementace Lexikální analýza 28
Přímá implementace char text[256]; int leng, ival; int lex(void) { int ch; START: while((ch=getchar())== ) ; /* odstranění mezer */ Lexikální analýza 29
Přímá implementace if( isalpha(ch) ) { leng = 0; do { text[leng++] = ch; } while( isalnum(ch=getchar()) ); text[leng] = \0 ; ungetc(ch,stdin); return(ident); } Lexikální analýza 30
Přímá implementace else if( isdigit(ch) ) { ival = 0; do { ival = 10*ival+(ch- 0 ); } while( isdigit(ch=getchar()) ); ungetc(ch,stdin); return(num); } Lexikální analýza 31
Přímá implementace } else if (ch== { ) { while( (ch=getchar())!= } && ch!=eof); if( ch==eof ) { error( Missing end of comment ); return(eof); } goto START; } else return(ch); /* ostatní znaky */ Lexikální analýza 32
Přímá implementace getchar() čte znaky ze vstupu udržuje aktuální číslo řádku kopie zdrojového textu do protokolu správa vyrovnávacích pamětí makrogenerátor (např. C, C++) ungetc() vrací zpět jeden nebo více znaků Java: java.io.pushbackinputstream Lexikální analýza 33
Implementace konečného automatu Tabulka + Přechodová funkce + Interpret výhodné jako výstup konstruktoru Přímý přepis do programu Lexikální analýza 34
Implementace konečného automatu static int state; int next(int newstate) { state = newstate; return getchar(); } int lex(void) { int ch = next(0); Lexikální analýza 35
Implementace konečného automatu for(;;) switch(state) { case 0: if (ch== ) ch = next(0); else if( isalpha(ch) ) { leng = 0; text[leng]=ch; ch = next(1); } Lexikální analýza 36
Implementace konečného automatu /* case 0: */ else if (isdigit(ch)) { ival = ch- 0 ; ch = next(2); } else if (ch== { ) ch = next(3); else return(ch); break; Lexikální analýza 37
Implementace konečného automatu case 1: if (isalnum(ch)) { } text[++leng] = ch; ch = next(1); else { } text[++leng] = \0 ; unget(ch,stdin); return(ident); break; Lexikální analýza 38
Implementace konečného automatu Lexikální analýza 39
Implementace konečného automatu } } case 3: if (ch==eof) { error( Missing end of comment ); return(eof); } else if (ch== } ) ch = next(0); else ch = next(3); break; Lexikální analýza 40
Konstruktor LEX / FLEX %{ #include <stdlib.h> #define IDENT 256 #define NUM 257 int yyival; %} Lexikální analýza 41
Konstruktor LEX / FLEX space [ \t\n] ws {space}+ \{[^}]*\} letter [A-Za-z] digit [0-9] id {letter}({letter} {digit})* number {digit}+ %% Lexikální analýza 42
Konstruktor LEX / FLEX {ws} {/* no action, no return */} {id} return(ident); {number} { yyival=atoi(yytext); return(num); }. return(yytext[0]); Lexikální analýza 43