GENEROVÁNI KÓDU jazyk Mila

Podobné dokumenty
PROGRAMOVACÍ JAZYKY A PŘEKLADAČE LEXIKÁLNÍ ANALÝZA

PROGRAMOVACÍ JAZYKY A PŘEKLADAČE REALIZACE PŘEKLADAČE I

Virtuální počítač. Uživatelský program Překladač programovacího jazyka Operační systém Interpret makroinstrukcí Procesor. PGS K.

2) Napište algoritmus pro vložení položky na konec dvousměrného seznamu. 3) Napište algoritmus pro vyhledání položky v binárním stromu.

Generování vnitřní reprezentace programu

Konstruktory překladačů

Programovací jazyk Pascal

GENEROVÁNÍ KÓDU 9. SHRNUTÍ - PŘÍKLAD POSTUPU PŘEKLADU VSTUPNÍHO PROGRAMU (ZA POUŽITÍ DOSUD ZNÁMÝCH TECHNIK)

Základní pojmy. Úvod do programování. Základní pojmy. Zápis algoritmu. Výraz. Základní pojmy

Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15

Automaty a gramatiky(bi-aag) Formální překlady. 5. Překladové konečné automaty. h(ε) = ε, h(xa) = h(x)h(a), x, x T, a T.

PROGRAMOVACÍ JAZYKY A PŘEKLADAČE STRUKTURA PŘEKLADAČE

Vyučovací hodina. 1vyučovací hodina: 2vyučovací hodiny: Opakování z minulé hodiny. Procvičení nové látky

Poslední aktualizace: 14. října 2011

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Syntaktická analýza. Implementace LL(1) překladů. Šárka Vavrečková. Ústav informatiky, FPF SU Opava

Automaty a gramatiky(bi-aag) Motivace. 1. Základní pojmy. 2 domácí úkoly po 6 bodech 3 testy za bodů celkem 40 bodů

Programovací jazyk. - norma PASCAL (1974) - implementace Turbo Pascal, Borland Pascal FreePascal Object Pascal (Delphi)

PROGRAMOVACÍ JAZYKY A PŘEKLADAČE LL SYNTAKTICKÁ ANALÝZA DOKONČENÍ, IMPLEMENTACE.

Západočeská univerzita v Plzni Dokumentace překladače PL/0 v PHP Předmět KIV/FJP

Základy programování (IZP)

Obsah přednášky. programovacího jazyka. Motivace. Princip denotační sémantiky Sémantické funkce Výrazy Příkazy Vstup a výstup Kontinuace Program

PŘETĚŽOVÁNÍ OPERÁTORŮ

Úvod do programovacích jazyků (Java)

Zápis programu v jazyce C#

Úvod z historie. Kompilátory. Kompilace / Kompilátor Compile / Compiler. Pojem kompilátoru. Úvod z historie

PROGRAMOVACÍ JAZYKY A PŘEKLADAČE PŘEKLADY TYPICKÝCH JAZYKOVÝCH KONSTRUKCÍ PROGRAMOVACÍCH JAZYKŮ.

Programování v C++ 1, 1. cvičení

Čtvrtek 8. prosince. Pascal - opakování základů. Struktura programu:

Sémantika Tabulka symbolů Intermediální kód Typová kontrola, přetypování Statická a dynamická sémantika. Sémantická analýza.

Úvod do programování - Java. Cvičení č.4

Abstraktní třídy, polymorfní struktury

Lexikální analýza. Rozhraní lexikálního analyzátoru. Miroslav Beneš Dušan Kolář. M. Beneš, D. Kolář: Lexikální analýza 1. Lexikální analýza 2

Lexikální analýza. Miroslav Beneš Dušan Kolář

Implementace LL(1) překladů

Náznak ukázky syntaxe a sémantiky pro projekt. 1 Syntaktické prvky. Poslední aktualizace: 8.

Výrazy, operace, příkazy

Soubory. Hung Hoang Dieu. Department of Mathematics Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague 1 / 7

Lexikální analýza Teorie programovacích jazyků

Algoritmizace. Cíle předmětu

Uplatnění metod na zvolený jazyk

Základy programování (IZP)

Bezkontextové gramatiky. Z. Sawa (VŠB-TUO) Úvod do teoretické informatiky 6. května / 49

Základy programování (IZP)

PODPROGRAMY PROCEDURY A FUNKCE

Funkce, intuitivní chápání složitosti

- znakové konstanty v apostrofech, např. a, +, (znak mezera) - proměnná zabírá 1 byte, obsahuje kód příslušného znaku

3. přednáška. Obsah: Řídící struktury sekvence, if-else, switch, for, while, do-while. Zpracování posloupnosti

Jazyk C++, některá rozšíření oproti C

Martin Flusser. Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague. December 7, 2016

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) Fakulta elektrotechniky a informatiky Katedra softwarových technologií

- speciální symboly + - * / =., < > <> <= >= a další. Klíčová slova jsou chráněnými útvary, které nelze použít ve významu identifikátorů.

Datové struktury. alg12 1

for (i = 0, j = 5; i < 10; i++) { // tělo cyklu }

Logické operace. Datový typ bool. Relační operátory. Logické operátory. IAJCE Přednáška č. 3. může nabýt hodnot: o true o false

dovolují dělení velkých úloh na menší = dekompozice

Semestrální práce z předmětu Teorie programovacích jazyků

Implementace aritmetického stromu pomocí směrníků

Obsah přednášky. 12. Dokumentace zdrojového kódu Tvorba elektronické dokumentace UML. Co je diagram tříd. Ing. Ondřej Guth

NPRG030 Programování I, 2010/11

NPRG030 Programování I RNDr.Tomáš Holan, Ph.D. 4.patro, č

Výrazy, operace, příkazy

Řídicí struktury. alg3 1

Ukazka knihy z internetoveho knihkupectvi

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Maturitní otázky z předmětu PROGRAMOVÁNÍ

NPRG030 Programování I, 2016/17 1 / :58:13

Struktura programu v době běhu

PREPROCESOR POKRAČOVÁNÍ

Interpret jazyka IFJ2011

NPRG030 Programování I, 2015/16 1 / :25:32

Jazyk C++ I. Šablony

14. Složitější konstrukce

Základy jazyka C# Obsah přednášky. Architektura.NET Historie Vlastnosti jazyka C# Datové typy Příkazy Prostory jmen Třídy, rozhraní

Algoritmizace a programování

Odvozené a strukturované typy dat

Algoritmizace a programování

Jazyk C++ I. Polymorfismus

Úvod do programování

BI-PA1 Programování a algoritmizace 1, ZS Katedra teoretické informatiky

type Obdelnik = array [1..3, 1..4] of integer; var M: Obdelnik;

O datových typech a jejich kontrole

Rekurzivní algoritmy

Prezentace a vysvětlení programového prostředí NXC

Martin Flusser. Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague. October 17, 2016

Správné vytvoření a otevření textového souboru pro čtení a zápis představuje

EVROPSKÝ SOCIÁLNÍ FOND. Úvod do PHP PRAHA & EU INVESTUJEME DO VAŠÍ BUDOUCNOSTI

Reprezentace dat v informačních systémech. Jaroslav Šmarda

ALGORITMIZACE A PROGRAMOVÁNÍ

Identifikátory označují objekty v programu používané (proměnné, typy, podprogramy).

Paměť počítače. alg2 1

Příkazové skripty Procedurální jazyky Lua a ostatní

Programování v jazyce JavaScript

Algoritmy I. Cvičení č. 2, 3 ALGI 2018/19

Algoritmizace prostorových úloh

Programování v C++ 2, 4. cvičení

VÝUKOVÝ MATERIÁL. Bratislavská 2166, Varnsdorf, IČO: tel Číslo projektu

Základní způsoby: -Statické (přidělění paměti v čase překladu) -Dynamické (přiděleno v run time) v zásobníku na haldě

Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague

Implementace seznamů do prostředí DELPHI pomocí lineárního seznamu

Transkript:

Czech Technical University in Prague Faculty of Information Technology Department of Theoretical Computer Science GENEROVÁNI KÓDU jazyk Mila Jan Janoušek Evropský sociální fond. Praha & EU: Investujeme do vaší budoucnosti

Příklad programu Příklad implementace programovacího jazyka (Mila) vypocet nejvetsiho spolecneho delitele const a = 84, b = 36; var x, y; begin x := a; y := b; while x <> y do if x > y then x:= x - y y:= y - x; write a; write b; write x; end 1 EBNF program = deklarace složený-příkaz deklarace = 'const' identifikátor '=' 'číslo' ',' identifikátor '=' 'číslo' ';' 'var' identifikátor ',' identifikátor ';' složený-příkaz = 'begin' příkaz ';' příkaz 'end' příkaz = identifikátor-proměnné ':=' výraz 'write' výraz 'if' podmínka 'then' příkaz ['' příkaz] 'while' podmínka 'do' příkaz složený-příkaz ε podmínka = výraz ('=' '<>' '<' '>' '<=' '>=') výraz výraz = ['-'] term ('+' '-') term term = faktor ('*' '/') faktor faktor = identifikátor-proměnné identifikátor-konstanty číslo '(' výraz ')' identifikátor-proměnné = identifikátor identifikátor-konstanty = identifikátor 2 Lexikální elementy lexikální-element = identifikátor číslo spec-symbol spec-symbol = '+' '-' '*' '/' '<' '>' '<=' '>=' ',' ';' ':=' klíčové-slovo klíčové-slovo = 'var' 'const' 'begin' 'end' 'if' 'then' '' 'while' 'do' 'write' identifikátor = písmeno písmeno číslice číslo = číslice číslice písmeno = 'A' 'B'... 'Z' 'a' 'b'... 'z' číslice = '0' '1' '2' '3' '4' '5' '6 zásobník vrch zásobníku paměť proměnných čítač instrukcí Zásobníkový počítač z : array [0..maxz] of integer v : integer m : array [0..maxm] of integer ci : integer typ operand význam instrukce provedení instrukce instr. TC n uložení hodnoty na zásobník v := v + 1; z[v] := n TA a uložení adresy na zásobník v := v + 1; z[v] := a DR dereference z[v] := m[z[v]] BOP op binární operace v := v-1; z[v] := z[v] op z[v+1] UNM unární minus z[v] := -z[v] ST přiřazení m[z[v-1]] := z[v]; v := v 2 WRT výstup hodnoty write(z[v]); v := v 1 JU adr nepodmíněný skok ci := adr IFJ adr podmíněný skok b := z[v]; v := v-1; if b=0 then ci := adr STOP ukončení programu 3 4

operátor symb. označení číselný kód + Plus 0 - Minus 1 * Times 2 / Divide 3 = Eq 4 <> NotEq 5 < Less 6 > Greater 7 <= LessOrEq 8 >= GreaterOrEq 9 Příklad const a = 84, b = 36; var x, y; adresa x je 0, adresa y je 1 begin 0: TA 0 x := a; 1: TC 84 2: ST 3: TA 1 y := b; 4: TC 36 5: ST 6: TA 0 while x <> y do 7: DR 8: TA 1 9: DR 10: BOP 5 11: IFJ 34 12: TA 0 if x > y then 13: DR 14: TA 1 15: DR 16: BOP 7 17: IFJ 26 18: TA 0 x := x - y 5 6 19: TA 0 20: DR 21: TA 1 22: DR 23: BOP 1 24: ST 25: JU 33 26: TA 1 y := y - x; 27: TA 1 28: DR 29: TA 0 30: DR 31: BOP 1 32: ST 33: JU 6 34: TC 84 write a; 35: WRT 36: TC 36 write b; 37: WRT 38: TA 0 write x; 39: DR 40: WRT 41: STOP end 7 Interpret Specifikace: enum TypInstr TA, TC, BOP, UNM, DR, ST, IFJ, JU, WRT, STOP ; enum Operator Plus, Minus, Times, Divide, Eq, NotEq, Less, Greater, LessOrEq, GreaterOrEq ; void Run(); Implementace: struct Instr TypInstr typ; int opd; ; enum MaxZas = 100, MaxProm = 100, MaxProg = 200; static int z[maxzas]; // zasobnik static int v; // vrchol zasobniku static int m[maxprom]; // pamet promennych static Instr p[maxprog]; // pamet programu; static int ic; // citac instrukci 8

Interpret void Run() Instr instr; printf("\ninterpretace programu\n"); ic = 0; v = -1; for (;;) instr = p[ic++]; switch (instr.typ) case TA: z[++v] = instr.opd; case TC: z[++v] = instr.opd; case BOP: int right = z[v--]; int left = z[v--]; switch (instr.opd) case Plus: z[++v] = left + right; case Minus:... case Eq: z[++v] = left == right; case NotEq:... case UNM: z[v] = -z[v]; case DR: z[v] = m[z[v]]; case ST: int val = z[v--]; int adr = z[v--]; m[adr] = val; case IFJ: if (!z[v--]) ic = instr.opd; case JU: ic = instr.opd; case WRT: printf("%d\n", z[v--]); case STOP: printf("konec interpretace\n\n"); return; 9 10 Lexikální analyzátor typedef enum /* ident číslo + - * / */ IDENT, NUMB, PLUS, MINUS, TIMES, DIVIDE, /* = <> < > <= >= ( ) := */ EQ, NEQ, LT, GT, LTE, GTE, LPAR, RPAR, ASSGN, /*, ; */ COMMA, SEMICOLON, /* var const begin end if then */ kwvar, kwconst, kwbegin, kwend, kwif, kwthen, kwelse, /* while do write */ kwwhile, kwdo, kwwrite, /* konec souboru */ EOI LexSymbol; enum MaxLenIdent = 32; extern LexSymbol Symb; extern char Ident[MaxLenIdent]; /* atribut symbolu IDENT */ extern int Cislo; /* atribut symbolu NUMB */ void CtiSymb(void); void InitLexan(char*); void Chyba(char*); void ChybaSrovnani(LexSymbol); 11 Převod EBNF na bezkontextovou gramatiku pravidla EBNF A = α (β 1 β 2 ) χ A = α [β] χ A = α β χ pravidla bezkontextové gramatiky A α X χ X β 1 X β 2 nebo A α β 1 χ A α β 2 χ A α X χ X β X ε nebo A α β χ A α χ A α X χ X β X X ε 12

LL(1) gramatika 1: Program Dekl SložPříkaz 2: Dekl DeklKonst Dekl 3: Dekl DeklProm Dekl 4: Dekl ε 5: DeklKonst const ident = číslo ZbDeklKonst ; 6: ZbDeklKonst, ident = číslo ZbDeklKonst 7: ZbDeklKonst ε 8: DeklProm var ident ZbDeklProm ; 9: ZbDeklProm, ident ZbDeklProm 10: ZbDeklProm ε 11: SložPříkaz begin Příkaz ZbPříkazů end 12: ZbPříkazů ; Příkaz ZbPříkazů 13: ZbPříkazů ε 14: Příkaz ident := Výraz 15: Příkaz write Výraz 16: Příkaz if Podmínka then Příkaz ČástElse 17: Příkaz while Podmínka do Příkaz 18: Příkaz SložPříkaz 19: Příkaz ε 20: ČástElse Příkaz 21: ČástElse ε 22: Podmínka Výraz RelOp Výraz 23: RelOp = 24: RelOp <> 25: RelOp < 26: RelOp > 27: RelOp <= 28: RelOp >= 29: Výraz Term ZbVýrazu 30: Výraz - Term ZbVýrazu 31: ZbVýrazu + Term ZbVýrazu 32: ZbVýrazu - Term ZbVýrazu 33: ZbVýrazu ε 34: Term Faktor ZbTermu 35: ZbTermu * Faktor ZbTermu 36: ZbTermu / Faktor ZbTermu 13 14 37: ZbTermu ε 38: Faktor ident 39: Faktor číslo 40: Faktor ( Výraz ) Atributy vstupních symbolů: vstupní symbol ident číslo Překlad do jazyka zásobníkového počítače syntetizovaný atribut sid shod Atributy výstupních symbolů: výstupní symbol dědičný atribut TC dhod TA da DR BOP dop UNM ST WRT JU dadr IFJ dadr STOP 15 16

Tabulka symbolů: klíč: identifikátor hodnota: popis významu identifikátoru Zpracování deklarací a tabulka symbolů Jména procedur operujících nad tabulkou symbolů budeme považovat za speciální výstupní symboly, jejichž výskyt v pravidle překladové gramatiky znamená vyvolání příslušné procedury. Dědičné atributy těchto symbolů budou reprezentovat vstupní parametry procedur. výst. symbol dědičné atr. význam deklkonst did, dhod Symbol označuje proceduru deklkonst(id,h), která doplní do tabulky symbolů deklaraci identifikátoru konstanty id s hodnotou h. Jde-li o druhou deklaraci identifikátoru, procedura ohlásí chybu a tabulku symbolů nezmění. deklprom did Symbol označuje proceduru deklprom(id), která doplní do tabulky symbolů deklaraci identifikátoru proměnné id. Deklarovaným proměnným jsou postupně přidělovány adresy 0, 1, 2,.... Jde-li o druhou deklaraci identifikátoru, procedura ohlásí chybu a tabulku symbolů nezmění. 1: Program Dekl SložPříkaz STOP 2: Dekl DeklKonst Dekl 3: Dekl DeklProm Dekl 4: Dekl ε 5: DeklKonst const ident = číslo deklkonst ZbDeklKonst ; 6: ZbDeklKonst, ident = číslo deklkonst ZbDeklKonst deklkonst.did := ident.sid deklkonst.dhod := číslo.shod deklkonst.did := ident.sid deklkonst.dhod := číslo.shod 7: ZbDeklKonst ε 8: DeklProm var ident deklprom ZbDeklProm ; deklprom.did := ident.sid 9: ZbDeklProm, ident deklprom ZbDeklProm deklprom.did := ident.sid 10: ZbDeklProm ε 17 18 Snadný, až na pravidlo Faktor ident Překlad výrazů kde překlad závisí na tom, jak je identifikátor deklarován. Jestliže ident je identifikátorem proměnné, výstupem má být dvojice instrukcí TA a DR kde a je adresa proměnné. výst. symbol dědičný atr. význam TR did Symbol označuje proceduru GenTR(id), která zjistí, zda identifikátor id je deklarován jako identifikátor proměnné nebo konstanty. V prvním případě generuje instrukce TA a DR kde a je adresa proměnné. Ve druhém případě generuje instrukci TC h kde h je hodnota konstanty. Není-li identifikátor deklarován, procedura ohlásí chybu. Jestliže ident je identifikátorem konstanty, výstupem má být instrukce TC hod kde hod je hodnota konstanty. Toto rozlišení nelze provést pomocí pravidel překladové gramatiky. Zavedeme proto speciální výstupní symbol TR (take result) označující sémantickou proceduru, která z tabulky symbolů zjistí, jak je identifikátor deklarován, a vygeneruje odpovídající instrukce. Vstupním parametrem procedury bude identifikátor, symbol TR tedy bude mít jediný dědičný atribut did. 19 20

22: Podmínka Výraz RelOp Výraz BOP BOP.dop := RelOp.sop 23: RelOp = RelOp.sop := Eq 24: RelOp <> RelOp.sop := NotEq......... 28: RelOp >= RelOp.sop := GreaterOrEq 29: Výraz Term ZbVýrazu 30: Výraz - Term UNM ZbVýrazu 31: ZbVýrazu + Term BOP ZbVýrazu BOP.dop := Plus 32: ZbVýrazu - Term BOP ZbVýrazu BOP.dop := Minus 33: ZbVýrazu ε 34: Term Faktor ZbTermu 35: ZbTermu * Faktor BOP ZbTermu BOP.dop := Times 36: ZbTermu / Faktor BOP ZbTermu BOP.dop := Divide 37: ZbTermu ε 38: Faktor ident TR TR.did := ident.sid 39: Faktor číslo TC TC.dhod := číslo.shod 40: Faktor ( Výraz ) Překlad jednoduchých příkazů Přiřazovací příkaz ident := výraz se přeloží do posloupnosti instrukcí TA a instrukce vytvořené překladem výrazu ST kde a je adresa proměnné ident. Pro zjištění adresy proměnné zavedeme funkci adrprom nad tabulkou symbolů: volání funkce adrprom(id) význam Funkce zjistí, zda id je identifikátorem proměnné. V kladném případě vrátí adresu proměnné, v záporném případě ohlásí chybu a vrátí nulu. 14: Příkaz ident TA := Výraz ST TA.da := adrprom(ident.sid) 21 22 Příkaz výstupu write výraz se přeloží do posloupnosti instrukcí instrukce vytvořené překladem výrazu WRT 15: Příkaz write Výraz WRT Prázdný příkaz má prázdný překlad. 19: Příkaz ε Překlad příkazu while Příkaz cyklu while podmínka do příkaz se přeloží do posloupnosti instrukcí a1: instrukce vytvořené překladem podmínky IFJ a2 instrukce vytvořené překladem příkazu JU a1 a2: Překlad vytvoříme tímto způsobem: před zpracováním podmínky si zapamatujeme aktuální hodnotu čítače instrukcí generovaného programu (tj. adresu a1), po překladu podmínky vygenerujeme instrukci IFJ s prozatím neurčeným operandem a zapamatujeme si adresu instrukce v cílovém programu (označme ji aifj), po překladu příkazu tvořícího tělo cyklu vygenerujeme instrukci JU s operandem a1, do operandu instrukce na adrese aifj dosadíme aktuální hodnotu čítače instrukcí generovaného programu (a2). 23 24

Překlad příkazu while Zavedeme speciální výstupní symboly GetIC a PutIC označující pomocné sémantické akce operující s čítačem instrukcí generovaného programu. výst. symbol děd. atr. synt. atr. význam GetIC sadr Symbol označuje funkci GetIC(), která vrátí aktuální hodnotu čítače instrukcí generovaného programu PutIC dadr Symbol označuje proceduru PutIC(adr), která dosadí do operandu instrukce na adrese adr aktuální hodnotu čítače instrukcí generovaného programu Adresu vygenerované instrukce IFJ formálně označíme tak, že k tomuto symbolu přidružíme syntetizovaný atribut sadr. 17: Příkaz while GetIC Podmínka IFJ do Příkaz JU PutIC IFJ.dadr := 0 JU.dadr := GetIC.sadr PutIC.dadr := IFJ.sadr Překlad příkazu if příkaz překlad if podmínka then příkaz1 instrukce vytvořené překladem podmínky IFJ a1 instrukce vytvořené překladem příkazu1 a1: if podmínka then příkaz1 příkaz2 instrukce vytvořené překladem podmínky IFJ a1 instrukce vytvořené překladem příkazu1 JU a2 a1: instrukce vytvořené překladem příkazu2 a2: Využijeme speciální výstupní symboly GetIC a PutIC. Úpravu instrukce IFJ provedeme až v pravidle pro neterminál ČástElse. K tomuto neterminálu proto přidružíme dědičný atribut dadr, jehož hodnotou bude adresa instrukce IFJ, která má být upravena. 25 26 Překlad příkazu if 16: Příkaz if Podmínka IFJ then Příkaz ČástElse IFJ.dadr = 0 ČástElse.dadr := IFJ.sadr 20: ČástElse JU PutIC 1 Příkaz PutIC 2 JU.dadr := 0 PutIC 1.dadr := ČástElse.dadr PutIC 2.dadr := JU.sadr 21: ČástElse PutIC PutIC.dadr := ČástElse.dadr 27 Přehled přidružení atributů druh symbolu symbol dědičné atributy neterminální symbol vstupní symbol výstupní symbol označující instrukci zásobníkového počítače syntetiz. atributy Program, Dekl, DeklKonst, DeklProm, ZbDeklKonst, ZbDeklProm, SložPříkaz, ZbPříkazů, Příkaz, Podmínka, Výraz, ZbVýrazu, Term, ZbTermu, Faktor ČástElse dadr RelOp sop ident sid číslo shod TC TA DR BOP UNM ST WRT JU IFJ STOP dhod da dop dadr dadr sadr sadr 28

speciální výstupní symbol deklkonst deklprom TR GetIC PutIC did, dhod did did dadr sadr Realizace tabulky symbolů Spojový seznam, jehož prvky budou (kromě ukazatele na další prvek) obsahovat: lexikální element identifikátoru (řetěz znaků) kód druhu identifikátoru celé číslo označující adresu proměnné nebo hodnotu konstanty. enum DruhId Nedef, IdProm, IdKonst; struct PrvekTab char *ident; DruhId druh; int hodn; PrvekTab *dalsi; PrvekTab(char *i, DruhId d, int h, PrvekTab *n); ; PrvekTab::PrvekTab(char *i, DruhId d, int h, PrvekTab *n) ident = new char[strlen(i)+1]; strcpy(ident, i); druh = d; hodn = h; dalsi = n; ; 29 30 Realizace tabulky symbolů static PrvekTab *TabSym; /* ukazatel na začátek tab. symbolů */ static PrvekTab *hledejid(char *id) PrvekTab *p = TabSym; while (p) if (strcmp(id,p->ident)==0) return p; p = p->dalsi; return NULL; static void Chyba(char *id, char *txt) printf("identifikator %s: %s\n", id, txt); Realizace tabulky symbolů void deklkonst(char *id, int val) PrvekTab *p = hledejid(id); if (p) Chyba(id, "druha deklarace"); return; TabSym = new PrvekTab(id, IdKonst, val, TabSym); void deklprom(char *id) static int volna_adr; PrvekTab *p = hledejid(id); if (p) Chyba(id, "druha deklarace"); return; TabSym = new PrvekTab(id, IdProm, volna_adr, TabSym); volna_adr++; 31 32

Realizace tabulky symbolů int adrprom(char *id) PrvekTab *p = hledejid(id); if (!p) Chyba(id, "neni deklarovan"); return 0; if (p->druh!= IdProm) Chyba(id, "neni identifikatorem promenne"); return 0; return p->hodn; DruhId idpromkonst(char *id, int *v) PrvekTab *p = hledejid(id); if (p) *v = p->hodn; return p->druh; Chyba(id, "neni deklarovan"); return Nedef; Specifikace: int Gener(TypInstr, int = 0); void GenTR(char*); void PutIC(int); int GetIC(); Implementace: int Gener(TypInstr ti, int opd) p[ic].typ = ti; p[ic].opd = opd; return ic++; Realizace výstupních funkcí 33 34 Realizace výstupních funkcí void GenTR(char *id) int v; DruhId druh = idpromkonst(id, &v); switch (druh) case IdProm: Gener(TA, v); Gener(DR); case IdKonst: Gener(TC, v); void PutIC(int adr) p[adr].opd = ic; int GetIC() return ic; void Srovnani(LexSymbol s) if (Symb == s) CtiSymb(); ChybaSrovnani(s); void Srovnani_IDENT(char *id) if (Symb == IDENT) strcpy(id, Ident); CtiSymb(); ChybaSrovnani(IDENT); void Srovnani_NUMB(int *h) if (Symb == NUMB) *h = Cislo; CtiSymb(); ChybaSrovnani(NUMB); 35 36

void Program() /* Program -> Dekl SložPříkaz STOP */ Dekl(); SlozPrikaz(); Gener(STOP); void Dekl() switch (Symb) case kwvar: /* Dekl -> DeklProm Dekl */ DeklProm(); Dekl(); case kwconst: /* Dekl -> DeklKonst Dekl */ DeklKonst(); Dekl(); default: /* Dekl -> ε */ ; 37 void DeklKonst() /* DeklKonst -> const ident = číslo deklkonst ZbDeklKonst ; */ char id[maxlenident]; int hod; CtiSymb(); Srovnani_IDENT(id); Srovnani(EQ); Srovnani_NUMB(&hod); deklkonst(id, hod); ZbDeklKonst(); Srovnani(SEMICOLON); void ZbDeklKonst() if (Symb == COMMA) /* ZbDeklKonst ->, ident = číslo deklkonst ZbDeklKonst */ char id[maxlenident]; int hod; CtiSymb(); Srovnani_IDENT(id); Srovnani(EQ); Srovnani_NUMB(&hod); deklkonst(id, hod); ZbDeklKonst(); /* ZbDeklKonst -> ε */ ; 38 void DeklProm() /* DeklProm -> var ident deklprom ZbDeklProm ; */ char id[maxlenident]; CtiSymb(); Srovnani_IDENT(id); deklprom(id); ZbDeklProm(); Srovnani(SEMICOLON); void ZbDeklProm() if (Symb == COMMA) /* ZbDeklProm ->, ident deklprom ZbDeklProm */ char id[maxlenident]; CtiSymb(); Srovnani_IDENT(id); deklprom(id); ZbDeklProm(); /* ZbDeklProm -> ε */ ; void SlozPrikaz() /* begin Příkaz ZbPříkazů end */ Srovnani(kwBEGIN); Prikaz(); ZbPrikazu(); Srovnani(kwEND); void ZbPrikazu() if (Symb == SEMICOLON) /* ZbPrikazu -> ; Příkaz ZbPříkazů */ CtiSymb(); Prikaz(); ZbPrikazu(); /* ZbPrikazu -> ε */ ; 39 40

void Prikaz() switch (Symb) case IDENT: /* Příkaz -> ident TA := Výraz ST */ Gener(TA, adrprom(ident)); CtiSymb(); Srovnani(ASSGN); Vyraz(); Gener(ST); case kwwrite: /* Příkaz -> write Výraz WRT */ CtiSymb(); Vyraz(); Gener(WRT); case kwif: /* Příkaz -> if Podmínka IFJ then Příkaz ČástElse */ CtiSymb(); Podminka(); int adrifj = Gener(IFJ); Srovnani(kwTHEN); Prikaz(); CastElse(adrIFJ); case kwwhile: /* Příkaz -> while GetIC Podmínka IFJ do Příkaz JU PutIC */ int a1 = GetIC(); CtiSymb(); Podminka(); int aifj = Gener(IFJ); Srovnani(kwDO); Prikaz(); Gener(JU, a1); PutIC(aIFJ); case kwbegin: /* Příkaz -> SložPříkaz */ SlozPrikaz(); 41 42 void CastElse(int adrifj) if (Symb == kwelse) /* ČástElse -> JU PutIC Příkaz PutIC */ CtiSymb(); int adrju = Gener(JU); PutIC(adrIFJ); Prikaz(); PutIC(adrJU); /* ČástElse -> ε */ ; void Podminka() /* Podmínka -> Výraz RelOp Výraz BOP */ Vyraz(); Operator op = RelOp(); Vyraz(); Gener(BOP, op); Operator RelOp() switch (Symb) case EQ: /* RelOp -> = */ CtiSymb(); return Eq; case NEQ: /* RelOp -> <> */ CtiSymb(); return NotEq; case LT: /* RelOp -> < */ CtiSymb(); return Less; case GT: /* RelOp -> > */ CtiSymb(); return Greater; case LTE: /* RelOp -> <= */ CtiSymb(); return LessOrEq; case GTE: /* RelOp -> >= */ CtiSymb(); return GreaterOrEq; default: Chyba("neocekavany symbol"); 43 44

void Vyraz() if (Symb == MINUS) /* Výraz -> - Term UNM ZbVýrazu */ CtiSymb(); Term(); Gener(UNM); ZbVyrazu(); /* Výraz -> Term ZbVýrazu */ Term(); ZbVyrazu(); void ZbVyrazu() switch (Symb) case PLUS: /* ZbVýrazu -> + Term BOP ZbVýrazu */ CtiSymb(); Term(); Gener(BOP, Plus); ZbVyrazu(); case MINUS: /* ZbVýrazu -> - Term BOP ZbVýrazu */ CtiSymb(); Term(); Gener(BOP, Minus); ZbVyrazu(); case default: /* ZbVýrazu -> ε */ ; void Term() /* Term -> Faktor ZbTermu */ Faktor(); ZbTermu(); void ZbTermu() switch (Symb) case TIMES: /* ZbTermu -> * Faktor BOP ZbTermu */ CtiSymb(); Faktor(); Gener(BOP, Times); ZbTermu(); case DIVIDE: /* ZbTermu -> / Faktor BOP ZbTermu */ CtiSymb(); Faktor(); Gener(BOP, Divide); ZbTermu(); case default:/* ZbTermu -> ε */ ; 45 46 void Faktor() switch (Symb) case IDENT: /* Faktor -> ident TR */ char id[maxlenident]; Srovnani_IDENT(id); GenTR(id); case NUMB: /* Faktor -> číslo TC */ int hodn; Srovnani_NUMB(&hodn); Gener(TC, hodn); case LPAR: /* Faktor -> ( Výraz ) */ CtiSymb(); Vyraz(); Srovnani(RPAR); default: Chyba("Neocekavany symbol"); 47