Transleerimise etapid

Translaator on programm, mis teisendab ühes programmeerimiskeeles (lähtekeeles) kirjutatud programmi (nn lähtekoodi) teises programmeerimiskeeles (objektkeeles) kirjutatud programmiks (objektkoodiks). Kui genereeritud objektkood on transleerimisel kasutava arvuti protsessorile arusaadav (s.t. protsessori masinkood või assemblerkood), võib translaator iga genereeritud käsu kohe ka täita ja objektkoodi üldse ei väljastata; selliseid translaatorieid nimetatakse interpretaatoriteks. Kui aga translaator väljastab transleerimise tulemuse eraldi tekstina (programmina, mis käivitatakse hiljem), nimetatakse translaatorit kompilaatoriks (compilator).

Interpretaatorid on mugavad programmi koostamisel ja silumisel - iga lähteteksti lisatud käsu saab kohe täita, seega on selle tulemus (ja võimalikud vead) kohe näha; interpretaatorit kasutavad keeled on (näiteks) erinevad Basic-ud, Prolog, paljud andmebaasissteemide keeled (SQL) jne. Kompilaatori kasutamisel saab hakata loodud programmi testima alles siis, kui kogu programm on valmis ja süntaksivigadeta, seega programmi silumine on palju palju aeglasem ja töömahukam. Kuid interpretaatorid on aeglasemad, sest täidetav programm koostatakse (transleeritakse) igal käivitamisel uuesti, s.t programmi täitmise ajale lisandub alati selle transleerimise aeg; kompilaatori korral saab kord juba kompileeritud programmi "otse" käivitada (transleerimist pole enam tarvis), s.t kompileeritud programmi täitmine on kiirem. Sellepärast ongi paljude keelte jaoks kaks translaatorit: programmi koostamise ja silumise ajal kasutatakse interpretaatorit, ja kui programm on silutud (vigadeta), siis see kompileeritakse lõpliku, kiirelt täidetava versiooni saamiseks.

Translaatori koostamisel osalevad (vähemalt) kolm programmeerimiskeelt:
- lähtekeel, s.t keel, milles on kirjutatud transleeritav programm;
– objektkeel, s.t keel, millesse transleeritakse;
– translaatori koostamiseks kasutatud keel.

Sageli ei toimu objektkeelse väljundi saamine ühe etapina, vaid kasutatakse nn "vahekeelt" (p-koodi, baitkoodi) - algul transleeritakse vahekeelde ja alles sealt objektkoodiks.

Transleerimine (lähteteksti teisendamine väljundtekstiks) on keerukas protsess ja tavaliselt jagatakse see etappideks, s.t lähteteksti läbitakse (töödeldakse) mitu korda. Kuna translaator peab töötama kiiresti, on need läbivaatused (enam-vähem) lineaarsed, s.t tagurdusteta protsessid. Esineb ka "lineaarseid" translaatoreid, mis sooritavad kogu transleerimisprotsessi ühekordse läbivaatuse ajal, näiteks programmeerimiskeel Pascal (esimene versioon) oli projekteeritud just nii, et seda saaks ühekordse läbivaatusega transleerida, kuid levinum on siiski mitmeastmeline transleerimine.

Translaatorites kasutatakse erinevaid liigendusi, kuid tüüpilised transleerimise etapid on:

leksikaanals: lähtetekstis (sümbolite jada) leitakse lekseemid, kõige väiksemad iseseisva tähendusega lähteteksti tekstijupid: identifikaatorid (muutujad), lähtekeele võtmesnad ( begin, if, then, else, main,...), aritmeetilised operaatorid, eraldaja (sulumrgid, reavahetused,...), eemaldatakse ülearused tühikud (see lihtne teisendus võimaldab transleeritavat teksti keskmiselt vähemalt 20% kokku suruda ja seega kiirendada järgnevaid etappe), kommentaarid jne; leksilise analüüsi tulemusena muutub lähteteksti sümbolite jada lekseemide jadaks;

süntaksianalüüs: lekseemide jada liigendamine programmikäskudeks, aritmeetilisteks avaldisteks jne; süntaksi analüüsi tulemusena konstrueeritakse lekseemide jadast transleeritava programmi (konkreetse) süntaksi puu;

abstraktse (hõreda) süntaksi puu moodustamine (AST – Abstract Syntax Tree): süntaksianalüüsi tulemusena saadud programmi süntaksi puust eemaldatakse kõik mitteoluline, näiteks kõik lähtekeele süntaksiga seotud osad (lähtekeele võtmesõnad), säilitades seejuures süntaksi puu semantika (struktuuri) või seda veidi teisendades; see etapp sooritatakse peamiselt edasiste teisenduste kiirendamiseks;

semantiline analüüs ja väljundkoodi genereerimine: programmi (abstraktse) süntaksi puu kirjeldatakse väljundkeele vahenditega, s.t väljundkeele käskudena, mis kas otsekohe ka täidetakse (interpretaatoris) või väljastatakse transleeritud programmina, väljund­tekstina (kompilaatoris)..

Esimesed kolm etappi – leksika- ja süntaksianalüüs ja abstraktse süntaksi puu moodustamine – on kõik sisendi (transleeritava programmi) analüüsi osad; sisendi struktuur on täielikult avatud alles abstraktse süntaksi puus ja alles pärast selle saamist võib hakata tegelema väljundi (objektkoodi) koostamisega. Sellepärast nimetatakse neid esimesi etappe translaatori esimeseks otsaks (first end) ja seda, mis toimub pärast abstraktse süntaksi puu saamist – translaatori teiseks (tagumiseks) otsaks (back end).

Viimane etapp – semantiline analüüs ja väljundkoodi genereerimine – võib olla jagatud veel mitmeks alametapiks. Transleerimise tulemusena tahetakse tavaliselt saada (võimalikult lihtsalt) koodi mitmesuguste protsessorite ja operatsioonisüsteemide jaoks. Sellepärast on otstarbekas teisendada lähtetekst mingile vahekujule, mis

– oleks (võrreldes lähtekeelega) võimalikult madala tasemega (s.t lähedane protsessorite masinkoodile);
– kuid siiski piisavalt üldine, nii et sellest on lihtne saada masinkood või assemblerkood kõigi erinevate protsessorite ja operatsioonisüsteemide jaoks.

Tüüpiline selline kaheastmelise transleerimisega keel on Java. Esimese etapina koostab Java-translaator java baitkoodi (class-files). See etapp ja selle tulemus (baitkood) ei sõltu objektarvuti operatsioonisüsteemist ega objektarvuti protsessori keelest. Baitkoodi kompileerib (interpreteerib) javac-translaator, mis võtab arvesse objektarvuti protsessori ja operatsioonisüsteemi iseärasusi (Windows PC, Unix-tööjaam, Apple Macintosh-arvuti jne)..

Java puhul on vaheetapp selgesti näha kaheastmelise transleerimisena, kuid ka paljudes teistes translaatorites kasutatakse (sisemiselt) vahekeeli. Näiteks program­meerimis­keele Pascal defineeris selle looja Wirth nn p-koodis – see oli suhteliselt madala taseme keel, mille instruktsioonid olid spetsiaalselt valitud nii, et Pascalist p-koodi transleerimine oleks lihtne ja kiire. Selline Pascalist p-koodi transleeriv translaator on universaalne, ei sõltu objektarvuti operatsioonisüsteemist ega protsessorist. Et mingi arvuti jaoks saada Pascal-translaatorit, on vaid tarvis kas interpreteerida p-koodi käske mingis keeles, mille translaator on selles arvutis juba olemas (C, assembler) või luua "päris" translaator, s.t p-koodist masinkoodiks teisendav translaator.

Windows on samuti suures osas kirjeldatud p-koodis. See teeb süsteemi veidi väiksemaks (kuna p-kood on siiski kõrgetasemelisem kui masinkood, on programmide tekstid selles lühemad) ja võimaldab lihtsamini koodi üle kanda uute protsessorite ja operatsiooni­süsteemide jaoks – sisestatud (embedded) süsteemid, pihuarvutid, Windows-CE jne.

Vabade translaatorite kollektsioon GCC (GNU Compiler Collection) kasutab samuti vahekeelt RTL – Register Transfer Language. GNU CC-sse kuuluvad Vaba Tarkvara Liidu (Free Software Foundation) poolt loodud väga kvaliteetsed C, C++, FORTRAN-i, Java ja mitme teise programmeerimiskeele translaatorid; see on üsna suur pakett, esimese stabiilse versiooni saamiseks kulus peaaegu kümme aastat. Vahekeele abil on GCC translaatoreid üle kantud (porditud) peaaegu paarikümne erineva protsessori jaoks. Selle abil oli ka suhteliselt lihtne luua paketti CygWin, mis võimaldab Unix-operatsioonisüsteemi jaoks loodud programme (näiteks Flex, Bison) kasutada ka Windows-keskkonnas. CygWin teisendab programmi Unix-operatsioonisüsteemi poole pöördumised Windowsi käskudeks, seega saab selle abil kasutada ka näiteks Linuxi jaoks loodud programme Windowsis. Analoogiline, kuid väiksem pakett on MinGW (Minimalist GNU for Windows).

Peale "kõrgemalt madalamale", s.t kõrgema taseme keelest madalama taseme keelde teisendavate translaatorite kasutatakse ka nn "risttranslaatoreid" (cross-compilers), mis transleerivad ühest kõrgkeelest teise, ja dekompileerijaid (decompilers) ning dis­assemblereid, mis püüavad kas masinkoodist või assemblerkoodist saada ekvivalentset programmi kõrgtaseme keeles. Kuna dekompileerijad ja disassemblerid programmi sisust aru ei saa, on ka nende poolt genereeritud kood (kõrgtaseme keeles) tavaliselt (peaaegu) loetamatu. Ka risttranslaatorite teine pool (pärast lähteprogrammi sisu analüüsi) on analoogiline dekompileerijaga – madalama taseme esitusest peab saama esituse kõrgema taseme keeles, sellepärast on ka nende poolt genereeritud programmid raskesti loetavad ja translaatorid ise on üsna suured, näiteks FortranC (Fortranist C-keelde transleeriv translaator) lähtekood on enam kui 36200-realine programm.

 


Küsimused, probleemid: ©2004-2013 Jaak Henno