20
1 od 20 PREVAJALNIKI Avtor: Blaž Sovdat Razred: 4.Ra Mentor: mag. Boštjan V

Prevajalniki

Embed Size (px)

DESCRIPTION

High school thesis defence.

Citation preview

Page 1: Prevajalniki

1 od 20

PREVAJALNIKI

Avtor: Blaž SovdatRazred: 4.RaMentor: mag. Boštjan Vouk

Page 2: Prevajalniki

2 od 20

Kaj je prevajalnik?

Je program Izvorni program

preslika v semantično ekvivalenten ciljni program.

Rezultat prevajanja ni nujno izvršljiv program

Page 3: Prevajalniki

3 od 20

Shema preprostega prevajalnika

Leksikalni analizator Parser (sintaksna analiza) Generator vmesne kode Optimizacija (neodvisna od arhitekture) Generator kode Optimizator

Page 4: Prevajalniki

4 od 20

Leksikalni analizator

Neposreden ``stik'' z izvornim programom Nize vhodnih znakov grupira v lekseme Ignorira komentarje Drži sled za ``trenutno vrstico'' Razširja makroje Vrača simbole v obliki (ime, kazalec)

Page 5: Prevajalniki

5 od 20

Leksikalni analizator

Izgradimo ga na podlagi vzorcev za lekseme Vzorce zapišemo z regularnimi izrazi Regularni izraz, ki opiše identifikatorje za C

(imena spremenljivk, funkciji, ...)

ID → (CRKA | ST)(CRKA | ST | _)* CRKA → A | … | z ST → 0 | … | 9

Page 6: Prevajalniki

6 od 20

Leksikalni analizator

• Pri prepoznavi ključnih besed, kot je if, se pojavi problem, ker slednja ustreza tudi vzorcu za identifikator

• Problem rešimo tako, da ključne besede vnaprej vpišemo v simbolno tabelo

• Če nek niz ustreza več vzorcem, izberemo ``najdaljšega’’; npr. za elseif ne vrnemo (else,0), (if,1), temveč (elseif,0)

Page 7: Prevajalniki

7 od 20

Leksikalni analizator

• Primer: izraz x := (a + b) * c;• Za zgornji izraz bi lahko dobili sekvenco simbolov

• (id,1), (assign,null), (paren,2), (id, 3), (aop, 4), (id, 5), (aop, 6), (id, 7), (term, null)

• Leksikalni analizator ne generira sekvenc ``sam po sebi’’

• Kliče ga parser, ki zahteva naslednji simbol z vhoda

• Zato moramo simbole prepoznati čim hitreje

Page 8: Prevajalniki

8 od 20

Leksikalni analizator

• Sodelovanje parserja in leksikalnega analizatorja

Page 9: Prevajalniki

9 od 20

Leksikalni analizator

• Za hitro prepoznavo simbolov lahko uporabimo Aho-Corasick algoritem

• Generalizacija KMP algoritma za iskanje vzorca v nizu; časovna kompleksnost O(n + m), kjer je n dolžina niza in m dolžina vzorca

• Za preproste prevajalnike kot je naš, je sprejemljivo tudi naivnejše iskanje

Page 10: Prevajalniki

10 od 20

Leksikalni analizator

Na podlagi regularnih izrazov sestavimo tranzicijski diagram ali simuliramo končni avtomat

Leksikalne analizatorje lahko generiramo na podlagi opisa vzorcev

Primera takih orodij sta Lex in Flex

Page 11: Prevajalniki

11 od 20

Simbolna tabela

Podatkovna struktura Ponavadi implementirana kot razpršena tabela

(hashtable) Hrani podatke o konstruktih izvornega programa

(tip spremenljivke, njena vrednost, …) Velike količine podatkov (tudi nekaj 100k vnosov) Hiter dostop Možnost redeklaracije spremenljivk (povezujemo

simbolne tabele v povezan seznam)

Page 12: Prevajalniki

12 od 20

Simbolna tabela

• Naši primeri se poslužujejo kar razredov, ki jih nudita standardni knjižnici Jave in C++

• Kalkulator za simbolno tabelo uporablja Javanski razred Hashtable, prevajalnik pa ``vsebnik’’ std::map

• Slednji je realiziran z rdeče črnim drevesom (simbolna tabela ni nujno razpršena tabela)

Page 13: Prevajalniki

13 od 20

Parser

Zgrajen na podlagi gramatike Dobi simbole, ki jih je vrnil leksikalni analizator Na podlagi slednjih preveri, če lahko gramatika

izpelje program (sintaktična pravilnost programa) Lahko vključuje preverjanje tipov Generira ustrezna poročila o napakah (npr.

Pričakoval ')' ) Sestavi drevo izpeljav

Page 14: Prevajalniki

14 od 20

Parser

Primer LR gramatike za aritmetične izraze

E → E + T | E – T | T T → T * F | T / F | F F → (E) | id | num Primer niza, ki ga lahko generira zgornja

gramatika je '3+4' Imamo izpeljavo E => E + T => T + T

=> F + T => 3 + T => 3 + F => 3 + 4

Page 15: Prevajalniki

15 od 20

Parser

• Vsi naši primeri implementirajo rekurziven LL(k) parser

• Za vsak nekončen simbol gramatike se implementira funkcijo

• Parser se za razširitev produkta odloča na podlagi enega znaka v naprej (lookahead)

• Če vhodni simbol ne ustreza nobenemu produktu, javi napako

• Gre za top-down pristop

Page 16: Prevajalniki

16 od 20

Generator kode

• Za vsako produkcijo gramatike določimo dogodek

• Problem nastane pri generiranju kode za konstrukte, ki vključujejo pogojne in/ali nepogojne skoke

• Rešujemo z ``rezerviranjem’’ label, na katere smo generirali skoke

• Posledica je redundantna koda; odvečne labele in skoki, …

• Lahko rešimo s preprostimi optimizacijskimi metodami

Page 17: Prevajalniki

17 od 20

Generiranje kode

• Naš prevajalnik porabi končno mnogo registrov• V realnosti imamo omejeno količino registrov,

recimo k• To je problem alokacije in dodeljevanja registrov• Je NP-poln (l. 1982 je Chaitin barvanje grafa

reduciral v alokacijo registrov)• Registre lahko alociramo z barvanjem grafa (iz kode

programa zgradimo graf)• Če je kromatično število grafa > k, potem je

potrebno generirati ``spill code.’’

Page 18: Prevajalniki

18 od 20

Uporaba na drugih področjih

• Opisane tehnike niso omejene le na prevajalniško tehnologijo

• Z gramatikamo lahko opišemo protokol (lep primer je IRC protokol, opisan z ABFN) in zanj napišemo parser

• Prepoznava vzorcev v nizu je uporabna vsepovsod; npr. vsak urejevalnik besedil ima možnost iskanja niza v dokumentu

• Z gramatikami so poskusili opisati tudi naravni jezik (izkaže se, da je razred KNG gramatik je za to prešibek)

Page 19: Prevajalniki

19 od 20

Gramatika našega jezika

program -> dcls block

block -> { stmts }

decls -> decls decl

decl -> type var

var -> id, var | id;

stmts -> stmts stmt

stmt -> expr

| if(bool) block

| if(bool) block else block

| while(bool) block

| break

| continue

| block

bool -> bool || join | joinjoin -> join && equ | equequ -> equ = rel j equ <> rel j relrel -> expr > expr j expr < exprexpr -> expr + term | expr - term | termterm -> term * un | term / un | term%un | unun -> -un | facfac -> (bool) | id | num | real

Page 20: Prevajalniki

20 od 20

Primer izvornega programa

int i, j, m, n;

{

i := 2; m := 0; n := 1000;

while(i < n) {

j := i - 1;

while(j > 1) {

if(i % j != 0) { break; }

j := j - 1;

}

if(j = 1) { m := m + 1; }

i := i + 1;

}

}