sličica|220x220px|Zgled izvorne kode napisane v programskem jeziku Java, ki bo izpisala sporočilo "Hello World!" na standardni izhod ko je le-ta prevedena in izvršena.

Prográmski jêzik je stroju berljiv umetni jezik, ki je bil razvit, da izraža izračune oz. komputacije, katere lahko izvaja stroj oziroma računalnik. Programski jeziki so nastali zaradi razvoja računalnikov in so bili sprva podrejeni temu razvoju in je zato zgodnje obdobje razvoja programskih jezikov hkrati tudi zgodovina računalnikov..

Elementi

Vsi programski jeziki imajo nekaj osnovnih gradnikov za opis podatkov in procesov ali pretvorb, ki nanašajo nanje (kot npr. seštevanje dveh števil ali izbira elementa iz zbirke). Ti osnovni gradniki (primitivi) so opredeljeni s sintaktičnimi in semantičnimi pravili, ki opisujejo njihovo strukturo in pomen. Sintaksa je nabor pravil ali formul, ki določa množico (formalno pravilnih) stavkov. Pravila ne omogočajo samo ugotoviti ali je neko zaporedje stavek, določajo tudi samo zgradbo stavka, ki je nujna pri prepoznavanju njegovega pomena. Zato sta sintaksa in semantika tesno povezani.

Sintaksa (skladnja) opredeljuje strukturo stavkov programskega jezika, medtem ko semantika (pomenoslovje) predstavlja njen abstraktni pomen. Ker morajo vsi uporabniki jezika imeti enako predstavo o pomenu posameznih stavkov programskega jezika, morajo biti pravila, ki določajo sintakso in semantko natančno določena. Praviloma se sintaktične nepravilnosti ugotavljajo mnogo hitreje in enostavneje kot semantične. Del programske opreme prevajalnika, ki je odgovoren za ugotavljanje omenjenih nepravilnosti, se imenuje razčlenjevalnik (angl. parser), kateri izvaja analize skladnje pred prevodom izvorne kode v strojno kodo programske opreme.

Sintaksa (skladnja/slovnica) sličica|desno|292px|Obarvana sintaksa je pogosto v pomoč programerjem pri prepoznavanju elementov izvorne kode. Jezik zgoraj je Python.

Sintaksa programskega jezika ali nauk o zgradbi jezika govori o združevanju elementov jezika, na primer besed, v višje strukture, na primer v stavke. Enolično določa obliko dovoljenih izrazov v danem programskem jeziku. Večina programskih jezikov je tekstovnih; uporabljajo zaporedje besedila, ki vključuje besede, števila, ločila, podobno kot je to v naravnih jezikih. Na drugi strani obstaja tudi nekaj programskih jezikov, ki so grafični, ki omogoča uporabniku specifikacijo programa z grafičnimi elementi namesto z besedilom.

Sintaksa jezika obravnava možne kombinacije znakov in drugih elemetov jezika ter njihov medsebojni odnos ne glede na pomen teh kombinacij. Za pomen kombinacij simbolov je odgovorna semantika. Ker je večina jezikov tekstovnih, ta članek obravnava tekstovno sintakso.

Sintaksa programskega jezika je običajno podana s kombinacijo regularnih izrazov in metasintaktičnega jezika kot je Backus-Naurova notacija, ki podaja sintakso jezika v obliki razvidni iz naslednjega zgleda: <vsota>::= <sumand> + <sumand> <sumand>::= <konstanta> | <spremenljivka> Oklepaja "<" in ">" omogočata predstavitev gradnikov jezika s pomočjo besed oz. fraz naravnega jezika, znak "|" pa omogoča naštevanje alternativ. Takšna predstavitev sintakse je lahko razumljiva tako programerju kot računalniku, ki s prevajalnikom razpoznava programske stavke.

Spodaj je preprost zgled sintakse, ki temelji na programskem jeziku Lisp: izraz ::= atom | seznam atom ::= število | simbol število ::= [+-]?['0'-'9']+ simbol ::= ['A'-'Z''a'-'z'].* seznam ::= '(' izraz* ')'

Ta slovnica določa sledeče: izraz je ali atom ali list; atom je ali število ali simbol; število je neprekinjeno zaporedje en ali več desetiških cifer, z možnim predhodnim znakom za plus ali minus; simbol je črka, ki ji sledi nič ali več katerihkoli znakov (izključeni so presledki); in seznam je povezan par oklepajev, z nič ali več izrazi znotraj oklepajev.

Primeri dobro oblikovanega zaporedja žetonov (token) v tej sintaksi so: '12345', '()', '(a b c232 (1))'

Vsi sintaktično pravilni programi niso pravilni tudi semantično. Mnogo sintaktično pravilnih programov je slabo napisanih in lahko (odvisno od specifikacij jezika in trdnosti implementacije) ustvarijo napako pri prevajanju ali izvajanju. V nekaterih primerih se lahko taki programi obnašajo nepričakovano.

Zgled uporabe naravnega jezika za sintaktično pravilni stavek, ki pa mu ni mogoče določiti pomena: »Colorless green ideas sleep furiously. -Brezbarvne zelene ideje spijo besno.« (Noam Chomsky, 1957), je slovnično pravilno oblikovan toda nima splošno priznanega pomena. »Janez je poročen samec.« je slovnično pravilno oblikovan stavek toda izraža pomen, ki ne more biti pravilen.

Sledeči košček C jezika je sintaktično pravilen, ampak izvaja operacije, ki niso semantično definirane (operacija *p >> 4 nima pomena za vrednost kompleksnega tipa in p->im ni definiran ker je vrednost p null kazalec):

complex *p = NULL; complex abs_p = sqrt(*p >> 4 + p->im);

Če je deklaracija tipa iz prve vrstice izpuščena, bo program sprožil napako pri prevajanju, ker spremenljivka "p" ne bo definirana. Toda program bo še vedno sintaktično pravilen, ker deklaracija tipa zagotavlja le semantične informacije.

Slovnica, ki je potrebna za opredelitev programskega jezika, se lahko klasificira glede na svoj polažaj v hierarhiji Chomskega. Sintaksa večine programskih jezikov se lahko opredeli kot uporaba Slovnice tipa 2, t.j kontekstno neodvisne slovnice (context-free grammar). Section 2.2: Pushdown Automata, pp.101–114. Nekateri jeziki, vključno z Perl in Lisp, vsbujejo konstrukte, ki dovoljujejo izvajanje med fazo razčlenjevanje kode (parser). Jeziki, ki vsebujejo konstrukte, ki dovoljujejo programerju spreminjanje obnašanja razčlenjevalnika kode, napravijo analizo sintakse za nedoločljiv problem in na splošno zabrišejo razlikovanje med razčlenjevanjem kode in izvajanjem.Jeffrey Kegler, "Perl and Undecidability", The Perl Review. Papers 2 and 3 prove, using respectively Rice's theorem and direct reduction to the halting problem, that the parsing of Perl programs is in general undecidable.

Semantika

Izraz semantika se navezuje na pomen jezikovnih elementov v nasprotju z jezikovno obliko (sintakso). Včasih ima jezikovni element samo en pomen in mu je prirejena ena sama stvar. Običajno pa moremo pravi pomen besede razbrati šele iz konteksta. Semantiko programskih stavkov je zelo težko opisati s formalnimi jeziki.

Statična semantika

Statična semantika opredeljuje omejitve za strukturo veljavnih besedil, ki jih težko izrazimo s standardnimi sintaktičnimi formalizmi. Za prevedene jezike statična semantika vključuje zlasti tista pravila, ki se jih lahko preveri med prevajanjem. Primeri vključujejo preverjanje prisotnosti deklaracij identifikatorjev predno je uporabljen (v jezikih, ki takšne deklaracije zahtevajo) ali pa, da se uporabljene labele v case stavku med seboj razlikujejo.Michael Lee Scott, Programming language pragmatics, Edition 2, Morgan Kaufmann, 2006, ISBN 0-12-633951-1, p. 18–19 Veliko pomembnih omejitev tega tipa (kot je to preverjanje, da so identifikatorji uporabljeni v ustreznem kontekstu, ali da klici podprogramov vsebujejo pravilno število in tip argumentov) se lahko uveljavi tako, da se jih definira kot pravilo v logiki imenovani sistem tipov. Druge oblike statične analize kot je analiza toka podatkov so lahko prav tako del statične semantike.

Dinamična semantika

Ko so enkrat podatki opredeljeni, se mora stroju podati navodila za izvajanje operacij nad podatki. Na primer, semantika lahko definira strategijo s katero se izrazi ovrednotijo za vrednosti ali način s katerim kontrolne strukture pogojno izvajajo stavke. Dinamična semantika (poznana tudi kot "semantika izvajanja") jezika definira kako in kdaj naj določen konstrukt jezika izvede določeno obnašanje programa. Obstaja več načinov definiranja semantike izvajanja. Za določitev semantike izvajanja jezikov se pogosto uporabi naravni jezik.

Sistemi tipov Sistem tipov definira kako programski jezik razvršča vrednosti in izraze v tipe, kako z njimi ravna in kako so medsebojno povezani. Cilj sistema tipov je preverjanje in običajno uveljavljanje nekega nivoja pravilnosti napisanih programov z detekcijo nepravilnih operacij. Vsak odločljiv sistem tipov vključuje kompromis: medtem ko zavrača številne nepravilne programe, lahko prepove tudi nekatere pravilne četudi neobičajne programe. V večini tipiziranih jezikih se sistem tipov uporablja le za preverjanje tipov (type checking) programov, toda nekateri jeziki se zanašajo na programerja, da bo pravilno opredelil tipe. Formalno obravnavanje tipov se imenuje tudi teorija tipov.

Tipizirani jezik proti netipiziranemu

Jezik je tipiziran, če specifikacija vsake operacije definira tip podatkov te operacije. Na primer, podatek predstavljen z "to besedilo med narekovaji " je string. V večini programskih jezikov deljenje števila s stringom nima pomena; zato bo večina modernih programskih jezikov zavrnila vsak poskus izvajanja programa, ki bi izvajal takšno operacijo. V nekaterih jezikih se vsaka nesmiselna operacija zazna pri prevajanju programa (»statično« preverjanje tipov) in jo zavrne že prevajalnik; medtem ko se pri ostalih jezikih zazna šele pri izvajanju programa (»dinamično« preverjanje tipov), kar povzroči izjeme v času izvajanja (run-time exception; programska napaka, ki običajno kaže na »hrošče«).

Netipizirani jezik, kot je to večina zbirnih jezikov, dovoljuje izvajanje katerekoli operacije nad katerimkoli podatkom, in se jih običajno obravnava kot zaporedja bitov različne dolžine.

V praksi se malo jezikov opredeljuje kot tipizirane s stališča teorije tipov (preverjanje in zavračanje vseh operacij), večina modernih jezikov ponuja določeno stopnjo tipizacije. Nekateri jeziki omogočajo eksplicitne pretvorbe med podatkovnimi tipi; s tem se varnost tipiziranja zamenja z natančnejšo kontrolo izvajanja programa (glej eksplicitne pretvorbe).

Statično tipiziranje proti dinamičnemu

Glede na čas preverjanja tipov ločimo dve skupini programskih jezikov: jeziki statičnih tipov (statically typed languages) in jeziki dinamičnih tipov (dynamically typed languages). Značilnost statičnega tipiziranja je, da ima vsaka spremenljivka in prameter tip, ki ga določi programer. Preverjanje tipa se preveri še pred izvajanjem programa, običajno v času prevajanja. Na primer, 1 in (2+2) sta integer izraza; ne moreta biti posredovana funkciji, ki pričakuje string, ne moreta biti shranjena v spremenljivki, ki vsebuje datume.

Jeziki statičnih tipov so ali vidno tipizirani (manifest typing) ali pa so tipizirani s sklepanjem (type inference). V prvem primeru mora programer eksplicitno napisati tipe na določenem mestu v kodi. V drugem primeru prevajalnik sklepa o tipu izrazov in deklaracij glede na kontekst. O sklepanju o tipu govorimo takrat, kadar tip entitete ni podan, temveč ga povzamemo iz okolice. Večina prevladujočih statično tipiziranih jezikov, kot so C++, C# in Java, so vidno tipizirani. Popolno tipiziranje s sklepanjem je običajno povezano z neprevladujočimi jeziki kot sta Haskell in ML. Kakorkoli, veliko vidno tipiziranih jezikov podpira delno tipiziranje s sklepanjem; na primer, Java in C# vsebujeta v omejenem obsegu tudi tipiziranje s sklepanjem.Specifically, instantiations of generic types are inferred for certain expression forms. Type inference in Generic Java—the research language that provided the basis for Java 1.5's bounded parametric polymorphism extensions—is discussed in two informal manuscripts from the Types mailing list: Generic Java type inference is unsound (Alan Jeffrey, 17 December 2001) and Sound Generic Java type inference (Martin Odersky, 15 January 2002). C#'s type system is similar to Java's, and uses a similar partial type inference scheme.