Arvuti on (äärmiselt abstraheeritult) kast, mis on jagatud ruudukesteks (mälupesadeks ). Iga ruuduke võib :
- sisaldada musta palli (bit "0");
- sisaldada valge palli (bit "1");
- olla tühi.
Arvutamine (programmi käivitamine/täitmine) koosneb sammudest/instruktsioonidest, kus igal sammul:
- kirjutatakse midagi ("0" või "1") mingisse
ruudukesse (mälupesasse) - kuid konkreetset mälupesa saab
näidata vaid siis, kui on kokku lepitud mingi viis
ruudukeste/mälupesade adresseerimiseks ; järgnevas oletame
(lihtsustatult), et mälupesad on aderesseeritud järjestikuste
arvudega (näiteks) kaheksandsüsteemis ( reaalseted arvutid
võivad kasutada näiteks heksadetsimaalsüsteemi (hex)
);
- loetakse midagi ("0" või "1") mingist ruudukest
(mälupesast). Kuid loetu on tarvis kuidagi salvestada,
sellepärast on arvutis mingi (lõplik, väike) arv registreid
- mälupesad, mis on vahetulemuste ja operatsioonide argumentide
salvestamiseks ( kuna need peavad olema väga kiired, siis
tavaliselt väga väike arv);
- tehakse mingi (aritmeetiline, loogiline) operatsioon (binaarne - kahe
argumendiga, unaarne - ühe argumendiga; kuna operatsioon
salvestatakse samades mälupesades, peab olema fikseeritud mingi
mälupesade hulk, kus fikseeritud 0/1-de jada kirjeldab
operatsiooni, s.t. operatsioonidel on kahendkood); siin on mitmeid
võimalusi sõltuvalt argumentide ja tulemuse
adresseerimise võimalustest:
- operandid (mõlemad mälupesadest), tulemus -
mälupesasse (kolmeaadressiline süsteem - keerukas ja kallis);
- operandid (mõlemad) mälupesadest, tulemus - fikseeritud
registrisse või
- üks operand - mälupesast, teine ja tulemus - fikseeritud
registritest (üheaadressiline süsteem).
Operatsiooni sooritamine, selle tulemuse salvestamine ja
järgmisena täidetava instruktsiooni valik võib
sõltuda mingitest väärtustest (mis on salvestatud
mälupesades või registrites), seega on tarvis ka
tingimuslauset :
if
(mälupesa/registri väärtus)
then (operatsioon).
Kuid sõltumata sellest, milline on operatsioonide kirjeldamise süntaks, on arvuti alati lõplik automaat , mille olekute arv on 2**(mälupesade+registrite arv) - arvuti olek (igal hetkel) on määratud tema mälupesade ja registrite sisuga.
Selle
lõpliku automaadi tööd juhib protsesso, mis
operatsiooni (automaadi oleku muutuse) kirjelduse põhjal muudab
automaadi olekut. Kirjeldus esitatakse protsessorile bitijadana, kus on
operandide aadressid, operatsiooni kood ja tulemuse aadress, s.t.
käsk võiks välja näha nii
001010100011 ja selle bitijada
tähendus (semantika) võiks olla:
võta arvud pesadest 001 ja 010, liida need (kood 100) ja salvesta tulemus pesas 011 - see oleks binaarne masinkood kolmeaadressilises süsteemis.
Esimeste arvutite jaoks pidid selliseid bitijadasid konstrueerime programmeerijad. Selline programmeerimisviis (bitijadadena masinkoodis) on äärmiselt inimvaenulik - inimesed teevad selliste bitijadade käsitlemisel väga palju vigu.
Esimese sammuna koodi "inimlikustamisel" oli nn sümboolsete nimede kasutuselevõtt, näit koodi "100" asemel kirjutati "add" - sündis assemblerkeel. Assemblerkeel on vaid masinkoodi bitijadade (mehhaaniline) asendus operatsioonide ja muutujate nimedega, kuid inimesele juba palju lihtsamini arusaadavam ja lihtsam. Järk-järgult lisandusid programmeerimiskeeltesse üha keerukamad konstruktsioonid: ühe tehte asemel (masinkoodis ja ka assembleris sooritab iga käsk vaid ühe aritmeetilise või loogilise operatsiooni) sai kirjutada juba terve mitmesuguseid matemaatilisi funktsioone sisaldava avaldise, toodi sisse juhtimiskonstruktsioonid (if-then(-else), tsüklid), moodulid, objektid jne jne). Kuid programmi täitmisel peab kõik need kaasaegsete programmeerimiskeelte konstruktsioonid algul programmi tekstist üles leidma ja teisendada masinkoodi - see on ainuke, millest protsessor "aru saab".
Translaatori ülesanne ongi algul "avastada" transleeritava programmi struktuur (süntaks), leida selles käsud, muutujate deklaratsioonid, alamprogrammid/moodulid/klassid ja siis (näiteks) teisendada kõrgtaseme keele käsk
IF A OR (B AND C) THEN X := Y + Z
ja siis teisendada see assemblerkoodiks (või mõneks teiseks programmeerimiskeeleks), näiteks selliseks:
100 IF A GOTO 106
101 GOTO 102
102 IF B GOTO 104
103 GOTO 108
104 IF C GOTO 106
105 GOTO 108
106 T1 := Y+Z
107 X := T1
Kogu probleem on stringi (sisendteksti; nii lähtetekst kui ka tulemus on märgijadad, s.t. stringid!) struktuuri avastamine ja selle stringi teisendamine. Osutub, et nii struktuuri avastamist kui ka väljundi genereerimist on võimalik etappide kaupa nii kirjeldada, et kogu teisenduse programm (s.t. translaator) genereeritakse sellest kirjeldusest (pool)automaatselt.
Kuid sellisest formaalsest translaatorite genereerimise süsteemi kirjeldamiseks ja sellest arusaamiseks on tarvis aru saada ja osata kasutada sümbolijadade hulkade (keelte) teisendamise formalismidest - abstraktsetest automaatidest ja grammatikatest.