430 likes | 519 Views
Lexikální analýza. Miroslav Beneš Dušan Kolář. Rozhraní lexikálního analyzátoru. Ú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
E N D
Lexikální analýza Miroslav Beneš Dušan Kolář
Rozhraní lexikálního analyzátoru Lexikální analýza
Ú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
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
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, ... • Reprezentacesymbolu – dvojice (kategorie, atribut) Lexikální analýza
Příklady lexikálních symbolů Lexikální analýza
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
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
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
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
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
Specifikace symbolů • Graf přechodů konečného automatu • (syntaktický graf) Lexikální analýza
Specifikace symbolů • Lexikální symboly lze obvykle popsatregulárnímijazyky(typ 3) • Co nedokážeme popsat? • Zanořené konstrukce (závorky) • Opakované konstrukce {wcw|w{a,b}*} • Zadaný počet opakování • nHa1a2…an (FORTRAN) Lexikální analýza
Regulární výrazy nad • RE označuje {} (prázdný řetězec) • Je-li a, pak aoznačuje {a} • 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
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
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
Regulární definice • Pojmenované regulární výrazy • d1 -> r1 • d2 -> r2 • ... • dn -> rn • různáreg. výrazy nadjména {d1, d2,…, di-1} Lexikální analýza
Regulární definice • letter -> [A-Za-z] • digit -> [0-9] • id -> letter (letter | digit)* • Použití:konstruktory lex. analyzátorů Lexikální analýza
Konečné automaty • (Q, , f, q0, F) • Q – konečná množina stavů • - vstupní abeceda • f – přechodová funkce • q0 – počáteční stav • F – množina koncových stavů • f: Q x ( {e}) -> 2Qrozšířený NKA • f: Q x -> Q DKA Lexikální analýza
Konečné automaty desítkovéčíslo šestnáctkové číslo Lexikální analýza
Konečné automaty NKA Lexikální analýza
Konečné automaty deterministický konečný automat Lexikální analýza
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
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
Konečný automatpro 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
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
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
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
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
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
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
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
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
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
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
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
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
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
Implementace konečného automatu Lexikální analýza
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
Konstruktor LEX / FLEX %{ #include <stdlib.h> #define IDENT 256 #define NUM 257 int yyival; %} Lexikální analýza
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
Konstruktor LEX / FLEX {ws} {/* no action, no return */} {id} return(IDENT); {number} { yyival=atoi(yytext); return(NUM); } . return(yytext[0]); Lexikální analýza