Šta je prevodilac. Programski jezici. kompajleri i interpretatori. Algoritam jednostavnog tumača

Konkretni izvršioci programskih jezika su prevodioci i tumači.

Prevodilac je program na osnovu kojeg kompjuter konvertuje unesene programe u mašinski jezik, budući da može da izvršava programe napisane samo na jeziku njegovog procesora, a algoritmi navedeni na drugom jeziku moraju biti prevedeni u mašinski jezik pre nego što se izvrše .

Prevodilac- program ili tehničko sredstvo kojim se vrši emitovanje programa.

Emitovanje programa- transformacija programa predstavljenog na jednom od programskih jezika u program na drugom jeziku, ekvivalentan u smislu rezultata prvog. Prevoditelj obično vrši i dijagnostiku grešaka, generira rječnike identifikatora, ispisuje tekstove programa itd.

Poziva se jezik na kojem je predstavljen ulazni program original jezik, a sam program - izvorni kod. Izlazni jezik se naziva ciljni jezik ili objektivan kod. Svrha prijevoda je pretvaranje teksta s jednog jezika na drugi koji je razumljiv primaocu teksta. U slučaju programa prevoditelja, odredište je tehnički uređaj(procesor) ili program tumača.

Prevodioci su implementirani kao prevodioci ili prevodioci. Što se tiče obavljanja posla, kompajler i interpreter se veoma razlikuju.

Jezik procesora (mašinski kod) je niskog nivoa. Poziva se prevodilac koji pretvara programe u mašinski jezik koji se prihvata i izvršava direktno od strane procesora kompajler.

Kompajler(engleski) kompajler- kompajler, kolektor) čita ceo program, prevodi ga i kreira kompletnu verziju programa na mašinskom jeziku, koja se zatim izvršava. Izlaz kompajlera je binarna izvršna datoteka.

Prednost kompajlera: program se kompajlira jednom i nisu potrebne dodatne transformacije za svako izvršavanje. Shodno tome, kompajler nije potreban na ciljnoj mašini za koju se program kompajlira. Nedostatak: poseban korak kompilacije usporava pisanje i otklanjanje grešaka i otežava pokretanje malih, jednostavnih ili jednokratnih programa.

Ako je izvorni jezik asemblerski jezik (jezik niskog nivoa blizak mašinskom jeziku), onda se prevodilac takvog jezika zove asembler.

Drugi metod implementacije je kada se program izvršava sa tumač nema prevoda uopšte.

Tumač(engleski) tumač- interpreter, interpreter) prevodi i izvršava program red po red.

Tumač programski simulira mašinu čija petlja dohvati-izvrši radi na instrukcijama na jezicima visokog nivoa, a ne na mašinskim instrukcijama. Takvo softversko modeliranje stvara virtuelnu mašinu koja implementira jezik. Ovaj pristup se zove čista interpretacija. Čista interpretacija se obično koristi za jezike sa jednostavnom strukturom (na primjer, APL ili Lisp). Tumači komandna linija obraditi komande u skriptama na UNIX-u ili u batch fajlovima (.bat) na MS-DOS-u, takođe obično u čistom režimu interpretacije.

Prednost čistog tumača: odsustvo posrednih radnji za prevođenje pojednostavljuje implementaciju tumača i čini ga pogodnijim za korištenje, uključujući i u interaktivnom načinu. Nedostatak je što interpreter mora biti dostupan na ciljnoj mašini na kojoj se program treba izvršiti. Takođe, po pravilu dolazi do manje ili više značajnog gubitka u brzini. A svojstvo čistog interpretatora, da se greške u interpretiranom programu otkrivaju samo kada se pokuša izvršiti naredba (ili linija) sa greškom, može se prepoznati i kao nedostatak i kao prednost.

Postoje kompromisi između kompilacije i čiste interpretacije implementacije programskog jezika, kada interpretator, prije izvršavanja programa, prevodi ga u međujezik (na primjer, u bytecode ili p-code), što je pogodnije za interpretaciju (tj. govorimo o tumaču sa ugrađenim prevodiocem) . Takav metod se zove mješovita implementacija. Perl je primjer implementacije mješovitih jezika. Ovaj pristup kombinuje prednosti kompajlera i interpretatora (veća brzina izvršavanja i jednostavnost upotrebe) i nedostatke (potrebni su dodatni resursi za prevođenje i skladištenje programa na srednjem jeziku; mora se obezbediti tumač za izvršavanje programa na ciljna mašina). Baš kao iu slučaju kompajlera, mješovita implementacija to zahtijeva prije izvršavanja izvor nije sadržavao greške (leksičke, sintaksičke i semantičke).

Sa povećanjem računarskih resursa i širenjem heterogenih mreža (uključujući Internet) koje povezuju računare različitih tipova i arhitektura, pojavila se nova vrsta interpretacije, u kojoj se izvorni (ili posredni) kod kompajlira u mašinski kod direktno u toku rada. , "u letu". Već kompajlirani delovi koda se keširaju tako da kada im se ponovo pristupi, odmah dobijaju kontrolu, bez ponovne kompilacije. Ovaj pristup je nazvan dinamička kompilacija.

Prednost dinamičke kompilacije je u tome što brzina interpretacije programa postaje uporediva sa brzinom izvršavanja programa u konvencionalnim kompajliranim jezicima, dok se sam program pohranjuje i distribuira u jednom obliku, nezavisno od ciljnih platformi. Nedostatak je veća složenost implementacije i veći zahtjevi za resursima nego u slučaju jednostavnih kompajlera ili čistih interpretatora.

Ova metoda je vrlo pogodna za web aplikacije. Shodno tome, pojavila se dinamička kompilacija koja je donekle podržana u implementacijama Jave, . NET Framework, Perl, Python.

Jednom kada je program preveden, ni izvorni kod programa ni kompajler nisu potrebni za pokretanje programa. Istovremeno, program koji tumači obrađuje mora biti ponovo preveden na mašinski jezik svaki put kada se program pokrene. To jest, izvorna datoteka je direktno izvršna.

Prevedeni programi rade brže, ali interpretirane programe je lakše popraviti i promijeniti.

Svaki određeni jezik je fokusiran ili na kompilaciju ili interpretaciju, ovisno o svrsi za koju je stvoren. Na primjer, C++ se obično koristi za rješavanje prilično složenih problema u kojima je važna brzina programa, pa se ovaj jezik implementira pomoću kompajlera.

Da bi se postigla veća brzina programa u interpretiranim programskim jezicima, može se koristiti prijevod u srednji bajt kod. Jezici koji dozvoljavaju ovaj trik su Java, Python i neki drugi programski jezici.

Algoritam jednostavnog tumača:

2. analizirati uputstvo i odrediti odgovarajuće radnje;

3. poduzeti odgovarajuće mjere;

4. ako uslov završetka programa nije dostignut, pročitajte sljedeću instrukciju i idite na korak 2

Programski jezici se mogu podijeliti na kompajlirane i interpretirane.

Program na kompajliranom jeziku se konvertuje (prevodi) u skup instrukcija za ovog tipa procesora (mašinskog koda), a zatim se upisuje u izvršni modul, koji se može pokrenuti za izvršenje kao poseban program. Drugim riječima, prevodilac prevodi izvorni kod programa iz programskog jezika visokog nivoa u binarne kodove instrukcija procesora.

Ako je program napisan na interpretiranom jeziku, onda tumač direktno izvršava (tumači) izvorni tekst bez prethodnog prijevoda. Program ostaje na svom originalnom jeziku i ne može se pokrenuti bez tumača. Možemo reći da je računarski procesor tumač mašinskog koda.

Ukratko, prevodilac prevodi izvorni kod programa u mašinski jezik odmah i u potpunosti, stvarajući poseban izvršni program, a tumač izvršava izvorni kod neposredno tokom izvršavanja programa.

Podjela na kompajlirane i interpretirane jezike je donekle proizvoljna. Dakle, za bilo koji tradicionalno kompajlirani jezik, kao što je Pascal, možete napisati tumač. Osim toga, većina modernih "čistih" interpretatora ne izvršavaju jezičke konstrukcije direktno, već ih kompajliraju u neku srednju reprezentaciju visokog nivoa (na primjer, s promjenljivom dereferenciranjem i makro ekspanzijom).

Za bilo koji interpretirani jezik možete kreirati kompajler - na primjer, jezik Lisp, izvorno interpretiran, može se kompajlirati bez ikakvih ograničenja. Kod generiran u vrijeme izvođenja također se može dinamički kompajlirati u vrijeme izvođenja.

U pravilu, kompajlirani programi rade brže i ne zahtijevaju dodatni programi, pošto su već prevedeni na mašinski jezik. Istovremeno, sa svakom promjenom teksta programa potrebna je njegova ponovna kompilacija, što stvara poteškoće u razvoju. Osim toga, kompajlirani program može raditi samo na istom tipu računara, i obično pod istim operativnim sistemom, za koji je kompajler i dizajniran. Da biste kreirali izvršni fajl za drugu vrstu mašine, potrebna je nova kompilacija.

Interpretirani jezici imaju neke specifične dodatne karakteristike (vidi gore), osim toga, programi u njima se mogu pokrenuti odmah nakon modifikacije, što olakšava razvoj. Program interpretiranog jezika se često može pokrenuti na mnogo različitih tipova mašina i operativnih sistema bez dodatnog napora.

Međutim, interpretirani programi rade znatno sporije od kompajliranih programa i ne mogu se izvoditi bez dodatnog programa tumača.

Neki jezici, kao što su Java i C#, spadaju između kompajliranih i interpretiranih. Naime, program se ne kompajlira u mašinski jezik, već u niskorazinski mašinski nezavisan kod, bajt kod. Zatim se izvršava bajtkod virtuelna mašina. Za izvršenje bajtkoda obično se koristi interpretacija, iako se neki od njegovih dijelova mogu prevesti u mašinski kod direktno tokom izvršavanja programa koristeći Just-in-time kompilaciju (JIT) kako bi se program ubrzao. Za Javu, bajt kod se izvršava virtuelnim Java mašina(Java virtuelna mašina, JVM), za C# - Common Language Runtime.

Ovaj pristup vam u određenom smislu omogućava da koristite prednosti i interpretatora i kompajlera. Treba spomenuti i originalni jezik Forth, koji ima i tumača i kompajlera.

Pošto je tekst napisan programskim jezikom nerazumljiv za računar, potrebno ga je prevesti u mašinski kod. Takav prevod programa iz programskog jezika u jezik mašinskog koda naziva se prevođenje, a izvode ga posebni programi - prevodioci.

Prevoditelj - pomoćni program koji pretvara izvorni program koji se nalazi u ulaznom programskom jeziku u program rada predstavljen u objektnom jeziku.

Trenutno su kompajleri podijeljeni u tri glavne grupe: asembleri, kompajleri i interpretatori.

Assembler je sistemski uslužni program koji pretvara simboličke konstrukcije u instrukcije mašinskog jezika. Specifičnost asemblera je da doslovno prevode jednu simboličku instrukciju u jednu mašinsku instrukciju. Stoga je asemblerski jezik (koji se naziva i autokod) dizajniran da olakša percepciju kompjuterskog skupa instrukcija i ubrza programiranje u ovom skupu instrukcija. Programeru je mnogo lakše da zapamti mnemoničku oznaku mašinskih instrukcija nego njihov binarni kod.

Istovremeno, asemblerski jezik, pored analoga mašinskih instrukcija, sadrži mnoge dodatne direktive koje olakšavaju, posebno, upravljanje računarskim resursima, pisanje fragmenata koji se ponavljaju i pravljenje multimodulnih programa. Stoga je ekspresivnost jezika mnogo bogatija od samog jezika simboličkog kodiranja, što uvelike povećava efikasnost programiranja.

Kompajler je pomoćni program koji prevodi na mašinski jezik program napisan u izvornom programskom jeziku. Baš kao asembler, kompajler pretvara program iz jednog jezika u drugi (najčešće u jezik određenog računara). Međutim, naredbe izvornog jezika značajno se razlikuju po organizaciji i snazi ​​od naredbi strojnog jezika. Postoje jezici u kojima je jedna instrukcija izvornog jezika prevedena u 7-10 mašinskih instrukcija. Međutim, postoje i jezici u kojima svaka instrukcija može odgovarati 100 ili više strojnih instrukcija (na primjer, Prolog). Osim toga, u izvornim jezicima često se koristi striktno kucanje podataka koje se provodi kroz njihov preliminarni opis. Programiranje se možda neće oslanjati na kodiranje algoritma, već na pažljivo razmišljanje o strukturama podataka ili klasama. Proces prevođenja sa takvih jezika obično se naziva kompilacija, a izvorni jezici se obično nazivaju programski jezici visokog nivoa (ili jezici visokog nivoa). Apstrakcija programskog jezika iz komandnog sistema računara dovela je do nezavisnog stvaranja širokog spektra jezika fokusiranih na rešavanje specifičnih problema. Pojavili su se jezici za naučne proračune, ekonomske proračune, pristup bazama podataka i drugo.

Interpretator je program ili uređaj koji obavlja translaciju od operatora do operatera i izvršavanje originalnog programa. Za razliku od kompajlera, tumač ne proizvodi program na mašinskom jeziku kao izlaz. Nakon što prepozna komandu izvornog jezika, ona je odmah izvršava. I prevodioci i prevodioci koriste iste metode raščlanjivanja izvornog koda programa. Ali tumač vam omogućava da započnete obradu podataka nakon što napišete čak i jednu naredbu. Ovo čini proces razvoja i otklanjanja grešaka fleksibilnijim. Osim toga, nedostatak izlaznog mašinskog koda omogućava vam da ne "bacite smeće" eksternih uređaja dodatni fajlovi, a sam interpreter se može prilično lako prilagoditi bilo kojoj arhitekturi stroja razvijajući ga samo jednom u široko korišćenom programskom jeziku. Stoga su interpretirani jezici kao što su Java Script, VB Script postali široko rasprostranjeni. Nedostatak interpretatora je mala brzina izvršavanja programa. Obično interpretirani programi rade 50 do 100 puta sporije od programa napisanih u mašinskom kodu.

Emulator je program ili softver i hardverski alat koji pruža mogućnost izvršavanja programa na datom računaru bez reprogramiranja, koristeći kodove ili metode za izvođenje operacija koje se razlikuju od ovog računara. Emulator je sličan tumaču po tome što direktno izvršava program napisan na nekom jeziku. Međutim, najčešće je to strojni jezik ili srednji kod. Oba predstavljaju instrukcije u binarnom kodu koje se mogu izvršiti odmah nakon prepoznavanja koda operacije. Za razliku od tekstualnih programa, nije potrebno prepoznati strukturu programa, odabrati operande.

Emulatori se često koriste u različite svrhe. Na primjer, prilikom razvoja novih računarskih sistema, prvo se kreira emulator koji pokreće programe koji se razvijaju za računare koji još ne postoje. Ovo vam omogućava da procenite komandni sistem i razvijete osnovnu softverčak i prije nego što se stvori odgovarajuća oprema.

Vrlo često se emulator koristi za pokretanje starih programa na novim računarima. Tipično, noviji računari su brži i imaju bolje periferne uređaje. Ovo vam omogućava da efikasnije emulirate starije programe od pokretanja na starijim računarima.

Transkoder - program ili softverski uređaj koji prevodi programe napisane na mašinskom jeziku jednog računara u programe na mašinskom jeziku drugog računara. Ako je emulator manje inteligentan analog interpretatora, onda transkoder djeluje u istom svojstvu u odnosu na kompajler. Slično, izvorni (i obično binarni) mašinski kod ili međureprezentacija se pretvara u drugi sličan kod u jednoj instrukciji i bez ikakve opšte analize strukture izvornog programa. Transkoderi su korisni kada se programi prenose sa jedne računarske arhitekture na drugu. Mogu se koristiti i za rekonstrukciju teksta programa jezika visokog nivoa iz dostupnog binarnog koda.

Makroprocesor je program koji zamjenjuje jedan niz znakova drugim. To je vrsta kompajlera. Generiše izlazni tekst obradom posebnih umetaka koji se nalaze u izvornom tekstu. Ovi umetci su napravljeni na poseban način i pripadaju jezičkim konstrukcijama koje se nazivaju makro jezik. Makroprocesori se često koriste kao dodaci programskim jezicima, povećavajući funkcionalnost programskih sistema. Gotovo svaki asembler sadrži makroprocesor, koji povećava efikasnost razvoja mašinskih programa. Takvi programski sistemi se obično nazivaju makro asemblerima.

Makroprocesori se takođe koriste sa jezicima visokog nivoa. Oni povećavaju funkcionalnost jezika kao što su PL/1, C, C++. Makroprocesori se posebno široko koriste u C i C++, što olakšava pisanje programa. Makroprocesori povećavaju efikasnost programiranja bez promjene sintakse i semantike jezika.

Sintaksa - skup pravila određenog jezika koji određuju formiranje njegovih elemenata. Drugim riječima, to je skup pravila za formiranje semantički značajnih nizova znakova u datom jeziku. Sintaksa je specificirana pomoću pravila koja opisuju koncepte određenog jezika. Primjeri koncepata su: varijabla, izraz, operator, procedura. Redoslijed pojmova i njihova dopuštena upotreba u pravilima određuju se sintaksički ispravne strukture, formiranje programa. Sintaksom je definirana hijerarhija objekata, a ne način na koji oni međusobno djeluju. Na primjer, operator se može pojaviti samo u proceduri, dok se izraz u operatoru, varijabla može sastojati od imena i opcijskih indeksa, itd. Sintaksa nije povezana sa pojavama u programu kao što su "skakanje na nepostojeću oznaku" ili "promenljiva sa datim imenom nije definisana". To je ono što semantika radi.

Semantika - pravila i uvjeti koji određuju odnos između elemenata jezika i njihovih semantičkih značenja, kao i tumačenje značenja značenja sintaksičkih konstrukcija jezika. Objekti programskog jezika ne samo da se postavljaju u tekst u skladu sa određenom hijerarhijom, već su i dodatno međusobno povezani preko drugih koncepata koji formiraju različite asocijacije. Na primjer, varijabla za koju sintaksa definira ispravnu lokaciju samo u deklaracijama i nekim izjavama, ima specifičan tip, može se koristiti s ograničenim skupom operacija, ima adresu, veličinu i mora biti deklarirana prije upotrebe u program.

Parser je komponenta kompajlera koja provjerava usklađenost izvornih izjava sa sintaksnim pravilima i semantikom datog programskog jezika. Uprkos nazivu, analizator provjerava i sintaksu i semantiku. Sastoji se od nekoliko blokova, od kojih svaki rješava svoje probleme. To će se detaljnije razmotriti kada se opisuje struktura prevodioca. programiranje jezika prevodioca kompajlera

Svaki prevodilac obavlja sljedeće glavne zadatke:

  • - analizira emitovani program, posebno utvrđuje da li sadrži sintaksičke greške;
  • - generiše izlazni program (često se naziva objektni program) na jeziku mašinskih instrukcija;
  • - dodjeljuje memoriju za objektni program.1.1 Tumači

Jedna često citirana prednost implementacije interpretatora je da dozvoljava "neposredan način rada". Neposredni režim vam omogućava da postavite računaru zadatak kao što je PRINT 3.14159*3/2.1 i vraća vam odgovor čim pritisnete ENTER (ovo vam omogućava da koristite računar od 3.000 dolara kao kalkulator od 10 dolara). Osim toga, tumači imaju posebne atribute koji olakšavaju otklanjanje grešaka. Možete, na primjer, prekinuti obradu programa interpretatora, prikazati sadržaj određenih varijabli, preletjeti program, a zatim nastaviti s izvršavanjem.

Ono što programeri najviše vole kod tumača je mogućnost brzog odgovora. Ovde nema potrebe za kompilacijom, jer je tumač uvek spreman da interveniše u vašem programu. Unesite RUN i rezultat je vaš poslednja promena na ekranu se pojavi.

Međutim, jezici tumača imaju nedostatke. Neophodno je, na primjer, imati kopiju interpretatora u memoriji u svakom trenutku, dok mnoge karakteristike interpretatora, a time i njegove karakteristike, možda neće biti potrebne za izvršavanje određenog programa.

Suptilni nedostatak tumača je to što oni obično obeshrabruju dobar stil programiranja. Budući da komentari i drugi formalizirani detalji zauzimaju mnogo programske memorije, ljudi ih obično ne koriste. Đavo je manje bijesan od BASIC programera tumača koji pokušava ubaciti 120K programa u 60K memoriju. ali što je najgore, prevodioci su spori.

Oni provode previše vremena smišljajući šta da rade umjesto da rade stvarnu stvar. Prilikom izvršavanja programskih izraza, tumač prvo mora skenirati svaku naredbu kako bi pročitao njen sadržaj (šta ova osoba traži od mene?), a zatim izvršiti traženu operaciju. Izjave u petljama se previše skeniraju.

Razmotrite program: na interpretatoru BASIC 10 ZA N=1 DO 1000 20 PRINT N,SQR(N) 30 NEXT N na prvom prelazu kroz ovaj program, BASIC Interpreter mora pogoditi šta red 20 znači:

  • 1. pretvoriti numeričku varijablu N u niz
  • 2. pošaljite niz na ekran
  • 3. pređite na sledeću oblast za štampanje
  • 4. izračunaj kvadratni korijen od N
  • 5. pretvoriti rezultat u string
  • 6. pošaljite niz na ekran

U drugom prolazu petlje, sve ovo nagađanje se ponovo ponavlja, pošto su svi rezultati proučavanja ovog niza prije nekoliko milisekundi potpuno zaboravljeni. I tako u svih narednih 998 prolaza. Očigledno, ako biste mogli nekako odvojiti fazu skeniranja/razumijevanja od faze izvršenja, imali biste više brzi program. A kompajleri su upravo za to.


4. Osnovni principi konstruisanja prevodilaca. Prevodioci, prevodioci i tumači - opća šema rada. Savremeni prevodioci i prevodioci.

Osnovni principi konstruisanja prevodilaca.

Prevodioci, prevodioci, tumači - opća šema rada.

Definicija prevodioca, kompajlera, tumača

Za početak, dajmo nekoliko definicija – koji su prevodioci i prevodioci već spominjani mnogo puta.

Formalna definicija prevodioca

Prevodilac je program koji prevodi ulazni program na izvornom (ulaznom) jeziku u ekvivalentan izlazni program u rezultirajućem (izlaznom) jeziku. U ovoj definiciji, riječ "program" se pojavljuje tri puta, i to nije greška ili tautologija. Zaista, u radu prevodioca uvijek učestvuju tri programa.

Prvo, sam prevodilac je program 1 - obično je uključen u sistemski softver računarskog sistema. Odnosno, prevodilac je deo softvera (softvera), on je skup mašinskih instrukcija i podataka i izvršava ga računar, kao i svi drugi programi u okviru operativnog sistema (OS). Sve komponente prevodioca su fragmenti ili moduli programa sa sopstvenim ulaznim i izlaznim podacima.

Drugo, početni podatak za rad prevodioca je tekst ulaznog programa - neki niz rečenica ulaznog programskog jezika. Ovo je obično datoteka znakova, ali ova datoteka mora sadržavati programski tekst koji zadovoljava sintaktičke i semantičke zahtjeve jezika unosa. Osim toga, ova datoteka nosi neko značenje, određeno semantikom jezika unosa.

Treće, izlaz prevodioca je tekst rezultirajućeg programa. Rezultirajući program je izgrađen prema sintaksičkim pravilima navedenim u izlaznom jeziku prevodioca, a njegovo značenje je određeno semantikom izlaznog jezika. Važan zahtjev u definiciji prevoditelja je ekvivalentnost ulaznih i izlaznih programa. Ekvivalencija dva programa znači podudarnost njihovog značenja u smislu semantike ulaznog jezika (za izvorni program) i semantike izlaznog jezika (za rezultujući program). Bez ispunjavanja ovog zahtjeva, sam prevodilac gubi svako praktično značenje.

Dakle, da biste kreirali prevodioca, prvo morate odabrati jezike za unos i izlaz. Sa stanovišta pretvaranja rečenica na ulaznom jeziku u ekvivalentne rečenice na izlaznom jeziku, prevodilac se ponaša kao prevodilac. Na primjer, prevođenje programa iz C u asemblerski jezik u suštini se ne razlikuje od prevođenja, recimo, s ruskog na engleski, s jedinom razlikom što je složenost jezika nešto drugačija (zašto nema prevodilaca s prirodnih jezika ​​- vidi odeljak „Klasifikacioni jezici i gramatike, poglavlje 9). Dakle, sama riječ "prevodilac" (engleski: translator) znači "prevodilac".

Rezultat rada prevodioca biće rezultujući program, ali samo ako je tekst izvornog programa tačan - ne sadrži greške u pogledu sintakse i semantike jezika unosa. Ako je izvorni program pogrešan (sadrži barem jednu grešku), tada će rezultat rada prevoditelja biti poruka o grešci (u pravilu, s dodatnim objašnjenjima i naznakom lokacije greške u izvornom programu). U tom smislu, prevodilac je sličan prevodiocu, na primer, sa engleskog, kome je ubačen pogrešan tekst.

Teoretski, moguće je implementirati prevodilac pomoću hardvera. Autor se susreo s takvim razvojem, ali njihova široka praktična primjena nije poznata. U ovom slučaju, sve komponente translatora mogu se implementirati u obliku hardvera i njihovih fragmenata - tada kolo prepoznavača može dobiti potpuno praktičnu implementaciju!

definicija kompajlera.

Razlika između prevodioca i prevodioca

Pored pojma "prevodilac", široko se koristi i koncept "kompilatora", koji mu je blizak po značenju.

kompajler - je prevodilac koji prevodi izvorni program u njegov ekvivalentni objektni program na mašinskom ili asemblerskom jeziku.

Dakle, kompajler se razlikuje od prevodioca samo po tome što njegov rezultujući program uvek mora biti napisan u mašinskom kodu ili asemblerskom jeziku. Rezultirajući program prevodioca, općenito, može se napisati na bilo kojem jeziku - moguće je, na primjer, prevesti programe iz Pascal u C. Prema tome, svaki prevodilac je prevodilac, ali ne i obrnuto - neće svaki prevodilac biti prevodilac . Na primjer, gore spomenuti prevoditelj sa Pascala na C neće biti 1.

Sama riječ "kompajler" dolazi od engleski termin"kompajler" ("kompajler", "linker"). Očigledno, pojam duguje svoje porijeklo sposobnosti kompajlera da kreiraju objektne programe zasnovane na izvornim programima.

Rezultirajući program kompajlera naziva se "program objekta" ili "objektni kod". Datoteka u koju se upisuje obično se naziva "objektni fajl". Čak i kada je rezultujući program generisan na mašinskom jeziku, postoji značajna razlika između objektnog programa (objektne datoteke) i izvršnog programa (izvršne datoteke). Program koji generiše kompajler ne može se direktno izvršavati na računaru, jer nije vezan za određenu memorijsku oblast gde bi trebalo da se nalaze njegov kod i podaci (za više detalja pogledajte odeljak „Principi funkcionisanja programskih sistema“, Poglavlje 15 ) 2 .

Kompajleri su daleko najčešća vrsta kompajlera (mnogi ih smatraju jedinom vrstom kompajlera, iako to nisu). Imaju najširu praktičnu primenu, što je posledica široke distribucije svih vrsta programskih jezika. U nastavku ćemo uvijek govoriti o kompajlerima, što znači da je izlazni program napisan

Naravno, prevodioce i kompajlere, kao i sve druge programe, razvija osoba (ljudi) - obično grupa programera. U principu, mogli bi ga kreirati direktno u jeziku mašinskih instrukcija, ali količina koda i podataka savremenih kompajlera je tolika da je njihovo kreiranje u jeziku mašinskih instrukcija gotovo nemoguće u razumnom roku uz razumne troškove rada. Stoga se gotovo svi moderni prevodioci također kreiraju pomoću kompajlera (obično u toj ulozi nastupaju prethodne verzije kompajlera istog proizvođača). I u ovom svojstvu, kompajler je već izlazni program za drugi kompajler, koji nije ništa bolji ni lošiji od svih ostalih generisanih izlaznih programa 2 .

Definicija tumača. Razlika između tumača i prevodioca

Pored sličnih koncepata "prevodilac" i "kompilator", postoji fundamentalno drugačiji koncept tumača.

Tumač - to je program koji uzima ulazni program u izvornom jeziku i izvršava ga.

Za razliku od prevoditelja, tumači ne generiraju rezultirajući program (ili bilo koji rezultirajući kod općenito) - i to je fundamentalna razlika između njih. Tumač, kao i prevodilac, analizira tekst izvornog programa. Međutim, on ne generiše rezultirajući program, već odmah izvršava originalni program u skladu sa njegovim značenjem datim semantikom ulaznog jezika. Dakle, rezultat interpretera će biti rezultat dat značenjem izvornog programa, ako je ovaj program ispravan, ili poruka o grešci ako je izvorni program netačan.

Naravno, da bi izvršio izvorni program, tumač mora nekako da ga konvertuje u mašinski jezik, jer je u suprotnom nemoguće pokrenuti programe na računaru. To čini, ali rezultirajući mašinski kodovi nisu dostupni - nisu vidljivi korisniku interpretatora. Ove mašinske kodove generiše interpretator, izvršavaju se i uništavaju

1 Posebno treba napomenuti da su se sada u modernim programskim sistemima počeli pojavljivati ​​kompajleri u kojima se rezultirajući program kreira ne na jeziku mašinskih instrukcija i ne na asembleru, već na nekom međujeziku. Sam po sebi, ovaj međujezik se ne može direktno izvršavati na računaru, ali zahteva poseban posredni tumač za izvršavanje programa napisanih na njemu. Iako bi u ovom slučaju termin "prevodilac" vjerovatno bio ispravniji, u literaturi se koristi termin "prevodilac", budući da je srednji jezik jezik vrlo niskog nivoa, koji se odnosi na mašinske instrukcije i asemblerske jezike.

Ovo dovodi do prastarog pitanja kokoške i jaja. Naravno, u prvoj generaciji, prvi kompajleri su pisani direktno u mašinskim uputstvima, ali je onda, sa pojavom kompajlera, ova praksa napuštena. Čak i najkritičniji dijelovi kompajlera se kreiraju, u najmanju ruku, korištenjem asemblerskog jezika - i to također obrađuje kompajler. tozhayutsya po potrebi - kako to zahtijeva konkretna implementacija) tumača. Korisnik vidi rezultat izvršenja ovih kodova - postoji rezultat izvršenja izvornog programa (zahtev za ekvivalentnost izvornog programa i generisanih mašinskih kodova u ovom slučaju, (uslovno, mora biti ispunjen).

Detaljnije, pitanja vezana za implementaciju interpretatora i njihovo odstupanje od kompajlera razmatraju se kasnije u odgovarajućem odeljku.

Namjena prevodilaca, kompajlera i tumača. Primjeri implementacije

Prvi programi koji su kreirani za računare prve generacije napisani su direktno na jeziku mašinskih kodova. Bio je to zaista pakleni posao. Odmah je postalo jasno da osoba ne treba i ne može govoriti jezikom mašinskih komandi, čak i ako je kompjuterski stručnjak. O; Međutim, svi pokušaji da se kompjuter nauči da govori jezike ljudi okrunjeni su uspjehom i malo je vjerovatno da će ikada biti okrunjeni (za što postoje određeni pozitivni razlozi o kojima se govori u prvom poglavlju ovog priručnika).

Od tada je cjelokupni razvoj kompjuterskog softvera neraskidivo povezan sa pojavom i razvojem kompajlera.

Prvi kompajleri bili su kompajleri iz asemblerskih jezika ili, kako su ih zvali, mnemoničkih kodova. Mnemokodovi su pretvorili "filkinovo slovo" mašinskih komandi u više-manje razumljiv jezik za specijaliste - monične (uglavnom engleske) oznake ovih komandi. (Već je postalo mnogo lakše davati programe, ali ni jedan računar nije sposoban da izvrši mnems (jezik asemblera), stoga se pojavila potreba za kreiranjem kompajlera. Ovi prevodioci su elementarni, ali i dalje igraju značajnu ulogu u programski sistemi danas Više detalja o asembleru i kompajlerima iz priče: dalje u odgovarajućem odeljku.

Sljedeći korak bilo je stvaranje jezika visokog nivoa. Jezici visokog nivoa (većina programskih jezika pripada njima) predstavljaju neku srednju vezu između čisto formalnih jezika i jezika prirodne komunikacije ljudi. Od prvog su dobili strogu malizaciju sintaktičke strukture rečenica jezika, od drugog - značajan dio vokabulara, semantiku glavnih struktura i izraza (sa elementima matematičkih operacija koje potiču iz algebre).

Pojava jezika visokog nivoa uvelike je pojednostavila proces programiranja, iako ga nije svela na „nivo domaćice“, kako su neki autori u zoru rođenja programskih jezika arogantno tvrdili 1 . Bilo je malo takvih jezika, zatim na desetine, sada ih je, vjerovatno, više od stotinu. Ovom procesu se ne nazire kraj. Ipak, računari tradicionalne, "Neumann" arhitekture, koji mogu razumjeti samo mašinske instrukcije, i dalje prevladavaju, pa je pitanje kreiranja kompajlera i dalje aktuelno.

Čim se pojavila velika potreba za stvaranjem kompajlera, počela je da se razvija specijalizovana teorija. Vremenom je našla praktičnu primenu u raznim kreiranim kompajlerima. Kompajleri su kreirani i nastavljaju da se stvaraju ne samo za nove, već i za odavno poznate jezike. Mnogi proizvođači od poznatih, renomiranih kompanija (kao što su Microsoft ili Inprise) do malo poznatih autorskih timova objavljuju sve više novih uzoraka kompajlera na tržištu. To je zbog brojnih razloga, o kojima će biti riječi u nastavku.

Konačno, budući da je većina teorijskih aspekata u oblasti kompajlera dobila svoju praktičnu implementaciju (a to se, mora se reći, dogodilo prilično brzo, kasnih 60-ih), razvoj kompajlera je išao putem njihove ljubaznosti prema osoba - korisnik, programer programa na jezicima visokog nivoa. Logičan završetak ovog procesa bio je stvaranje programskih sistema - softverski sistemi, koji kombinuju, pored direktnih kompajlera, mnoge povezane softverske komponente. Nakon što su se pojavili, programski sistemi su brzo osvojili tržište i sada većim dijelom dominiraju na njemu (zapravo, odvojeni kompajleri su rijetkost među modernim softverskim alatima). Za informacije o tome šta su moderni sistemi programiranja i kako su organizovani, pogledajte poglavlje Moderni programski sistemi. Sada su kompajleri sastavni deo svakog računarskog sistema. Bez njihovog postojanja, programiranje bilo kojeg primijenjenog zadatka bilo bi teško, ako ne i nemoguće. A programiranje specijaliziranih sistemskih zadataka, po pravilu, se izvodi ako ne u jeziku visokog nivoa (C trenutno najčešće koristi u ovoj ulozi), onda u asembleru, dakle, koristi se odgovarajući kompajler. Programiranje direktno u jezicima mašinskog koda je izuzetno rijetko i samo za rješavanje vrlo uskih pitanja. Nekoliko riječi o primjerima implementacije kompajlera i interpretatora, kao io tome kako se oni odnose na druge postojeće softverski alati. Kompajlere, kao što će biti pokazano kasnije, obično je nešto lakše implementirati od interpretatora. Što se tiče efikasnosti, oni ih takođe nadmašuju - očigledno je da će se kompajlirani kod uvijek izvršavati brže od interpretacije sličnog izvornog programa. Osim toga, ne dozvoljava svaki programski jezik konstrukciju jednostavnog tumača. Međutim, tumači imaju jednu značajnu prednost – kompajlirani kod je uvijek vezan za arhitekturu računarskog sistema na koji je orijentisan, a izvorni program je vezan samo za semantiku programskog jezika, koji je mnogo lakše standardizovati. Ovaj aspekt je u početku ignorisan. Prvi kompajleri bili su mnemonički kompajleri. Njihovi potomci - moderni kompajleri iz asemblerskih jezika - postoje za gotovo sve poznate računarske sisteme. Izuzetno su strogo fokusirani na arhitekturu. Zatim su tu bili kompajleri iz jezika kao što su FORTRAN, ALGOL-68, PL/1. Bili su fokusirani na mainframe računare sa batch obradom zadataka. Od navedenog, jedino se FORTRAN, možda, i dalje koristi do danas, budući da ima ogroman broj biblioteka za različite namjene. Mnogi jezici, rođeni, nisu postali široko rasprostranjeni - ADA, Modula, Simula poznati su samo uskom krugu stručnjaka. Istovremeno, tržište softverski sistemi dominiraju kompajleri jezika za koje se nije predviđala svetla budućnost. Prije svega, sada su to C i C ++. Prvi od njih je rođen sa operativni sistemi poput UNIX-a, zajedno sa njim je osvojio svoje "mesto na suncu", a zatim prešao na OS drugih tipova. Drugi je u sebi uspješno utjelovio primjer implementacije ideja objektno orijentisanog programiranja na dobro uspostavljenoj praktičnoj osnovi 1 . Možete spomenuti i prilično uobičajen Pascal, koji je, neočekivano za mnoge, izašao iz okvira čisto obrazovnog jezika za univerzitetsko okruženje.

Istorija tumača (još!) nije tako bogata. Kao što je već spomenuto, u početku im se nije pridavao značajniji značaj, jer su u gotovo svim aspektima inferiorni u odnosu na kompajlere. Od poznatih jezika koji su podrazumijevali interpretaciju, može se spomenuti samo Basic, iako većina sada poznaje njegovu kompajliranu implementaciju Visual Basica, koju je napravio Microsoft. Međutim, sada se situacija donekle promijenila, jer s razvojem Interneta pitanje prenosivosti softvera i njihove neovisnosti od hardverske platforme postaje sve važnije. Najpoznatiji primjer danas je jezik Java (koji sam po sebi kombinira kompilaciju i interpretaciju) i pripadajući JavaScript. Na kraju krajeva, HTML jezik, koji podupire HTTP protokol koji je doveo do tako brzog razvoja World Wide Weba, također je interpretirani jezik. Prema autorovim riječima, iznenađenja još uvijek čekaju sve na polju pojave novih tumača, a prvi od njih su se već pojavili - na primjer, jezik C # („C-sharp“, ali ime je posvuda kao “C oštro”), najavio je Microsoft.

O b o istoriji programskih jezika i trenutnom stanju na tržištu kompajlera, možete pričati dugo i puno. Autor smatra da je moguće ograničiti se na ono što je već rečeno, jer to nije svrha ovog priručnika. Oni koji žele mogu se obratiti literaturi.

faze prevođenja. Opća shema prevodioca

Na sl. 13.1 prikazuje opštu šemu kompajlera. Iz toga je jasno da b Općenito, proces kompilacije sastoji se od dvije glavne faze – sinteze i analize.

U fazi analize prepoznaje se tekst izvornog programa, kreiraju se i popunjavaju tabele identifikatora. Rezultat njegovog rada je određena interna reprezentacija programa, razumljiva kompajleru.

U fazi sinteze, na osnovu interne reprezentacije programa i informacija sadržanih u tabeli (tabelama) identifikatora, generiše se tekst rezultujućeg programa. Rezultat ove faze je objektni kod.

Osim toga, kompajler sadrži dio zadužen za analizu i ispravljanje grešaka, koji, ukoliko postoji greška u tekstu izvornog programa, treba što potpunije informirati korisnika o vrsti greške i mjestu njenog nastanka. U najboljem slučaju, kompajler može ponuditi korisniku opciju da popravi grešku.

Ovi koraci se sastoje od manjih koraka koji se nazivaju faze kompilacije. Sastav faza kompilacije dat je u najopštijem obliku, njihova specifična implementacija i proces interakcije

Prvo, to je prepoznavač za jezik izvornog programa. Zatim mora primiti lanac znakova ulaznog jezika kao ulaz, provjeriti pripadnost jeziku i, štaviše, identificirati pravila po kojima je ovaj lanac izgrađen (pošto je odgovor na pitanje o pripadnosti „da“ i „ne“ malo zanima). Zanimljivo je da korisnik, autor ulaznog programa, djeluje kao generator lanaca jezika unosa.

Drugo, kompajler je generator za jezik rezultujućeg programa. On mora izgraditi lanac izlaznog jezika oprahom na izlazu; data pravila, predviđeni mašinski jezik ili jezik i sampler. Prepoznavač ovog lanca biće računarski sistem pod kojim se kreira rezultujući program.

Leksička analiza(skener) je dio kompajlera koji čita literalne programe u izvornom jeziku i od njih gradi riječi (tokene) izvornog jezika. Ulaz leksičkog analizatora prima tekst izvornog programa, a izlazne informacije se prenose na dalju obradu od strane kompajlera u fazi raščlanjivanja. Sa teorijske tačke gledišta, leksički analizator nije obavezan, neophodan dio kompajlera. Međutim, postoje razlozi koji određuju njegovu prisutnost u gotovo svim kompajlerima. Za više detalja pogledajte odjeljak „Leksički analizatori (bilježnici). Principi konstruisanja skenera”.

Parsing je glavni dio kompajlera u fazi analize. O vrši ekstrakciju sintaksičkih konstrukcija u tekstu izvornog programa, koje obrađuje leksički analizator. U istoj fazi kompilacije provjerava se sintaktička ispravnost programa. Parser igra glavnu ulogu – ulogu prepoznavača teksta ulaznog programskog jezika (pogledajte odeljak "Parseri. Sintaksički kontrolisano prevođenje" u ovom poglavlju).

Semantička analiza je dio kompajlera koji provjerava ispravan* tekst izvornog programa u smislu semantike jezika unosa. CRS direktna validacija, semantička analiza mora izvršiti konverziju; Definicije teksta koje zahtijeva semantika izvornog jezika (kao što je dodavanje funkcija implicitne konverzije tipa). U raznim implementacijama komp. Tori, semantička analiza može dijelom ući u fazu sintaktičkog * parsinga, dijelom - u fazu pripreme za generiranje koda.

Priprema za generisanje koda je faza u kojoj kompajler izvodi preliminarne radnje koje su direktno povezane sa sintezom teksta rezultirajućeg programa, ali još ne dovode do generisanja teksta u izlaznom jeziku. Tipično, ova faza uključuje aktivnosti koje se odnose na identifikaciju jezičkih elemenata, dodjelu memorije, itd. (vidi odjeljak "Semantička analiza i priprema za generiranje koda", Poglavlje 14).

Generisanje koda- ovo je faza koja se direktno odnosi na generiranje zareza sastavnih rečenica ciljnog jezika i rezultirajućeg teksta u cjelini

Mogu se, naravno, razlikovati ovisno o verziji kompajlera. Međutim, u ovom ili onom obliku, sve predstavljene faze su gotovo uvijek prisutne u svakom konkretnom kompajleru.

Prevodilac kao cjelina, sa stanovišta teorije formalnih jezika, djeluje u „dvije uloge“, obavlja dvije glavne funkcije. programe. Ovo je glavna faza u fazi sinteze rezultirajućeg programa. Pored direktnog generisanja teksta rezultirajućeg programa, generisanje obično uključuje i optimizaciju – proces povezan sa obradom već generisanog teksta. Ponekad se optimizacija izdvaja kao zasebna faza kompilacije, jer ima značajan uticaj na kvalitet i efikasnost rezultujućeg programa (pogledajte odeljke „Generacija koda. Metode generisanja koda“ i „Optimizacija koda. Osnovne metode optimizacije“, Poglavlje 14 ).

Tabele identifikatora(ponekad "tabele znakova") su posebno organizirani skupovi podataka koji služe za pohranjivanje informacija o elementima izvornog programa, koji se zatim koriste za generiranje teksta rezultirajućeg programa. Može postojati jedna tabela identifikatora u određenoj implementaciji kompajlera, ili može postojati nekoliko takvih tabela. Elementi izvornog programa, informacije o kojima se moraju pohraniti tokom kompilacije, su varijable, konstante, funkcije itd. - specifičan sastav skupa elemenata ovisi o korištenom ulaznom programskom jeziku. Koncept „tabele“ uopšte ne podrazumeva da ovo skladište podataka treba da bude organizovano upravo u obliku tabela ili drugih nizova informacija – moguće metode za njihovo organizovanje detaljno su razmotrene kasnije, u odeljku „Tabele identifikatora. Organizacija tablica identifikatora.

Prikazano na sl. 13.1 Podjela procesa kompilacije na faze služi prije metodološkim svrhama iu praksi se možda neće tako strogo poštovati. Sljedeći pododjeljci ovog priručnika razmatraju različite opcije za tehničku organizaciju predstavljenih faza kompilacije. To ukazuje na to kako oni mogu biti povezani jedni s drugima. Ovdje razmatramo samo opšte aspekte ove vrste odnosa.

Prvo, tokom faze leksičke analize, tokeni se izdvajaju iz teksta ulaznog programa ukoliko su neophodni za sledeću fazu raščlanjivanja. Drugo, kao što će biti prikazano u nastavku, raščlanjivanje i generisanje koda mogu se obaviti u isto vrijeme. Dakle, ove tri faze kompilacije mogu raditi u kombinaciji, a priprema za generiranje koda također se može izvršiti zajedno s njima. Zatim razmatramo tehnička pitanja implementacije glavnih faza kompilacije, koja su usko povezana sa konceptom prolaz.

Koncept prolaza. Višeprolazni i jednoprolazni kompajleri

Kao što je već spomenuto, proces kompajliranja programa sastoji se od nekoliko faza. U stvarnim kompajlerima, sastav ovih faza može se donekle razlikovati od prethodnog - neke od njih se mogu podijeliti na komponente, dok se druge, naprotiv, kombiniraju u jednu fazu. Redoslijed kojim se faze kompilacije izvršavaju također može varirati između različitih varijanti kompajlera. U jednom slučaju, kompajler gleda tekst izvornog programa, odmah izvodi sve faze kompilacije i prima rezultat - objektni kod. U drugoj varijanti, on izvodi samo neke od faza kompilacije na izvornom tekstu i prima ne konačni rezultat, već skup nekih međupodataka. Ovi podaci se zatim ponovo obrađuju, a ovaj proces se može ponoviti nekoliko puta.

Pravi prevodioci, po pravilu, prevode tekst izvornog programa u nekoliko prolaza.

prolaz - ovo je proces sekvencijalnog čitanja od strane kompajlera podataka iz eksterne memorije, njihove obrade i stavljanja rezultata rada u eksternu memoriju. Najčešće, jedan prolaz uključuje izvršenje jedne ili više faza kompilacije. Rezultat međuprolaza je interna reprezentacija izvornog programa, rezultat posljednjeg prolaza je rezultirajući objektni program.

As eksternu memoriju mogu da deluju bilo koji nosioci informacija - RAM računara, drajvovi na magnetnim diskovima, magnetne trake itd. Savremeni kompajleri po pravilu nastoje da maksimalno iskoriste RAM računara za skladištenje podataka, i to samo kada postoji nedostatak raspoložive memorije, koriste se tvrdi magnetni diskovi. Drugi mediji za skladištenje se ne koriste u modernim kompajlerima zbog niske brzine razmene podataka.

Tokom svakog prolaza, kompajler ima pristup informacijama dobijenim iz svih prethodnih prolaza. Po pravilu, on teži da prvenstveno koristi samo informacije dobijene na prolazu koji neposredno prethodi trenutnom, ali u principu može pristupiti podacima od ranijih prolaza do izvornog koda programa. Informacije koje kompajler dobije prilikom izvršavanja prolaza nisu dostupne korisniku. Ili je pohranjen u ram memorija, koju kompajler oslobađa nakon završetka procesa prevođenja, ili je u obliku privremenih datoteka na disku, koji se također uništavaju nakon završetka kompajlera. Stoga, osoba koja radi s kompajlerom možda čak i ne zna koliko prolaza prevodilac obavlja - on uvijek vidi samo tekst izvornog programa i rezultirajućeg objektnog programa. Ali broj izvršenih prolaza je važan tehničke specifikacije kompajler, renomirane kompanije - programeri kompajlera to obično navode u opisu svog proizvoda.

Jasno je da programeri pokušavaju da minimiziraju broj prolaza koje obavljaju kompajleri. Ovo povećava brzinu kompajlera, smanjuje količinu memorije koja mu je potrebna. Jednoprolazni kompajler koji uzima izvorni program kao ulaz i odmah proizvodi rezultirajući objektni program je idealan.

Međutim, nije uvijek moguće smanjiti broj prolazaka. Broj potrebnih prolaza određen je prvenstveno gramatičkim i semantičkim pravilima izvornog jezika. Što je gramatika jezika složenija i što više opcija predlažu semantička pravila, to će prevodilac izvesti više prolaza (naravno, kvalifikacije programera kompajlera takođe igraju ulogu). Na primjer, to je razlog zašto su Pascal prevodioci obično brži od C kompajlera - Pascalova gramatika je jednostavnija i semantička pravila su stroža. Jednoprolazni kompajleri su rijetki, mogući su samo za vrlo jednostavne jezike. Pravi prevodioci obično izvode dva do pet prolaza. Dakle, pravi kompajleri su višeprolazni. Najčešći su kompajleri sa dva i tri prolaza, na primjer: prvi prolaz je leksička analiza, drugi je raščlanjivanje i semantička analiza, treći je generiranje koda i optimizacija (opcije izvršenja, naravno, zavise od programera). U modernim programskim sistemima, prvi prolaz kompajlera (leksička analiza koda) se često izvodi paralelno sa uređivanjem koda izvornog programa (ova varijanta konstruisanja kompajlera je razmatrana kasnije u ovom poglavlju).

Tumači. Karakteristike izgradnje tumača

Tumač je program koji uzima ulazni program u izvornom jeziku i izvršava ga. Kao što je gore spomenuto, glavna razlika između tumača i prevodilaca i kompajlera je u tome što interpretator ne generiše rezultirajući program, već jednostavno izvršava izvorni program.

Termin 'tumač', kao i 'prevodilac', znači 'prevodilac'. Sa stanovišta terminologije, ovi koncepti su slični, ali sa stanovišta teorije formalnih jezika i kompilacije, postoji velika fundamentalna razlika između njih. Ako se pojmovi "prevodilac" i "kompilator" gotovo ne razlikuju, onda se ne mogu brkati s konceptom "prevodilac".

Najjednostavniji način za implementaciju interpretatora bio bi da se izvorni program prvo u potpunosti prevede u strojne instrukcije, a zatim odmah izvrši. U takvoj implementaciji, interpreter se, zapravo, ne bi mnogo razlikovao od kompajlera, s jedinom razlikom što bi rezultirajući program u njemu bio nedostupan korisniku. Nedostatak takvog interpretatora bi bio taj što bi korisnik morao čekati da se cijeli izvorni program prevede prije nego što se može izvršiti. U stvari, takav tumač ne bi imao mnogo smisla - ne bi pružio nikakve prednosti u odnosu na sličan kompajler 1 . Stoga, velika većina interpretatora djeluje na način da izvršavaju izvorni program sekvencijalno, kako ulazi u ulaz interpretatora. Tada korisnik ne mora čekati završetak kompilacije cijelog izvornog programa. Štaviše, može uzastopno ući u izvorni program i odmah posmatrati rezultat njegovog izvršenja kako se komande unose.

Ovakvim redosledom rada interpretatora se manifestuje suštinska karakteristika koja ga razlikuje od kompajlera - ako interpreter izvršava komande kako stignu, onda ne može da izvrši optimizaciju izvornog programa. Posljedično, faza optimizacije u cjelokupnoj strukturi interpretatora će izostati. Inače će se malo razlikovati od strukture sličnog kompajlera. Samo treba uzeti u obzir da se u posljednjoj fazi – generiranju koda – strojne instrukcije ne upisuju u objektni fajl, već se izvršavaju kako su generirane.

Odsustvo koraka optimizacije definiše još jednu osobinu koja je tipična za mnoge tumače: obrnuta poljska notacija se vrlo često koristi kao interni prikaz programa (pogledajte odeljak „Generacija koda. Metode generisanja koda“, Poglavlje 14). Ovaj zgodan oblik predstavljanja operacija ima samo jedan značajan nedostatak - teško ga je optimizirati. Ali kod tumača, to je upravo ono što nije potrebno.

Ne dozvoljavaju svi programski jezici konstrukciju interpretatora koji bi mogli izvršiti izvorni program kako naredbe stignu.Da bi to učinio, jezik mora omogućiti postojanje kompajlera koji analizira izvorni program u jednom prolazu. Osim toga, jezik se ne može tumačiti kako se naredbe primaju ako dozvoljava da se pozivi funkcijama i strukturama podataka pojave prije nego što se direktno opisuju. Stoga se jezici kao što su C i Pascal ne mogu tumačiti ovom metodom.

Odsustvo koraka optimizacije dovodi do činjenice da je izvršavanje programa uz pomoć interpretatora manje efikasno nego uz pomoć sličnog kompajlera. Takođe, prilikom interpretacije, izvorni program se mora ponovo raščlaniti svaki put kada se izvrši, dok se kod kompajliranja analizira samo jednom, a objektni fajl se uvek koristi nakon toga. Dakle, tumači uvijek gube na performansama u odnosu na kompajlere.

Prednost interpretatora je nezavisnost izvršavanja programa od arhitekture ciljnog računarskog sistema. Kao rezultat kompilacije dobija se objektni kod koji je uvijek orijentiran na određenu arhitekturu. Da biste prešli na drugu arhitekturu ciljnih računarskih sistema], program se mora ponovo kompajlirati. A za interpretaciju programa] potrebno je imati samo njegov izvorni kod i tumač iz odgovarajućeg jezika.

Tumači su dugo vremena bili značajno inferiorniji u prevalenciji SZO peelers. U pravilu su postojali tumači za ograničen raspon relativno jednostavnih programskih jezika (kao što su, na primjer, osnovni alati za profesionalni razvoj softvera visokih performansi izgrađeni na vrhu kompajlera.

Novi podsticaj razvoju tumača dalo je širenje globalnog kompjuterske mreže. Takve mreže mogu uključivati ​​računare lične arhitekture i tada zahtjev za ujednačenom implementacijom teksta izvornog programa na svakoj od njih postaje odlučujući. Stoga, razvojem globalnih mreža i širenjem interneta širom svijeta,
U modernim programskim sistemima postoje softverske implementacije koje kombinuju i funkcije kompajlera i funkcije interpretatora - u zavisnosti od zahteva korisnika, izvorni program se ili kompajlira ili izvršava (interpretira). Osim toga, neki moderni programski jezici uključuju dvije faze razvoja: prvo se izvorni program kompajlira u srednji kod (neki jezik niskog nivoa), a zatim se ovaj rezultat kompilacije izvršava pomoću interpretatora ovog međujezika. Detaljnije, opcije za takve sisteme su razmotrene u poglavlju "Moderni programski sistemi".

Široko korišten primjer interpretiranog jezika je HTML (Hypertext Markup Language), jezik opisa hiperteksta. Na njegovoj osnovi trenutno funkcionira gotovo cjelokupna struktura interneta. Drugi primjer - Java jezici i JavaScript - kombinuju funkcije kompilacije i interpretacije. Tekst izvornog programa se kompajlira u neki srednji binarni kod koji ne zavisi od arhitekture ciljnog računarskog sistema, ovaj kod se distribuira preko mreže i izvršava na prijemnoj strani - interpretira se.

Prevodioci sa asemblerskog jezika ("sastavljači")

asemblerski jezik - to je jezik niskog nivoa. Struktura i međusobna povezanost lanaca ovog jezika bliski su mašinskim uputstvima ciljnog računarskog sistema, gde bi trebalo da se izvrši rezultujući program. Upotreba asemblerskog jezika omogućava programeru da upravlja resursima (procesor, RAM, eksterni uređaji, itd.) ciljnog računarskog sistema na nivou mašinskih instrukcija. Svaka instrukcija izvornog programa u asemblerskom jeziku se konvertuje u jednu mašinsku instrukciju kao rezultat kompilacije.

Prevodilac sa asemblerskog jezika će, naravno, uvek biti kompajler, pošto su jezik rezultujućeg programa mašinski kodovi. Prevodilac asemblerskog jezika često se jednostavno naziva "assembler" ili "assembler program".

Implementacija kompajlera iz asemblerskog jezika

Asemblerski jezik, po pravilu, sadrži mnemoničke kodove za mašinske instrukcije. Najčešće se koristi mnemonika naredbi na engleskom jeziku, ali postoje i druge varijante asemblerskih jezika (uključujući verzije na ruskom jeziku). Zato se asemblerski jezik nekada zvao „jezik mnemokoda“ (sada se ovaj naziv više praktično ne koristi). Sve moguće instrukcije u svakom asemblerskom jeziku mogu se podijeliti u dvije grupe: prva grupa uključuje instrukcije običnih jezika, koje se tokom prevođenja pretvaraju u strojne instrukcije; drugu grupu čine posebne jezičke instrukcije koje se ne pretvaraju u mašinske instrukcije, već ih kompajler koristi za obavljanje zadataka kompilacije (kao što je, na primer, zadatak dodeljivanja memorije). Sintaksa jezika je izuzetno jednostavna. Naredbe izvornog programa obično su napisane na način da postoji jedna naredba po redu programa. Svaka instrukcija asemblerskog jezika, po pravilu, može se podijeliti na tri komponente, koje slijede jednu za drugom: oznake, operacijski kod i polje operanda. Kompajler iz asemblerskog jezika obično takođe predviđa mogućnost komentara u ulaznom programu koji su odvojeni od komandi datim graničnikom.

Polje oznake sadrži identifikator koji predstavlja oznaku ili je prazno. Svaki identifikator oznake može se pojaviti samo jednom u programu asemblerskog jezika. Oznaka se smatra opisanom gdje je at sreo osrednji u programu (potreban je preliminarni opis oznaka). Oznaka se može koristiti za prijenos kontrole na komandu koju šalje. Nije neuobičajeno da se oznaka od ostatka naredbe odvoji znakom za razdvajanje (najčešće dvotočkom ":").

Operativni kod je uvijek strogo definirana mnemonika jedne od mogućih procesorskih naredbi ili također strogo definirana naredba (mog kompajlera. Operativni kod je napisan abecednim znakovima maternjeg jezika. Najčešće je njegova dužina 3-4, rjeđe - 5 ili 6 znakova.

Polje operanda je ili prazno ili je lista od jednog, dva, rjeđe tri operanda. Broj operanada je striktno definisan i zavisi od koda operacije - svaka operacija asemblerskog jezika daje fiksni broj svojih operanada. U skladu s tim, svaka od ovih opcija odgovara neadresiranim, jednoadresnim, dvoadresnim ili troadresnim instrukcijama (veći broj operanada se praktički ne koristi; u modernim računarima su rijetke čak i instrukcije s tri adrese). Kao opere; dov mogu biti identifikatori ili konstante.

Karakteristika asemblerskog jezika je da se određeni broj identifikatora u n dodjeljuje posebno za označavanje procesorskih registara. Takvi fikatori, s jedne strane, ne zahtijevaju preliminarni opis, ali kod D1 ih korisnik ne može koristiti u druge svrhe. Skup ovih identifikatora je unaprijed definiran za svaki asemblerski jezik.

Ponekad asemblerski jezik dozvoljava upotrebu kao operanda određenih ograničenih kombinacija oznaka registara, identifikatora i konstanti, koje su kombinovane nekim znakovima operatora. Takve kombinacije se najčešće koriste za označavanje tipova adresiranja, na primjer, u mašinskim uputstvima ciljnog računarskog sistema.

Na primjer, sljedeći niz naredbi

Ovo je primjer niza naredbi asemblerskog jezika n; procesori iz porodice Intel 80x86. Ovdje se nalazi naredba za opisivanje skupa (podaci (db), oznaka (petlje), opkodovi (mov, dec i jnz). Operandi su identifikator skupa podataka (podaci), oznake procesnog registra

(bx i cx), oznaka (petlje) i konstanta (4). Složeni operand podataka mapira indirektno adresiranje podataka u bazni registar bx na pomaku 4.

Ova sintaksa jezika može se lako opisati upotrebom regularne gramatike. Stoga izgradnja prepoznavača za asemblerski jezik nije teška. Iz istog razloga, u kompajlerima iz asemblerskog jezika, leksička i sintaktička analiza po pravilu se kombinuju u jedan prepoznavač.

Semantiku asemblerskog jezika u potpunosti i potpuno određuje ciljni računarski sistem na koji je ovaj jezik orijentisan. Semantika asemblerskog jezika određuje koja mašinska instrukcija odgovara svakoj instrukciji asemblerskog jezika, kao i koji operandi i koliko ih je dozvoljeno za određeni operacijski kod.

Stoga je semantička analiza u kompajleru asemblerskog jezika jednostavna kao i sintaktička analiza. Njegov glavni zadatak je provjeriti valjanost operanada za svaki operacijski kod, kao i provjeriti da li su svi identifikatori i oznake koje se susreću u ulaznom programu opisani i da identifikatori koji ih označavaju ne odgovaraju unaprijed definiranim identifikatorima koji se koriste za označavanje kodova operacija i registara procesora.

Parsiranje i semantičke šeme u kompajleru asemblerskog jezika se stoga mogu implementirati na osnovu konvencionalnog državnog stroja. Upravo je ova karakteristika odredila činjenicu da su prevodioci asemblerskog jezika istorijski bili prvi kompajleri kreirani za računare. Postoje i brojne druge karakteristike koje su specifične za asemblerske jezike i olakšavaju izradu kompajlera za njih.

Prvo, u kompajlerima iz asemblerskog jezika ne vrši se dodatna identifikacija varijabli - sve jezičke varijable zadržavaju imena koja im je dodijelio korisnik. Programer izvornog programa odgovoran je za jedinstvenost imena u izvornom programu; semantika jezika ne nameće nikakve dodatne zahtjeve ovom procesu. Drugo, u kompajlerima iz asemblerskog jezika, alokacija memorije je krajnje pojednostavljena. Kompajler iz asemblerskog jezika radi samo sa statičkom memorijom. Ako se koristi dinamička memorija, za rad s njom morate koristiti odgovarajuću biblioteku ili funkcije OS-a, a programer izvornog programa odgovoran je za njegovu dodjelu. Programer izvornog programa je također odgovoran za prosljeđivanje parametara i organiziranje memorijskog prikaza procedura i funkcija. On također mora voditi računa o odvajanju podataka iz programskog koda – kompajler na asembleru, za razliku od kompajlera iz jezika visokog nivoa, ne vrši automatski takvo razdvajanje. I treće, u fazi generiranja koda u kompajleru iz asemblerskog jezika, optimizacija se ne vrši, jer je programer izvornog programa odgovoran za organizaciju proračuna, redoslijed strojnih instrukcija i dodjelu registara procesora.

Osim ovih karakteristika, prevodilac asemblerskog jezika je normalan kompajler, ali mnogo pojednostavljen u poređenju sa bilo kojim kompajlerom jezika visokog nivoa. Kompajleri iz asemblerskog jezika se najčešće implementiraju u dvoprolaznoj šemi. Na prvom prolazu, kompajler analizira izvorni program, pretvara ga u mašinske kodove i istovremeno popunjava tabelu identifikatora. Ali pri prvom prolazu u mašinskim uputstvima, adrese onih operanada koji se nalaze u RAM-u ostaju nepopunjene. Na drugom prolazu, kompajler popunjava ove adrese i istovremeno otkriva nedeklarisane identifikatore. To je zato što se operand može deklarirati u programu nakon što je prvi put korišten. Tada njegova adresa još nije poznata u vrijeme konstruiranja strojne instrukcije, pa je stoga potreban drugi prolaz. Tipičan primjer takvog operanda je oznaka koja skače naprijed u nizu instrukcija.

Makro definicije i makro komande

Razvoj programa na asembleru je prilično naporan proces koji često zahtijeva jednostavno ponavljanje istih ponovljenih operacija. Primjer bi bio niz instrukcija koje se izvršavaju svaki put za postavljanje prikaza memorijskog stoga kada se unese procedura ili funkcija.

Da bi se olakšao rad programera, kreirani su takozvani makroi.

makro je zamjena teksta, tokom koje se svaki identifikator određenog tipa zamjenjuje nizom znakova iz nekog skladišta podataka. Proces izvršavanja makronaredbe naziva se generiranje makroa, a niz znakova koji nastaje izvođenjem makroa naziva se proširenje makroa.

Proces izvršavanja makronaredbi sastoji se od sekvencijalnog pregleda teksta izvornog programa, otkrivanja određenih identifikatora u njemu i njihove zamjene odgovarajućim nizovima znakova. Štoviše, izvodi se tekstualna zamjena jednog lanca znakova (identifikatora) drugim lancem znakova (string). Takva zamjena naziva se makro zamjena.

Makro definicije se koriste za određivanje koje identifikatore treba zamijeniti s kojim redovima. Makro definicije su prisutne direktno u tekstu izvornog programa. Odlikuju se posebnim ključnim riječima ili graničnicima koji se ne mogu naći nigdje drugdje u tekstu programa. Tokom obrade, sve makro definicije su potpuno isključene iz teksta ulaznog programa, a informacije sadržane u njima se pohranjuju za obradu prilikom izvršavanja makro naredbi.

Makro može sadržavati parametre. Tada svaki makro koji mu odgovara mora, kada se pozove, sadržavati niz znakova umjesto svakog parametra. Ovaj niz se zamjenjuje prilikom izvršavanja makroa na svakom mjestu gdje se odgovarajući parametar pojavljuje u definiciji makroa. Parametar makroa može biti drugi makro, u kom slučaju će se rekurzivno pozivati ​​kad god treba izvršiti zamjenu parametra. U principu, makroi mogu formirati niz

Rekurzivni pozivi, slični nizu rekurzivnih poziva procedura i funkcija, ali umjesto izračunavanja i prosljeđivanja parametara, oni vrše samo tekstualne zamjene 1 .

Makro komande i makro definicije obrađuju se posebnim modulom koji se naziva makro procesor ili makro generator. Makrogenerator kao ulaz prima tekst izvornog programa koji sadrži makro definicije i makro komande, a na njegovom izlazu se pojavljuje tekst makro ekstenzije izvornog programa, koji ne sadrži makro definicije i makro komande. Oba teksta su samo programski tekstovi, nikakva druga obrada se ne vrši. To je makro proširenje izvornog teksta koje ulazi u ulaz kompajlera.

Sintaksa makro naredbi i makro definicija nije striktno definirana. Može se razlikovati ovisno o implementaciji kompajlera od asemblerskog jezika. Ali sam princip izvođenja makro zamjena u tekstu programa je nepromijenjen i ne ovisi o njihovoj sintaksi.

Makrogenerator najčešće ne postoji kao poseban programski modul, već je dio kompajlera iz asemblerskog jezika. Makro ekstenzija izvornog programa obično nije dostupna njegovom programeru. Štaviše, makro supstitucije se mogu izvoditi sekvencijalno kada se raščlanjuje izvorni kod na prvom prolazu kompajlera, zajedno sa raščlanjivanjem celog teksta programa, a zatim makro proširenje izvornog programa kao celine možda uopšte ne postoji kao takvo.

Na primjer, sljedeći tekst definira makro push_0 u asemblerskom jeziku procesora tipa Intel 8086:

Hog ah, ah ■ gurnuti sjekiru endm

Semantika ovog makroa je da upiše broj "0" u stog preko registra procesora. Zatim svuda u tekstu programa, gdje će se makro susresti

Bit će zamijenjen kao rezultat zamjene makroa sa nizom naredbi:

Hog ah, ah ■ gurati sjekiru

Ovo je najjednostavnija makro definicija. Moguće je kreirati složenije makro definicije sa parametrima. Jedna od ovih makro definicija je opisana u nastavku:

Dubina takve rekurzije je obično vrlo ograničena. Niz rekurzivnih poziva makroima obično je podložan znatno strožijim ograničenjima od niza rekurzivnih poziva procedura i funkcija, koji je, sa naslaganim memorijskim prikazom, ograničen samo veličinom steka za prijenos parametara. add_abx makro xl,x2

push ax
endm

Tada se i makro naredba mora specificirati u tekstu programa sa odgovarajućim brojem parametara. U ovom primjeru, makro

Add_abx4,8 će biti zamijenjen nizom naredbi kao rezultat zamjene makroa:

Dodati sjekiru,4 dodati bx.4 dodati ex,8 gurati sjekiru

U mnogim kompajlerima iz asemblerskog jezika moguće su čak i složenije konstrukcije koje mogu sadržavati lokalne varijable i oznake. Primjer takve konstrukcije je makro definicija:

Loop_ax makro xl,x2,yl

Hog bx.bx loopax: dodajte bx.yl

Ovdje je oznaka 1 oopax lokalna, definirana samo unutar ovog makroa. U ovom slučaju se više ne može izvršiti jednostavna zamjena teksta makro naredbe u tekst programa, jer ako se ova makro naredba izvrši dvaput, to će dovesti do pojave dvije identične oznake u tekstu programa. U ovom slučaju, makrogenerator mora koristiti složenije metode zamjene teksta, slične onima koje koriste kompajleri prilikom identifikacije leksičkih elemenata ulaznog programa, kako bi svim mogućim lokalnim varijablama i makro oznakama dao jedinstvena imena unutar cijelog programa. Makro definicije i makro komande našle su upotrebu ne samo u asemblerskim jezicima, već iu mnogim jezicima visokog nivoa. Tamo ih obrađuje poseban modul koji se zove jezički preprocesor (na primjer, preprocesor jezika C je široko poznat). Princip obrade ostaje isti kao i za programe na asemblerskom jeziku - predprocesor vrši zamjene teksta direktno na linijama samog izvornog programa. U jezicima visokog nivoa, makro definicije moraju biti odvojene od teksta samog izvornog programa, tako da ih pretprocesor ne može pomešati sa sintaksom jezika unosa. Za to se koriste ili posebni znakovi i naredbe (preprocesorske komande), koje se nikada ne mogu pojaviti u tekstu izvornog programa, ili se pronalaze makro definicije

Unutar beznačajnog dijela izvornog programa - dio su komentara (takva implementacija postoji, na primjer, u Pascal kompajleru koji je kreirao Borland). Makroi se, s druge strane, mogu pojaviti bilo gdje u izvornom kodu programa, a sintaktički se njihov poziv ne može razlikovati od poziva funkcija u izvornom jeziku.

Treba imati na umu da se, unatoč sličnosti sintakse poziva, makro naredbe suštinski razlikuju od procedura i funkcija, jer ne generiraju rezultirajući kod, već su zamjena teksta koja se izvodi direktno u tekstu izvornog programa. Rezultat pozivanja funkcije i makronaredbe može biti ozbiljno drugačiji zbog toga.

Razmotrite primjer u jeziku C. Ako je funkcija opisana

Int fKint a) ( return a + a: ) i sličan makro

#define f2(a) ((a) + (a)) onda rezultat njihovog poziva neće uvijek biti isti.

Zaista, pozivi j=fl(i) i j=f2(i) (gdje su i i j neke cjelobrojne varijable) će dovesti do istog rezultata. Ali pozivi j=fl(++i) i j=f2(++i) će dati različita značenja varijabla j. Činjenica je da budući da je f2 makro definicija, u drugom slučaju će se izvršiti zamjena teksta, što će dovesti do niza operatora j=((++i) + (++i)). Može se vidjeti da će u ovom nizu operacija ++i biti izvršena dva puta, za razliku od poziva funkcije fl(++i) gdje se izvršava samo jednom.

Pošto tekst programa napisan na nekom programskom jeziku nije razumljiv računaru, potrebno ga je prevesti na mašinski jezik. Prevođenje programa iz programskog jezika u jezik mašinskog koda naziva se emitovanje(prevod - prevod), a izvode se posebnim programima - prevodioci.

Postoje dvije vrste prevoditelja: prevodioci i prevodioci.

Tumač naziva se prevodilac koji izvodi operator-by-operator (command-by-command) prevod i naknadno izvršavanje prevedenog operatora izvornog programa. Dva nedostatka metode interpretacije:

1. Program za tumačenje mora biti u memoriji računara tokom čitavog procesa izvršavanja originalnog programa, odnosno zauzimati određenu količinu memorije;

2. Proces prevođenja istog izraza se ponavlja onoliko puta koliko puta se ova naredba mora izvršiti u programu.

Kompajler je program koji konvertuje (prevodi) izvorni program u program (modul) na mašinskom jeziku. Nakon toga program se upisuje u memoriju računara i tek onda izvršava.

Tokom kompilacije, procesi prevođenja i izvršavanja su vremenski razdvojeni: prvo se izvorni program u potpunosti prevodi na mašinski jezik (nakon čega nije potrebno prisustvo prevodioca u RAM-u), a zatim se prevedeni program može više puta izvršavati.

Svaki prevodilac rješava sljedeće glavne zadatke:

1. Analizira emitovani program i utvrđuje da li sadrži sintaksičke greške;

2. Generiše izlazni program u kompjuterskom komandnom jeziku;

3. Dodjeljuje memoriju za izlazni program, tj. svaka varijabla, konstanta, nizovi i drugi objekti imaju svoje područje memorije.

Na ovaj način, Kompajler(engleski) kompajler- kompajler, kolektor) čita ceo program u potpunosti, prevodi ga i kreira kompletnu verziju programa na mašinskom jeziku, koji se zatim izvršava.

Tumač(engleski) tumač- interpreter, interpreter) prevodi i izvršava program red po red.

Nakon što je program preveden, više nisu potrebni ni izvorni program ni kompajler. Istovremeno, program koji interpretator obrađuje mora ponovo transfer u mašinski jezik svaki put kada se program pokrene.

Svaki određeni jezik je fokusiran ili na kompilaciju ili interpretaciju, ovisno o svrsi za koju je stvoren. Na primjer, Pascal obično se koristi za rješavanje prilično složenih problema u kojima je važna brzina programa. Stoga se ovaj jezik obično implementira pomoću kompajler. Na drugoj strani, OSNOVNI je kreiran kao jezik za programere početnike, za koje izvršavanje programa liniju po red ima neosporne prednosti. Ponekad za jedan jezik postoji i kompajler, i tumač. U ovom slučaju, možete koristiti interpreter da razvijete i testirate program, a zatim prevedete otklonjeni program da biste ubrzali njegovo izvršavanje.

Pošto je tekst napisan programskim jezikom nerazumljiv za računar, potrebno ga je prevesti u mašinski kod. Takav prevod programa iz programskog jezika u jezik mašinskog koda naziva se prevođenje, a izvode ga posebni programi - prevodioci.

Prevodilac je pomoćni program koji konvertuje izvorni program obezbeđen u ulaznom programskom jeziku u radni program predstavljen u objektnom jeziku.

Trenutno su kompajleri podijeljeni u tri glavne grupe: asembleri, kompajleri i interpretatori.

Assembler je sistemski uslužni program koji pretvara simboličke konstrukcije u instrukcije mašinskog jezika. Specifičnost asemblera je da doslovno prevode jednu simboličku instrukciju u jednu mašinsku instrukciju. Stoga je asemblerski jezik (koji se naziva i autokod) dizajniran da olakša percepciju kompjuterskog skupa instrukcija i ubrza programiranje u ovom skupu instrukcija. Programeru je mnogo lakše da zapamti mnemoničku oznaku mašinskih instrukcija nego njihov binarni kod.

Istovremeno, asemblerski jezik, pored analoga mašinskih instrukcija, sadrži mnoge dodatne direktive koje olakšavaju, posebno, upravljanje računarskim resursima, pisanje fragmenata koji se ponavljaju i pravljenje multimodulnih programa. Stoga je ekspresivnost jezika mnogo bogatija od samog jezika simboličkog kodiranja, što uvelike povećava efikasnost programiranja.

Kompajler je pomoćni program koji prevodi na mašinski jezik program napisan u izvornom programskom jeziku. Baš kao asembler, kompajler pretvara program iz jednog jezika u drugi (najčešće u jezik određenog računara). Međutim, naredbe izvornog jezika značajno se razlikuju po organizaciji i snazi ​​od naredbi strojnog jezika. Postoje jezici u kojima je jedna instrukcija izvornog jezika prevedena u 7-10 mašinskih instrukcija. Međutim, postoje i jezici u kojima svaka instrukcija može odgovarati 100 ili više strojnih instrukcija (na primjer, Prolog). Osim toga, u izvornim jezicima često se koristi striktno kucanje podataka koje se provodi kroz njihov preliminarni opis. Programiranje se možda neće oslanjati na kodiranje algoritma, već na pažljivo razmišljanje o strukturama podataka ili klasama. Proces prevođenja sa takvih jezika obično se naziva kompilacija, a izvorni jezici se obično nazivaju programski jezici visokog nivoa (ili jezici visokog nivoa). Apstrakcija programskog jezika iz komandnog sistema računara dovela je do nezavisnog stvaranja širokog spektra jezika fokusiranih na rešavanje specifičnih problema. Pojavili su se jezici za naučne proračune, ekonomske proračune, pristup bazama podataka i drugo.

Interpretator je program ili uređaj koji obavlja translaciju od operatora do operatera i izvršavanje originalnog programa. Za razliku od kompajlera, tumač ne proizvodi program na mašinskom jeziku kao izlaz. Nakon što prepozna komandu izvornog jezika, ona je odmah izvršava. I prevodioci i prevodioci koriste iste metode raščlanjivanja izvornog koda programa. Ali tumač vam omogućava da započnete obradu podataka nakon što napišete čak i jednu naredbu. Ovo čini proces razvoja i otklanjanja grešaka fleksibilnijim. Osim toga, odsustvo izlaznog strojnog koda omogućava da se vanjski uređaji ne "zasipaju" dodatnim datotekama, a sam interpreter se može prilično lako prilagoditi bilo kojoj strojnoj arhitekturi, razvio ga samo jednom u široko korištenom programskom jeziku. Stoga su interpretirani jezici kao što su Java Script, VB Script postali široko rasprostranjeni. Nedostatak interpretatora je mala brzina izvršavanja programa. Obično interpretirani programi rade 50 do 100 puta sporije od programa napisanih u mašinskom kodu.

Emulator je program ili softver i hardverski alat koji pruža mogućnost izvršavanja programa na datom računaru bez reprogramiranja, koristeći kodove ili metode za izvođenje operacija koje se razlikuju od ovog računara. Emulator je sličan tumaču po tome što direktno izvršava program napisan na nekom jeziku. Međutim, najčešće je to strojni jezik ili srednji kod. Oba predstavljaju instrukcije u binarnom kodu koje se mogu izvršiti odmah nakon prepoznavanja koda operacije. Za razliku od tekstualnih programa, nije potrebno prepoznati strukturu programa, odabrati operande.

Emulatori se često koriste u različite svrhe. Na primjer, prilikom razvoja novih računarskih sistema, prvo se kreira emulator koji pokreće programe koji se razvijaju za računare koji još ne postoje. Ovo omogućava procjenu skupa instrukcija i razvoj osnovnog softvera prije kreiranja odgovarajućeg hardvera.

Vrlo često se emulator koristi za pokretanje starih programa na novim računarima. Tipično, noviji računari su brži i imaju bolje periferne uređaje. Ovo vam omogućava da efikasnije emulirate starije programe od pokretanja na starijim računarima.

Transkoder - program ili softverski uređaj koji prevodi programe napisane na mašinskom jeziku jednog računara u programe na mašinskom jeziku drugog računara. Ako je emulator manje inteligentan analog interpretatora, onda transkoder djeluje u istom svojstvu u odnosu na kompajler. Slično, izvorni (i obično binarni) mašinski kod ili međureprezentacija se pretvara u drugi sličan kod u jednoj instrukciji i bez ikakve opšte analize strukture izvornog programa. Transkoderi su korisni kada se programi prenose sa jedne računarske arhitekture na drugu. Mogu se koristiti i za rekonstrukciju teksta programa jezika visokog nivoa iz dostupnog binarnog koda.

Makroprocesor je program koji zamjenjuje jedan niz znakova drugim. To je vrsta kompajlera. Generiše izlazni tekst obradom posebnih umetaka koji se nalaze u izvornom tekstu. Ovi umetci su napravljeni na poseban način i pripadaju jezičkim konstrukcijama koje se nazivaju makro jezik. Makroprocesori se često koriste kao dodaci programskim jezicima, povećavajući funkcionalnost programskih sistema. Gotovo svaki asembler sadrži makroprocesor, koji povećava efikasnost razvoja mašinskih programa. Takvi programski sistemi se obično nazivaju makro asemblerima.

Makroprocesori se takođe koriste sa jezicima visokog nivoa. Oni povećavaju funkcionalnost jezika kao što su PL/1, C, C++. Makroprocesori se posebno široko koriste u C i C++, što olakšava pisanje programa. Makroprocesori povećavaju efikasnost programiranja bez promjene sintakse i semantike jezika.

Sintaksa - skup pravila određenog jezika koji određuju formiranje njegovih elemenata. Drugim riječima, to je skup pravila za formiranje semantički značajnih nizova znakova u datom jeziku. Sintaksa je specificirana pomoću pravila koja opisuju koncepte određenog jezika. Primjeri koncepata su: varijabla, izraz, operator, procedura. Redoslijed koncepata i njihova dozvoljena upotreba u pravilima određuju sintaksički ispravne strukture koje formiraju programe. Sintaksom je definirana hijerarhija objekata, a ne način na koji oni međusobno djeluju. Na primjer, operator se može pojaviti samo u proceduri, dok se izraz u operatoru, varijabla može sastojati od imena i opcijskih indeksa, itd. Sintaksa nije povezana sa pojavama u programu kao što su "skakanje na nepostojeću oznaku" ili "promenljiva sa datim imenom nije definisana". To je ono što semantika radi.

Semantika - pravila i uvjeti koji određuju odnos između elemenata jezika i njihovih semantičkih značenja, kao i tumačenje značenja značenja sintaksičkih konstrukcija jezika. Objekti programskog jezika ne samo da se postavljaju u tekst u skladu sa određenom hijerarhijom, već su i dodatno međusobno povezani preko drugih koncepata koji formiraju različite asocijacije. Na primjer, varijabla za koju sintaksa definira ispravnu lokaciju samo u deklaracijama i nekim izjavama, ima specifičan tip, može se koristiti s ograničenim skupom operacija, ima adresu, veličinu i mora biti deklarirana prije upotrebe u program.

Parser je komponenta kompajlera koja provjerava usklađenost izvornih izjava sa sintaksnim pravilima i semantikom datog programskog jezika. Uprkos nazivu, analizator provjerava i sintaksu i semantiku. Sastoji se od nekoliko blokova, od kojih svaki rješava svoje probleme. To će se detaljnije razmotriti kada se opisuje struktura prevodioca.

Svaki prevodilac obavlja sljedeće glavne zadatke:

Analizira program koji se prevodi, posebno utvrđuje da li sadrži sintaksičke greške;

Generiše izlazni program (često se naziva objektni program) na jeziku mašinskih instrukcija;

Dodjeljuje memoriju za objektni program.