Programske jezike lahko delimo na razne načine. Eden od načinov je generacijska delitev. Tako lahko programske jezike uvrstimo v prvo generacijo, če je to strojni jezik, v drugo generacijo zbirne jezike. Vse ostale generacije predstavljajo višje programske jezike. Tretjo bi še lahko opredelili s postopkovnimi programskimi jeziki, četrto z deklarativnimi, vendar tu meja med generacijami ni več striktno določena. Vse preveč se generacijsko delitev izkorišča v ekonomsko-propagandno-reklamne namene s poudarkom na boljši prodaji nekega produkta, pa tudi sami programski jeziki so s svojim razvojem pričeli brisati meje med generacijami.
Tako ponavadi programske jezike delimo na:
Če hočemo, da računalnik razume informacijo kot navodilo za delo, le ta mora biti zapisana v binarni obliki (električni signali) in mora biti zapisana v strojnem jeziku.
Strojni jezik je sestavljen iz nizov kombinacij binarnih simbolov končne dolžine, ki predstavljajo ukaze specifičnega procesorja in njihove operande. Pri uporabi je potrebno natanko poznati pomen posameznih nizov.
zapis je neroden, človeku zelo nerazumljiv,
strojni jezik odvisen od računalnika (centralne procesne enote), program v strojnem jeziku neprenosljivi na drug računalniški sistem z drugovrstne centralno procesno enoto;
zelo težavno programiranje,
težavno odpravljanje napak v kodi programa,
zelo veliko binarnih številk za opis zelo enostavne funkcionalnosti (nizka osnovna kompleksnost ukazov),
...
Tipično so si programerji pri programiranju v strojnem jeziku pomagali s t.i. programskimi karticami, kjer so imeli opisan pomen posameznih ukazov in njihov način uporabe. Spodaj je primer delčka take kartice:
kaj hitro je bilo jasno, da je programiranje s pomočjo opisov ukazov precej enostavneje, kot pa z uporabo binarnih ukazov. Te opise ukazov, kjer je vsak ukaz dobil poljubno ime, so poimenovali mnemoniki, programiranje s pomočjo mnemonikov pa zbiranje (asembliranje, assembling). Primer programa v zbirniku in strojni kodi:
razen tega, da je bilo programiranje lažje, pa vse ostale slabosti, ki smo jih spoznali v zvezi s strojnim jezikom ostajajo (vse je sicer rahlo lažje naredi, pa vendar...). Drug problem, ki se pojavi z novim jezikom pa je v tem, da sam stroj tega jezike ne pozna več. Pred uporabo ga je potrebno pretvoriti v strojni jezik. To pretvorbo, pri kateri se opis ukaza (operacije) nadomesti z njeno binarno kodo, imenujemo zbiranje.
je logično nadaljevanje razvoja zbirnika kot programskega jezika. Programiranje je svoji osnovi kodiranje (pogosto istega ali podobnega) problema. Tako se npr. zgodi, da je potrebno za izpis znaka na zaslon spisati povprečno 5 ukazov. In to vsakič, ko želimo izpisati posamezen znak. In to pretežno istih ukazov. Zato se je pojavila ideja o grupiranju takih ukaz v en sam, 'močnejši ukaz' in s tem logično povečati kompleksnost obstoječih ukazov. V bistvu ni šlo za nove ukaze, temveč za skupino ukazov, ki so jo programerji lahko znova in znova uporabili v kodi. V zgodnji fazi zbiranja se je tako uporaba takega ukaza v programu nadomestila s celotno množico ukazov, ki smo jo predhodno zgrupirali. Grupe so poimenivali makroji. Mehanizem delovanja makrojev je tudi danes, v okviru višjih programski jezikov ostal enak:
Značilno za rabo makrojev je to, da končna koda z njihovo uporabo ni nič krajša kot zbirna koda. Vse kar dosežemo z njimi je, da programerju olajšamo delo.
Z uporabo mnemonikov je izvorni program postal krajši in s tem razumljivejši.
Koncentriranje oz. povečevanje funkcionalnosti ukazov pa je po drugi strani privedlo do nove kategorije programskih jezikov, t.i. višjih programskih jezikov.
Prehod v višje programske jezike je povzročilo povečevanje kompleksnosti ukazov z združevanjem manj kompleksnih ukazov in pojavom novega mehanizma izvajanja skupine ukazov : podprogramov. Pri podprogramih koda posameznih ukazov v fazi pretvorbe programa ne nadomesti 'klica' podprograma in s tem razpihuje končne kode, temveč se izvrši na mestu, kjer je definirana. Se pravi, da v rezultativni kodi nastopa le enkrat in jo po potrebi pač večkrat izvedemo (kličemo).
Pri prehodu na višji programski jezik je potrebno rešiti še dva problema , ki zadevata nižje programske jezike in ju lahko kratko strnemo v dve točki:
Visokonivojski programski jeziki programerju omogočajo pisanje v notaciji, ki je človeku bližja, in se mu hkrati ni potrebno ukvarjati s specifičnimi lastnostmi strojnega jezika (zmanjševanje semantičnega prepada).
Tudi višje programske jezike glede na njihove značilnosti lahko delimo na več skupin. Omejimo se na pomembnejše:
strukturirani
značilno za to skupino je, da po procesu prevajanja struktura programa ostane nespremenjena. Tipični primeri takih programskij jezikov so : C, Pascal, Pyton, Java, ..
nestrukturirani
ponavadi v to skupino spadajo programski jeziki, ki podpirajo brezpogojne skoke v kodi. Če se dva taka skoka v kodi križata, obstajata vsaj dve možnosti, kako zaporedje stavkov takega programa prepisati v izvršno kodo. Tipičen primer take prograskega jezike je bil (zgodnji) Basic
postopkovni
so programski jeziki, kjer pri kodiranju opisujemo pot, po kateri bom prišli do rešitve. Primeri so: C, Pascal, Basic, ...
deklarativni
programiranje sloni na definiciji podatkov (objektov) in relacij oz. povezav med njimi. Pri tem ne programiramo poti do rešitve, temveč zastavljamo vprašanja (query) glede na definicije in prepustimo jeziku samemu, da poišče pot do rešitve. V to skupino bi lahko uvrstili: Prolog, List, SQL,..
proceduralni
osnovni gradnik programa je procedura; zaporedje oz. nabor funkcionalnosti, ki pa nima omejitve pri dostopu do podatkov oz. drugih delov procedur. Primeri: Pascal, Basic, C, ..
modularni / objektni
za te je značilno, da je osnovni element modul s svojo funkcionalnostjo in lastnostmi, ki pa so ograjene v modul. Do njegove vsebine lahko dostopamo je na način, kot ga predpisuje sam modul. Zato za modul pravimo, da se zaveda svoje zgradbe. Primeri: Eifel, Java, (C++),..
Programske jezike bi lahko razdelili tudi glede na njihov namen : za uporabo s podatkovnimi bazami, za uporabo na področju umetne inteligence, ...