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

Podobné dokumenty
Implementace LL(1) překladů

Poslední aktualizace: 14. října 2011

Syntaxí řízený překlad

Atributovaný překlad

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

Vlastnosti Derivační strom Metody Metoda shora dolů Metoda zdola nahoru Pomocné množiny. Syntaktická analýza. Metody a nástroje syntaktické analýzy

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

Programovací jazyk Pascal

Uplatnění metod na zvolený jazyk

Výpočetní modely pro rozpoznávání bezkontextových jazyků zásobníkové automaty LL(k) a LR(k) analyzátory

Binární soubory (datové, typované)

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

Zadání: TÉMA: Zápis algoritmu, čtení textového souboru, porovnání řetězců.

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

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

Konstruktory překladačů

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

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

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

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

1 PRVOCISLA: KRATKY UKAZKOVY PRIKLAD NA DEMONSTRACI BALIKU WEB 1

Jednoznačné a nejednoznačné gramatiky

Překladač a jeho struktura

Pascal. Katedra aplikované kybernetiky. Ing. Miroslav Vavroušek. Verze 7

5 Rekurze a zásobník. Rekurzivní volání metody

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

Reprezentace aritmetického výrazu - binární strom reprezentující aritmetický výraz

Řešení: PŘENESVĚŽ (N, A, B, C) = přenes N disků z A na B pomocí C

Automaty a gramatiky

Úvod do programovacích jazyků (Java)

O datových typech a jejich kontrole

6 Příkazy řízení toku

Algoritmizace a programování

1. Implementace funkce počet vrcholů. Předmět: Algoritmizace praktické aplikace (3ALGA)

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

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

Čísla značí použité pravidlo, šipka směr postupu Analýza shora. Analýza zdola A 2 B 3 B * C 2 C ( A ) 1 a A + B. A Derivace zleva:

VYSOKÉ UČENÍ TECHNICKÉ V BRNĚ BRNO UNIVERSITY OF TECHNOLOGY

V každém kroku se a + b zmenší o min(a, b), tedy vždy alespoň o 1. Jestliže jsme na začátku dostali 2

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

Anotace. Dijkstrův algoritmus,

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

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

1. Definujte překladač. Jaký je rozdíl mezi interpretačním a kompilačním překladačem? Co je to konverzační překladač?

8) Jaké jsou důvody pro použití víceprůchodového překladače Dříve hlavně kvůli úspoře paměti, dnes spíše z důvodu optimalizace

Rekurze. Pavel Töpfer, 2017 Programování 1-8 1

Časová a prostorová složitost algoritmů

Anotace. Dámy na šachovnici dominance a nezávislost. Aritmetické výrazy, notace a převody mezi nimi, nejdelší rostoucí podposloupnost.

Úvod do programování

Test prvočíselnosti. Úkol: otestovat dané číslo N, zda je prvočíslem

Kapitola 6. LL gramatiky. 6.1 Definice LL(k) gramatik. Definice 6.3. Necht G = (N, Σ, P, S) je CFG, k 1 je celé číslo.

Algoritmy a datové struktury

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

Pseudonáhodná čísla = algoritmicky generovaná náhrada za náhodná čísla

NPRG030 Programování I, 2010/11

Anotace. Soubory a práce s nimi, rekurze podruhé, struktury (datový typ record), Martin Pergel,

Binární vyhledávací stromy

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

Abstraktní datové typy FRONTA

Interpret jazyka IFJ2011

Příklady: (y + (sin(2*x) + 1)*2)/ /2 * 5 = 8.5 (1+3)/2 * 5 = /(2 * 5) = 1.3. Pavel Töpfer, 2017 Programování 1-3 1

1.1 Struktura programu v Pascalu Vstup a výstup Operátory a některé matematické funkce 5

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

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

VY_32_INOVACE_08_2_04_PR

TÉMATICKÝ OKRUH TZD, DIS a TIS

SII - Informatika. 1. Atribut relace, jehož hodnota jednoznačně určuje prvek v jiné relaci, se nazývá:

1. D Y N A M I C K É DAT O V É STRUKTUR Y

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

Úvod do informatiky. Miroslav Kolařík

GENEROVÁNI KÓDU jazyk Mila

2 Strukturované datové typy Pole Záznam Množina... 4

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

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.

Datový typ prioritní fronta Semestrální práce z předmětu 36PT

Binární vyhledávací strom pomocí směrníků Miroslav Hostaša L06620

2.1 Podmínka typu case Cykly Cyklus s podmínkou na začátku Cyklus s podmínkou na konci... 5

Bezkontextové jazyky. Bezkontextové jazyky 1 p.1/39

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

53. ročník Matematické olympiády 2003/2004

Algoritmizace Dynamické programování. Jiří Vyskočil, Marko Genyg-Berezovskyj 2010

Konečný automat. Jan Kybic.

6. Příkazy a řídící struktury v Javě

NPRG030 Programování I, 2017/18 1 / :22:16

Programování 2 (NMIN102) Soubory. RNDr. Michal Žemlička, Ph.D.

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

Rozklad problému na podproblémy

Konstruktory a destruktory

Sada 1 - Základy programování

ExcelVBAmodul. Podpora pro výměnu dat automatů MICROPEL s aplikací Microsoft Excel

ALGORITMIZACE 2010/03 STROMY, BINÁRNÍ STROMY VZTAH STROMŮ A REKURZE ZÁSOBNÍK IMPLEMENTUJE REKURZI PROHLEDÁVÁNÍ S NÁVRATEM (BACKTRACK)

Basic256 - úvod do programování Příklady. ing. petr polách

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.

Dynamické datové typy a struktury

Unity a Objekty (NMIN102) RNDr. Michal Žemlička, Ph.D.

ALGORITMIZACE 2010/03 STROMY, BINÁRNÍ STROMY VZTAH STROMŮ A REKURZE ZÁSOBNÍK IMPLEMENTUJE REKURZI PROHLEDÁVÁNÍ S NÁVRATEM (BACKTRACK)

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ář

Anotace. Ordinalni typy - typ char, funkce ord, chr, succ, prev, inc, dec,

VYSOKÉ UČENÍ TECHNICKÉ V BRNĚ BRNO UNIVERSITY OF TECHNOLOGY

Transkript:

Implementace LL(1) překladů Ústav informatiky, FPF SU Opava sarka.vavreckova@fpf.slu.cz Poslední aktualizace: 6. ledna 2012

Postup Programujeme syntaktickou analýzu: 1 Navrhneme vhodnou LL(1) gramatiku popisující strukturu jazyka. 2 Vytvoříme podle ní překladový automat (rozkladovou tabulku) nebo alespoň všechny potřebné množiny. 3 Naprogramujeme: metodou přepisu rozkladové tabulky, metodou rekurzivního sestupu.

Postup Programujeme syntaktickou analýzu: 1 Navrhneme vhodnou LL(1) gramatiku popisující strukturu jazyka. 2 Vytvoříme podle ní překladový automat (rozkladovou tabulku) nebo alespoň všechny potřebné množiny. 3 Naprogramujeme: metodou přepisu rozkladové tabulky, metodou rekurzivního sestupu.

Postup Programujeme syntaktickou analýzu: 1 Navrhneme vhodnou LL(1) gramatiku popisující strukturu jazyka. 2 Vytvoříme podle ní překladový automat (rozkladovou tabulku) nebo alespoň všechny potřebné množiny. 3 Naprogramujeme: metodou přepisu rozkladové tabulky, metodou rekurzivního sestupu.

Postup Programujeme syntaktickou analýzu: 1 Navrhneme vhodnou LL(1) gramatiku popisující strukturu jazyka. 2 Vytvoříme podle ní překladový automat (rozkladovou tabulku) nebo alespoň všechny potřebné množiny. 3 Naprogramujeme: metodou přepisu rozkladové tabulky, metodou rekurzivního sestupu.

Postup Programujeme syntaktickou analýzu: 1 Navrhneme vhodnou LL(1) gramatiku popisující strukturu jazyka. 2 Vytvoříme podle ní překladový automat (rozkladovou tabulku) nebo alespoň všechny potřebné množiny. 3 Naprogramujeme: metodou přepisu rozkladové tabulky, metodou rekurzivního sestupu.

Přepis rozkladové tabulky Potřebujeme rozkladovou tabulku, zásobník na ukládání symbolů, proměnnou, ve které je uložen právě zpracovávaný symbol, funkci lex(), která nám vrátí další symbol, který extrahovala ze vstupního souboru (uloží do proměnné z předchozího bodu), proměnnou pro výstup (soubor, dynamická struktura apod.).

Popis metody Analýza probíhá takto: 1 zavoláme funkci Lex(), 2 zjistíme, o jaký symbol jde, přiřadíme terminál, 3 provedeme analýzu symbolu, zařadíme do derivačního stromu, při chybě nebo akceptování celého vstupu končíme výpočet, 4 pokud je hodnota symbolu potřebná (například identifikátor nebo číslo), uložíme ji, 5 návrat k prvnímu bodu.

Popis metody Analýza probíhá takto: 1 zavoláme funkci Lex(), 2 zjistíme, o jaký symbol jde, přiřadíme terminál, 3 provedeme analýzu symbolu, zařadíme do derivačního stromu, při chybě nebo akceptování celého vstupu končíme výpočet, 4 pokud je hodnota symbolu potřebná (například identifikátor nebo číslo), uložíme ji, 5 návrat k prvnímu bodu.

Popis metody Analýza probíhá takto: 1 zavoláme funkci Lex(), 2 zjistíme, o jaký symbol jde, přiřadíme terminál, 3 provedeme analýzu symbolu, zařadíme do derivačního stromu, při chybě nebo akceptování celého vstupu končíme výpočet, 4 pokud je hodnota symbolu potřebná (například identifikátor nebo číslo), uložíme ji, 5 návrat k prvnímu bodu.

Popis metody Analýza probíhá takto: 1 zavoláme funkci Lex(), 2 zjistíme, o jaký symbol jde, přiřadíme terminál, 3 provedeme analýzu symbolu, zařadíme do derivačního stromu, při chybě nebo akceptování celého vstupu končíme výpočet, 4 pokud je hodnota symbolu potřebná (například identifikátor nebo číslo), uložíme ji, 5 návrat k prvnímu bodu.

Popis metody Analýza probíhá takto: 1 zavoláme funkci Lex(), 2 zjistíme, o jaký symbol jde, přiřadíme terminál, 3 provedeme analýzu symbolu, zařadíme do derivačního stromu, při chybě nebo akceptování celého vstupu končíme výpočet, 4 pokud je hodnota symbolu potřebná (například identifikátor nebo číslo), uložíme ji, 5 návrat k prvnímu bodu.

Popis metody Budeme potřebovat tyto funkce: expand(číslo pravidla) uloží pravou stranu pravidla s daným číslem do zásobníku a na výstup přidá číslo pravidla, pop ověří shodnost symbolu na vstupu se symbolem vyjmutým ze zásobníku a načte další symbol ze vstupu, accept při konci vstupu a konci zásobníku ukončí výpočet programu, error ošetří chybu, která se vyskytla při překladu, Akce je hlavní řídicí funkce, v cyklu volá předchozí, zajišťuje pohyb v tabulce, Init je inicializační funkce (inicializuje zásobník, zajistí přednačtení prvního symbolu apod.), úklidová funkce je Done.

Ukážeme na příkladu: S AB A CD B +AB AB ε C (S) i n D CD /CD ε 1 2 3, 4, 5 6, 7, 8 9, 10, 11 Rozkladová tabulka i n + / ( ) $ S e1 e1 e1 A e2 e2 e2 B e3 e4 e5 e5 C e7 e8 e6 D e11 e11 e9 e10 e11 e11

Ukážeme na příkladu: S AB A CD B +AB AB ε C (S) i n D CD /CD ε 1 2 3, 4, 5 6, 7, 8 9, 10, 11 Rozkladová tabulka i n + / ( ) $ S e1 e1 e1 A e2 e2 e2 B e3 e4 e5 e5 C e7 e8 e6 D e11 e11 e9 e10 e11 e11

Datové typy type TTypSymbolu = (S_ID, S_NUM, S_PLUS, S_MINUS, S_MUL, S_DIV, S_LPAR, S_RPAR, S_ENDOFFILE, S_NS, S_NA, S_NB, S_NC, S_ND, S_HASH); // terminály // neterminály TSymbol = record typ: TTypSymbolu; atrib: string; // identifikace (název) symbolu // atribut TZnak = record rad: string; // zpracovávaný řádek pozice: byte; // pozice posledního načteného znaku na řádku delka: byte; // délka tohoto řádku cislo: word; // číslo řádku

Proměnné var konec: boolean; // indikátor ukončení výpočtu, proveden accept znak: TZnak; // aktuální znak načtený ze zdroje pro funkci Lex() symbol: TSymbol; // aktuální symbol načtený z proměnné vstup vrchol_zas: TTypSymbolu; // symbol na vrcholu zásobníku zasobnik: TZasobnik; // zásobník, prvky jsou typu TTypSymbolu

expanze procedure expand(cislo_prav: integer); begin case cislo_prav of 1: begin // S AB Pridej_do_zasobniku(S_NB); Pridej_do_zasobniku(S_NA); 2: begin // A CD Pridej_do_zasobniku(S_ND); Pridej_do_zasobniku(S_NC); 3: begin // B +AB Pridej_do_zasobniku(S_NB); Pridej_do_zasobniku(S_NA); Pridej_do_zasobniku(S_PLUS);... // pro každé pravidlo gramatiky kromě epsilonových pravidel vystup(cislo_prav); // zápis čísla použitého pravidla na výstup

Ošetření chyb procedure error(const hlaska: string); // Chyba syntaxe; // vypíše číslo řádku, pozici na řádku a řetězec s daným hlášením begin Konec := true; writeln( Chyba při syntaktické analýze na řádku,znak.cislo,, sloupci,znak.pozice, :,hlaska);

Zpracování terminálů a akceptování procedure pop; begin if symbol.typ = vrchol_zas) then Lex // lexikální analyzátor načte další symbol else error( chybný symbol na vstupu - +VypisTyp(symbol.typ)); procedure accept; begin Konec := true;

Inicializace a ukončení procedure Init; begin... // inicializace vstupu a výstupu Vytvor_zasobnik; Pridej_do_zasobniku(S_HASH); // symbol konce zásobníku Pridej_do_zasobniku(S_NS); // startovací symbol gramatiky Lex; // načte symbol ze vstupu do sym Konec := false; procedure Done; begin Zlikviduj_zasobnik; // uvolní paměť zabranou zásobníkem... // uzavření vstupu a výstupu

Simulace práce s tabulkou Funkce Akce Pracuje takto: vyjme ze zásobníku jeden symbol, tím určí řádek tabulky a podle symbolu na vstupu určí sloupec tabulky, podle obsahu buňky na daném řádku a sloupci zavolá funkci expand, pop, accept nebo error (prázdná buňka znamená error), je volána v cyklu tak dlouho, dokud není konec zpracovávaného programu.

Simulace práce s tabulkou case řádek of první_řádek: case sloupec of první_sloupec: obsah_buňky_[1,1] druhý_sloupec: obsah_buňky_[1,2]... end else error(...); druhý_řádek: case sloupec of první_sloupec: obsah_buňky_[2,1] druhý_sloupec: obsah_buňky_[2,2]... end else error(...);... terminál: pop; dno_zásobníku: if konec_vstupu then accept else error(...);

Simulace práce s tabulkou procedure Akce; begin vrchol_zas := Vyjmi_ze_zasobniku; case vrchol_zas of S_NS: if (symbol.typ in [S_ID,S_NUM,S_LPAR] then expand(1) else error( chybný symbol na vstupu - +symbol.typ); S_NA: if (symbol.typ in [S_ID,S_NUM,S_LPAR] then expand(2) else error( chybný symbol na vstupu - +symbol.typ); S_NB: case symbol.typ of S_PLUS: expand(3); S_MINUS: expand(4); S_RPAR,S_ENDOFFILE: expand(5); else error( chybný symbol na vstupu - +symbol.typ);...

Simulace práce s tabulkou S_NC: case symbol.typ of S_ID: expand(7); S_NUM: expand(8); S_LPAR: expand(6); else error( chybný symbol na vstupu - +symbol.typ); S_ND: case symbol.typ of S_MUL: expand(9); S_DIV: expand(10); S_PLUS,S_MINUS,S_RPAR,S_ENDOFFILE: expand(11); else error( chybný symbol na vstupu - +symbol.typ); S_PLUS,S_MINUS,S_MUL,S_DIV,S_LPAR,S_RPAR,S_ID,S_NUM: pop; else error( chybný symbol na vstupu - +symbol.typ); S_HASH: if (symbol.typ = S_ENDOFFILE) then accept else error( chybný symbol na vstupu - +symbol.typ);

Hlavní funkce syntaktické analýzy procedure S_analyza; begin Init; while (not Konec) do Akce; Done;

Vlastnosti metody Výhody: nepoužíváme přímo rekurzi (netřeba řešit problém hloubky rekurze s prostorovou složitostí). Nevýhody: u překladů zahrnujících např. matematické výrazy se hůře implementuje sémantika, potřebujeme zásobník.

Vlastnosti metody Výhody: nepoužíváme přímo rekurzi (netřeba řešit problém hloubky rekurze s prostorovou složitostí). Nevýhody: u překladů zahrnujících např. matematické výrazy se hůře implementuje sémantika, potřebujeme zásobník.

Rekurzívní sestup Potřebujeme LL(1) gramatiku (nemusíme dělat rozkladovou tabulku), množiny F IRST a F OLLOW, pro každé pravidlo A α vytvoříme množinu signatur F S(A, α) = F IRST (α F OLLOW (A)) proměnnou, ve které je uložen právě zpracovávaný symbol, funkci lex(), která nám vrátí další symbol, který extrahovala ze vstupního souboru (uloží do proměnné z předchozího bodu), proměnnou pro výstup (soubor, dynamická struktura apod.).

Popis metody Analýza probíhá takto: 1 zavoláme funkci Lex(), pak opět voláme pro každý symbol, 2 postupujeme přesně tak, jakobychom konstruovali derivační strom ručně : když jsme v uzlu ohodnoceném neterminálem, vytvoříme poduzly podle zvoleného pravidla, tentýž postup rekurzívně uplatníme na všechny poduzly (zleva doprava), které jsou ohodnoceny neterminály, u terminálních poduzlů pouze spustíme kontrolní porovnání podobně, jako bylo u předchozí metody pop. 3 rekurzívní volání probíhá zleva doprava a shora dolů, tedy i vstup je čten zleva doprava, 4 když skončí všechny rekurzivní výpočty pro jednotlivé větve a vstup je celý přečtený ($), akceptujeme vstup.

Popis metody Analýza probíhá takto: 1 zavoláme funkci Lex(), pak opět voláme pro každý symbol, 2 postupujeme přesně tak, jakobychom konstruovali derivační strom ručně : když jsme v uzlu ohodnoceném neterminálem, vytvoříme poduzly podle zvoleného pravidla, tentýž postup rekurzívně uplatníme na všechny poduzly (zleva doprava), které jsou ohodnoceny neterminály, u terminálních poduzlů pouze spustíme kontrolní porovnání podobně, jako bylo u předchozí metody pop. 3 rekurzívní volání probíhá zleva doprava a shora dolů, tedy i vstup je čten zleva doprava, 4 když skončí všechny rekurzivní výpočty pro jednotlivé větve a vstup je celý přečtený ($), akceptujeme vstup.

Popis metody Analýza probíhá takto: 1 zavoláme funkci Lex(), pak opět voláme pro každý symbol, 2 postupujeme přesně tak, jakobychom konstruovali derivační strom ručně : když jsme v uzlu ohodnoceném neterminálem, vytvoříme poduzly podle zvoleného pravidla, tentýž postup rekurzívně uplatníme na všechny poduzly (zleva doprava), které jsou ohodnoceny neterminály, u terminálních poduzlů pouze spustíme kontrolní porovnání podobně, jako bylo u předchozí metody pop. 3 rekurzívní volání probíhá zleva doprava a shora dolů, tedy i vstup je čten zleva doprava, 4 když skončí všechny rekurzivní výpočty pro jednotlivé větve a vstup je celý přečtený ($), akceptujeme vstup.

Popis metody Analýza probíhá takto: 1 zavoláme funkci Lex(), pak opět voláme pro každý symbol, 2 postupujeme přesně tak, jakobychom konstruovali derivační strom ručně : když jsme v uzlu ohodnoceném neterminálem, vytvoříme poduzly podle zvoleného pravidla, tentýž postup rekurzívně uplatníme na všechny poduzly (zleva doprava), které jsou ohodnoceny neterminály, u terminálních poduzlů pouze spustíme kontrolní porovnání podobně, jako bylo u předchozí metody pop. 3 rekurzívní volání probíhá zleva doprava a shora dolů, tedy i vstup je čten zleva doprava, 4 když skončí všechny rekurzivní výpočty pro jednotlivé větve a vstup je celý přečtený ($), akceptujeme vstup.

Popis metody Analýza probíhá takto: 1 zavoláme funkci Lex(), pak opět voláme pro každý symbol, 2 postupujeme přesně tak, jakobychom konstruovali derivační strom ručně : když jsme v uzlu ohodnoceném neterminálem, vytvoříme poduzly podle zvoleného pravidla, tentýž postup rekurzívně uplatníme na všechny poduzly (zleva doprava), které jsou ohodnoceny neterminály, u terminálních poduzlů pouze spustíme kontrolní porovnání podobně, jako bylo u předchozí metody pop. 3 rekurzívní volání probíhá zleva doprava a shora dolů, tedy i vstup je čten zleva doprava, 4 když skončí všechny rekurzivní výpočty pro jednotlivé větve a vstup je celý přečtený ($), akceptujeme vstup.

Popis metody Analýza probíhá takto: 1 zavoláme funkci Lex(), pak opět voláme pro každý symbol, 2 postupujeme přesně tak, jakobychom konstruovali derivační strom ručně : když jsme v uzlu ohodnoceném neterminálem, vytvoříme poduzly podle zvoleného pravidla, tentýž postup rekurzívně uplatníme na všechny poduzly (zleva doprava), které jsou ohodnoceny neterminály, u terminálních poduzlů pouze spustíme kontrolní porovnání podobně, jako bylo u předchozí metody pop. 3 rekurzívní volání probíhá zleva doprava a shora dolů, tedy i vstup je čten zleva doprava, 4 když skončí všechny rekurzivní výpočty pro jednotlivé větve a vstup je celý přečtený ($), akceptujeme vstup.

Popis metody Analýza probíhá takto: 1 zavoláme funkci Lex(), pak opět voláme pro každý symbol, 2 postupujeme přesně tak, jakobychom konstruovali derivační strom ručně : když jsme v uzlu ohodnoceném neterminálem, vytvoříme poduzly podle zvoleného pravidla, tentýž postup rekurzívně uplatníme na všechny poduzly (zleva doprava), které jsou ohodnoceny neterminály, u terminálních poduzlů pouze spustíme kontrolní porovnání podobně, jako bylo u předchozí metody pop. 3 rekurzívní volání probíhá zleva doprava a shora dolů, tedy i vstup je čten zleva doprava, 4 když skončí všechny rekurzivní výpočty pro jednotlivé větve a vstup je celý přečtený ($), akceptujeme vstup.

Popis metody Budeme potřebovat tyto funkce: Init, Done, expect ověří shodnost symbolu na vstupu se symbolem, který je parametrem této funkce, a načte další symbol ze vstupu, S, A, B,... pro každý neterminál vytvoříme stejně nazvanou funkci, tyto funkce se budou navzájem rekurzívně volat, error ošetří chybu, která se vyskytla při překladu.

Ukážeme na příkladu: S AB A CD B +AB AB ε C (S) i n D CD /CD ε 1 2 3, 4, 5 6, 7, 8 9, 10, 11

Datové typy type TTypSymbolu = (S_ID, S_NUM, S_PLUS, S_MINUS, S_MUL, S_DIV, S_LPAR, S_RPAR, S_ENDOFFILE); // terminály TSymbol = record typ: TTypSymbolu; atrib: string; // identifikace (název) symbolu // atribut TZnak = record rad: string; // zpracovávaný řádek pozice: byte; // pozice posledního načteného znaku na řádku delka: byte; // délka tohoto řádku cislo: word; // číslo řádku

Proměnné var konec: boolean; // indikátor ukončení výpočtu, proveden accept znak: TZnak; // aktuální znak načtený ze zdroje pro funkci Lex() symbol: TSymbol; // aktuální symbol načtený z proměnné vstup

Hlavní funkce syntaktické analýzy Úkol: inicializovat výpočet, zavolat funkci S, dále je vše voláno rekurzí, ukončit výpočet. procedure S analyza; begin Init; S; Done;

Hlavní funkce syntaktické analýzy Úkol: inicializovat výpočet, zavolat funkci S, dále je vše voláno rekurzí, ukončit výpočet. procedure S analyza; begin Init; S; Done;

Inicializace a ukončení procedure Init; begin... // inicializace vstupu a výstupu Lex; // načte symbol ze vstupu do sym Konec := false; procedure Done; begin... // uzavření vstupu a výstupu

Ošetření chyb procedure error(const hlaska: string); // Chyba syntaxe; // vypíše číslo řádku, pozici na řádku a řetězec s daným hlášením begin Konec := true; writeln( Chyba při syntaktické analýze na řádku,znak.cislo,, sloupci,znak.pozice, :,hlaska);

Zpracování terminálů porovná zpracovávaný symbol (terminál z pravidla) se znakem na vstupu (musí souhlasit), načte další znak ze vstupu. procedure expect(terminal: TTypSymbolu); begin if symbol.typ = terminal then Lex else error( chybný symbol na vstupu - +VypisTyp(symbol.typ));

Funkce neterminálů Pro každou množinu pravidel se stejnou levou stranou: A α 1 α 2 α n procedure A; begin if vstupni sym in FS(A,α 1 ) then... postupně jsou ošetřeny symboly z řetězce α 1 else if vstupni sym in FS(A,α 2 ) then... postupně jsou ošetřeny symboly z řetězce α 2 else... ostatní pravidla else error(...);

Funkce neterminálů Pro každou množinu pravidel se stejnou levou stranou: A α 1 α 2 α n procedure A; begin if vstupni sym in FS(A,α 1 ) then... postupně jsou ošetřeny symboly z řetězce α 1 else if vstupni sym in FS(A,α 2 ) then... postupně jsou ošetřeny symboly z řetězce α 2 else... ostatní pravidla else error(...);

Funkce neterminálů S AB procedure S; begin if symbol.typ in [S ID,S NUM,S LPAR] then begin A; B; end else error( chybný symbol na vstupu - +VypisTyp(symbol.typ));

Funkce neterminálů A CD procedure A; begin if symbol.typ in [S ID,S NUM,S LPAR] then begin C; D; end else error( chybný symbol na vstupu - +VypisTyp(symbol.typ));

Funkce neterminálů B +AB AB ε procedure B; begin case symbol.typ of S PLUS: begin expect(s PLUS); A; B; S MINUS: begin expect(s MINUS); A; B; S RPAR, S ENDOFFILE: ; else error( chybný symbol na vstupu - +VypisTyp(symbol.typ));

Funkce neterminálů C (S) i n procedure C; begin case symbol.typ of S LPAR: begin expect(s LPAR); S; expect(s RPAR); S ID: expect(s ID); S NUM: expect(s NUM); else error( chybný symbol na vstupu - +VypisTyp(symbol.typ));

Funkce neterminálů D CD /CD ε procedure D; begin case symbol.typ of S MUL: begin expect(s MUL); C; D; S DIV: begin expect(s DIV); C; D; S PLUS,S MINUS,S RPAR,S ENDOFFILE: ; else error( chybný symbol na vstupu - +VypisTyp(symbol.typ));

Vlastnosti metody Výhody: není nutné vytvářet rozkladovou tabulku, třebaže množiny signatur vytvořit musíme, nepotřebujeme vlastní zásobník, rekurze probíhá pouze přes vzájemné volání funkcí (procedur) s použitím systémového zásobníku, není problém s navázáním sémantické analýzy. Nevýhody: hloubka rekurze může za určitých okolností působit problémy s prostorovou složitostí.

Vlastnosti metody Výhody: není nutné vytvářet rozkladovou tabulku, třebaže množiny signatur vytvořit musíme, nepotřebujeme vlastní zásobník, rekurze probíhá pouze přes vzájemné volání funkcí (procedur) s použitím systémového zásobníku, není problém s navázáním sémantické analýzy. Nevýhody: hloubka rekurze může za určitých okolností působit problémy s prostorovou složitostí.