PROGRAMOVACÍ JAZYKY A PŘEKLADAČE REALIZACE PŘEKLADAČE I 2011 Jan Janoušek BI-PJP Evropský sociální fond Praha & EU: Investujeme do vaší budoucnosti
Programová realizace DKA typedef enum {q0, q1,... qn, Chyba Stavy; typedef enum {a1, a2,... am, Jiny, Konec Vstupy; const int KoncStav[] = {... ; Vstupy Vstup; const Stavy TabPrech[][Jiny+1] = { {..., {...,... {... ; void CtiVstup(void) /* Přečte jeden vstupní symbol a uloží jej do proměnné Vstup. Obsahuje-li vstupní řetěz nedovolený symbol, do Vstup se uloží Jiny. Při dosažení konce vstupního řetězce se do Vstup uloží Konec. */ {... int Automat(void) { Stavy stav = q0; CtiVstup(); while (Vstup!= Konec && stav!= Chyba) { stav = TabPrech[stav][Vstup]; CtiVstup(); return KoncStav[stav];
Příklad: identifikátory a celá čísla Programová realizace DKA typedef enum {Start,Ident,Cislo,Chyba Stavy; typedef enum {Pismeno,Cislice,Jiny,Konec Vstupy; const int KoncStav[] = {0,1,1,0; Vstupy Vstup; const Stavy TabPrech[][Jiny+1] = { /* Pismeno Cislice Jiny */ /* Start */ { Ident, Cislo, Chyba, /* Ident */ { Ident, Ident, Chyba, /* Cislo */ { Chyba, Cislo, Chyba ;
Reprezentace stavu místem v programu I Přechodový diagram budeme chápat jako speciální formu vývojového diagramu Stavům automatu budou odpovídat místa v programu označená návěštími. Není-li uzel q koncový a vedou-li z něj hrany ohodnocené symboly a1, a2,...,resp. an do uzlů p1, p2,... resp. pn, pak příkaz označený návěštím q bude mít tvar: q: case a1: CtiVstup(); goto p1; case a2: CtiVstup(); goto p2;... case an: CtiVstup(); goto pn; default: return 0;
Reprezentace stavu místem v programu I Je-li uzel q koncový a vedou-li z něj hrany ohodnocené symboly a1, a2,..., resp. an do uzlů p1, p2,..., resp. pn, pak příkaz označený návěštím q bude mít tvar: q: case a1: CtiVstup(); goto p1; case a2: CtiVstup(); goto p2;... case an: CtiVstup(); goto pn; case Konec: return 1; default: return 0;
Reprezentace stavu místem v programu I Příklad: identifikátory a celá čísla typedef enum {Pismeno,Cislice,Jiny,Konec Vstupy; Vstupy vstup; void CtiVstup(void) /* stejná definice jako v příkl. 2.13 */ {... int Automat(void) { CtiVstup(); Start: case Pismeno: CtiVstup(); goto Ident; case Cislice: CtiVstup(); goto Cislo; default: return 0;
Reprezentace stavu místem v programu I Ident: case Pismeno: case Cislice: CtiVstup(); goto Ident; case Konec: return 1; default: return 0; Cislo: case Cislice: CtiVstup(); goto Cislo; case Konec: return 1; default: return 0;
Reprezentace stavu místem v programu II /*q*/ while (Vstup == a) CtiVstup(); case a1: CtiVstup(); /*q1*/ Q1... case an: CtiVstup(); /*qn*/ Qn case Konec: return 1; _/* jen je-li q koncový stav default: return 0;
Reprezentace stavu místem v programu II Příklad: identifikátory a čísla int Automat(void) { CtiVstup(); /*Start*/ case Pismeno: CtiVstup(); /*Ident*/ while (Vstup==Pismeno Vstup==Cislice) CtiVstup(); case Konec: return 1; default: return 0;
Reprezentace stavu místem v programu II case Cislice: CtiVstup(); /*Cislo*/ while (Vstup==Cislice) CtiVstup(); case Konec: return 1; default: return 0; default: return 0;
Konečný překladový automat Ke každému přechodu může být přidružen výstupní symbol z množiny výstupních symbolů D Výstupní funkce: zobrazení z Q x T do D {ε Konečný překladový automat realizuje formální překlad Příklad: vstup: posloupnost nul a jedniček zakončená tečkou výstup: kopie vstupu s doplněním jedničky nebo nuly tak, aby celkový počet jedniček byl sudý
Místo výstupních symbolů akční symboly Neformální překlad: výsledkem překladu není posloupnost výstupních symbolů, ale hodnota určitého typu K přechodům přiřadíme akční symboly označující akce Příklad: automat modelující proceduru, která přečte celočíselnou konstantu z jazyka C a vrátí odpovídající hodnotu typu int 951 dekadický zápis 025 osmičkový zápis 0x3A hexadecimální zápis Vstupní abeceda: n 0 o 1.. 7 d 8, 9 h A.. F, a.. f x X, x
Překlad celočíselné konstanty Přechodový diagram konečného automatu: Význam akčních symbolů int Zaklad, Hodnota, HodnC; A1: Zaklad = 8; Hodnota = 0; A2: Zaklad = 16; A3: Hodnota = Zaklad * Hodnota + HodnC; A4: Zaklad =10; Hodnota = HodnC;
Realizace překladového automatu I Příklad: výpočet hodnoty celočíselné konstanty typedef enum {q0,q1,q2,q3,q4,q5,chyba Stavy; typedef enum {n,o,d,h,x,jiny,konec Vstupy; const int KoncStavy[] = { /*q1,q3,q4,q5*/ 0,1,0,1,1,1,0 ; Vstupy Vstup; int HodnC; int Hodnota; int Zaklad; void A1(void) {Zaklad=8; Hodnota=0; void A2(void) {Zaklad=16; void A3(void) {Hodnota=Zaklad*Hodnota+HodnC; void A4(void) {Zaklad=10; Hodnota=HodnC; void nic(void) {
Realizace překladového automatu I const Stavy TabPrech[][Jiny+1] = { /* n o d h x Jiny */ /*q0*/ {q1, q5, q5, Chyba,Chyba,Chyba, /*q1*/ {q4, q4, Chyba,Chyba,q2, Chyba, /*q2*/ {q3, q3, q3, q3, Chyba,Chyba, /*q3*/ {q3, q3, q3, q3, Chyba,Chyba, /*q4*/ {q4, q4, Chyba,Chyba,Chyba,Chyba, /*q5*/ {q5, q5, q5, Chyba,Chyba,Chyba ; const void (*TabAkci[][Jiny+1])(void) = { /* n o d h x Jiny */ /*q0*/ {A1, A4, A4, nic,nic,nic, /*q1*/ {A3, A3, nic,nic,a2, nic, /*q2*/ {A3, A3, A3, A3, nic,nic, /*q3*/ {A3, A3, A3, A3, nic,nic, /*q4*/ {A3, A3, nic,nic,nic,nic, /*q5*/ {A3, A3, A3, nic,nic,nic ;
Realizace překladového automatu I void CtiVstup(void) { int znak; znak = getchar(); if (znak<=' ') Vstup = Konec; else if (znak=='0') {Vstup = n; HodnC = 0; else if (znak >= '1' && znak <= '7') {Vstup = o; HodnC = znak - '0'; else if (znak == '8' znak == '9') {Vstup = d; HodnC= znak - '0'; else if (znak >= 'a' && znak <= 'f') {Vstup = h; HodnC = znak - 'a' + 10; else if (znak >= 'A' && znak <= 'F') {Vstup = h; HodnC = znak - 'A' + 10; else if (znak == 'x' znak == 'X') Vstup = x; else Vstup = Jiny;
Realizace překladového automatu I int Automat(int *vysl) { Stavy stav = q0; CtiVstup(); while (Vstup!= Konec && stav!= Chyba) { TabAkci[stav][Vstup](); stav = TabPrech[stav][Vstup]; CtiVstup(); *vysl = Hodnota; return KoncStavy[stav];
Realizace překladového automatu II /*q*/ while (Vstup == a) {A; CtiVstup(); case a1: A1; CtiVstup(); /*q1*/ Q1... case an: An; CtiVstup(); /*qn*/ Qn case Konec: return 1; /* když q je konc. Stav */ default: return 0;
Realizace překladového automatu II Příklad: výpočet hodnoty celočíselné konstanty typedef enum {n,o,d,h,x,jiny,konec Vstupy; Vstupy Vstup; int HodnC; void CtiVstup(void) {... int Automat(int *vysl) { int zakl, hodn; CtiVstup(); /*q0*/
Realizace překladového automatu II case n: /*A1*/ zakl = 8; hodn = 0; CtiVstup(); /*q1*/ case x: /*A2*/ zakl = 16; CtiVstup(); /*q2*/ case n: case o: case d: case h: /*A3*/ hodn = zakl * hodn + HodnC; CtiVstup(); /*q3*/ while (Vstup==n Vstup==o Vstup== d Vstup==h) { /*A3*/ hodn = zakl * hodn + HodnC; CtiVstup(); case Konec: *vysl = hodn; return 1; default: return 0; default: return 0; case n: case o:...
Realizace překladového automatu II case o: case d: /*A4*/ zakl = 10; hodn = HodnC; CtiVstup(); /*q5*/ while (Vstup==n Vstup==o Vstup==d) { /*A3*/ hodn = zakl * hodn + HodnC; CtiVstup(); case Konec: *vysl = hodn; return 1; default: return 0; default: return 0;