300 likes | 457 Views
Lexikálna analýza. LA ako súčasť prekladača. Je prvou časťou prekladača Robí analýzu – na prvej úrovni – zisťuje gramatickú správnosť Robí ďalšie služby podľa požiadavky (i možností) aby sa ďalšia činnosť prekladača zjednodušila Spolupracuje so SA. Úloha LA.
E N D
LA ako súčasť prekladača • Je prvou časťou prekladača • Robí analýzu – na prvej úrovni – zisťuje gramatickú správnosť • Robí ďalšie služby podľa požiadavky (i možností) aby sa ďalšia činnosť prekladača zjednodušila • Spolupracuje so SA
Úloha LA • Nájdenie a rozpoznanie lexikálnych jednotiek • Zakódovanie lexikálnych jednotiek • Vynechanie nepotrebných reťazcov • Výpočet syntetizovaných atribútov lexikálnych jednotiek akoterminálnych symbolov – najčastejšie textový tvar a jeho dĺžku
Vzťak k SA • LA ako samostatná fáza – sekvenčný postup Reťazec znakov ZP Reťazec lexikálnych jednotiek ZP SA LA
Vzťah k SA • Ako podprogram SA – na požiadanie vytvorí a dodá ďalšiu lexikálnu jednotku zo vstupu Požiadavka ďalšieho symbolu Reťazec znakov ZP LA SA Ďalší symbol/LJ ZP
Lexikálne jednotky – zaradenie do tried • Z hľadiska analýzy nie je potrebné poznať všetky konkrétnosti lexikálnych jednotiek – výraz je napr. a+b, 3-(a+b), atď. • Lexikálne jednotky spájame do tried, ktorých počet je pre ľubovolný programovací jazyk pomerne malý: • Číselné a logické hodnoty • Obmedzovače netextového charakteru, ako +, -, :=, / ap. • Obmedzovače textové, ako if, else, do • identifikátory
Model lexikálneho analyzátora • Modelom LA je konečný automat Poznámka: vieme už, že problémy môžu byť s determinizmom. Vieme však, že ku každému nedeterministickému KA existuje ekvivalentný deterministický KA.
Konštrukcia LA • LA konštruujeme z RG, ktorá špecifikuje lexikálne jednotky • Konštrukcia: Nech G = (N, T, P, S) je RG, potom možno skonštruovať KA K = (Q, T, , q0, F) taký, že L(K) = L(G) takto:
Konštrukcia LA Cont. Konštrukcia: Q = N {A}, pričom A N T = T q0 = S F = {S, A} ak S e P ; inak F = { A } : pre všetky a T, B N, C N platí: ak B a P tak A (B, a) ak B aC P tak C (B, a) (A, a) = ø
Jazyk lexikálnych jednotiek • Treba vytvoriť gramatiky – regulárne pre jednotlivé triedy LJ • Zjednodušíme si zápis tým, že symboly písmeno a číslica budú terminály a budú reprezentovať všetky písmená a číslice • Prvky z jednotlivých tried obmedzíme
Gramatiky pre jednotlivé triedy <identifikátor> písmeno | písmeno <zvyšok identifikátora> <zvyšok identifikátora> písmeno | písmeno <zvyšok identifikátora>| číslica | číslica <zvyšok identifikátora> <celé číslo> číslica | číslica <celé číslo> <obmedzovač> +| - |x |/ |; | : <rovná sa>| / <hviezdička> | * <lomeno> <rovná sa> = <hviezdička> * <lomeno> /
Kompozícia gramatík pre triedy • Vytvoríme teraz jednu gramatiku so začiatočným symbolom <lexikálna jednotka> • <lexikálna jednotka> písmeno | písmeno <zvyšok identifikátora>| číslica | číslica <celé číslo>| +| - |x |/ |; | : <rovná sa>| / <hviezdička> |* <lomeno> <zvyšok identifikátora> písmeno | písmeno <zvyšok identifikátora>| číslica | číslica <zvyšok identifikátora> <celé číslo> číslica | číslica <celé číslo> <rovná sa> = <hviezdička> * <lomeno> /
Konštrukcia KA – reprezentácia Stavovým diagramom písmeno | číslica | + | - | x | / | ; písmeno | číslica zvyšok identifikátora písmeno číslica číslica lexikálna jednotka celé číslo K / * hviezdička : = rovná sa / * lomeno
Problémy vytvoreného automatu • Hlavným problémom je jeho nedeterminizmus • Vieme, že existuje ekvivalentný deterministický automat • My ho môžeme vytvoriť „dekompozíciou“ koncového stavu tak, že vytvoríme koncové stavy pre jednotlivé triedy lexikálnych jednotiek • Budeme mať koncové stavy: • zvyšok identifikátora + K, celé číslo + K, hviezdička + K, K
Nový stavový diagram číslica zvyšok identifikátora +K písmeno písmeno číslica lexikálna jednotka celé číslo+K číslica / * hviezdička+K : = rovná sa K / * lomeno + | - | x | ;
Vlastnosti nového automatu Je deterministický, ale: Nemá rovnaký spôsob rozpoznania lexikálnych jednotiek. Podľa definície, reťazec patrí do jazyka, ak ho KA prijme, teda dostane sa do koncovej konfigurácie (qf , e). Teraz však nasledujú lexikálne jednotky „za sebou“, čo treba zobrať do úvahy Interpretácia „prázdneho vstupu“ je taká, že na vstupe je symbol, ktorý „nepatrí“ rozpoznávanej lexikálnej jednotke – prečítali sme „iný“ symbol . Týmto „iným“ symbolom ohodnotíme hranu, ktorou prejdeme do nového koncového stavu – koniec LJ Rozpoznávanie tak „rozšírime“ o jeden krok. Dostaneme nasledujúci automat
Rozpoznávanie postupnosti reťazcov číslica inak zvyšok identifikátora +K písmeno písmeno číslica lexikálna jednotka celé číslo+K inak Koniec LJ číslica inak / hviezdička+K inak * : = rovná sa K / * lomeno + | - | x | ;
Začiatok lexikálnej jednotky • Na prvý pohľad je začiatok lexikálnej jednotky jasný • Ak však lexikálne jednotky nasledujú za sebou – ako je to v prípade programu – situácia nie je taká jasná • Problémom môže byť už zmienený symbol „inak“ • Treba zabezpečiť, aby sme ho „nestratili”
Explicitné a implicitné LJ • Lexikálne jednotky možno rozdeliť na - explicitne definované - implicitne definované • Explicitne definované LJ rozpoznáme po prečítaní jej posledného symbolu (nepotrebujeme teda symbol „inak“) – napr. +, -, :=, ... • Implicitne definované LJ rozpoznáme až po prečítaní symbolu , ktorý jej nepatrí (potrebujeme teda symbol „inak“) – napr. identifikátor, celé číslo, ... • Zjednotenie je cez hranu „inak“ pre všetky LJ
Rozpoznanie kľúčových slov jazyka • Kľúčové slová programovacieho jazyka sú „identifikátory so špeciálnym významom“. • LA ich môže rozpoznať rôznym spôsobom - pomocou tabuľky symbolov, kde ich možno uchovávať - ich predznačením špeciálnym symbolom- zvyčajne apostrof
Model LA – preklad • Ďalšou úlohou LA po rozpoznaní LJ je ich zakódovanie • Zakódovanie LJ je ich zápis v inom jazyku – teda preklad • Do tejto kategórie prác patrí aj uchovanie informácií o LJ, ako ich textový tvar a dĺžka – pomáha nám pri uchovávaní a následnom vyhľadávaní LJ
Triedy LJ • LJ možno rozdeliť do neveľkého počtu tried • Každá trieda reprezentuje LJ, ktoré majú z hľadiska analýzy rovnaký význam • Nami používané LJ - čiastočne rozšírené možno zakódovať takto
Prekladový automat na zakódovanie LJ • Prekladový automat na zakódovanie LJ budeme reprezentovať stavovým diagramom • Ohodnotenie hrán bude mať tvar i/o , kde „i“ bude vstupný symbol, „o“ bude výstupný symbol • Kľúčové slová budú „predznačené“ apostrofom
Stavový diagram KPA e/e l/e s/e e/11 ‘/e kľúčové slovo 1 2 3 e / číslica inak / 1 zvyšok identifikátora +K písmeno / e e / písmeno číslica /e lexikálna jednotka celé číslo+K inak / 2 Koniec LJ e/číslica inak/8 / | e hviezdička+K inak * / 3 : / e = / 9 rovná sa K /| 4 * / e lomeno +/5 | -/6 | x/7| ;/10
Textový tvar a dĺžka LJ • Použijeme prekladovú gramatiku pre kódovanie • Zaujíma nás iba LJ identifikátor • Výstupný symbol označímevs
Prekladová gramatika pre text identifikátora G = ({LJ, ID}, {p, č, inak} {vs}, P, LJ ) P: LJ p ID ID p ID ID č ID ID inak vs PG rozšírime o spracovanie textového tvaru identifikátora a jeho dĺžku Atribúty: d – dĺžka identifikátora tti – textový tvar identifikátora
APG Syntax Sémantika LJ p ID ID.d := 1 ID.tti := p.kód ID p ID ID1.d := ID0.d + 1 ID1.tti := ID0.tti ||p.kód ID č ID ID1.d := ID0.d + 1 ID1.tti := ID0.tti || č.kód ID inak vs vs.d := ID.d vs.tti := ID.tti
Vynechanie nepotrebných symbolov • Ide o komentáre • Reťazce pri zvýšenie čitateľnosti programu