miniatura|Diagrama de blocs de l'operació d'un bon compilador. Un compilador és un programa informàtic que tradueix un programa escrit en un llenguatge de programació a un altre llenguatge de programació i que genera un programari equivalent que la màquina serà capaç d'interpretar. El segon llenguatge sol ser el llenguatge de màquina, però també pot ser un codi intermedi (bytecode), o simplement text. Aquest procés de traducció es coneix com a compilació.

Permet traduir el codi font d'un programa en llenguatge d'alt nivell, a un altre llenguatge de nivell inferior (típicament llenguatge de màquina). D'aquesta manera un programador pot dissenyar un programa en un llenguatge molt més proper a com pensa un ésser humà, per després compilar-ho a un programa més manejable per un ordinador.

Com a part important d'aquest procés de traducció, un compilador de bona qualitat sol informar l'usuari de la presència d'errors en el codi font.

El concepte va ser encunyat per la militar nord-americana Grace Hopper (1906-1992).

Parts d'un compilador La construcció d'un compilador implica la divisió del procés en una sèrie de fases que varia segons la complexitat. Aquestes fases es solen agrupar en dues tasques: l'anàlisi del programari font i la síntesi del programari de destinació.

Anàlisi: És la comprovació de la correcció del programa font, i inclou les fases corresponents a l'Anàlisi lèxica (que consisteix en la descomposició del programa font en components lèxics), l'Anàlisi sintàctica (agrupació dels components lèxics en frases gramaticals) i l'Anàlisi semàntica (comprovació de la validesa semàntica de les sentències acceptades a la fase d'Anàlisi sintàctica). Síntesi: sol generar la sortida expressada en el llenguatge de destinació i sol estar formada per una o diverses combinacions de fases de generació de codi i d'optimització de codi en el qual es cerca obtenir un codi el més eficient possible.

Alternativament, les fases descrites per a les tasques d'anàlisi i síntesi es poden agrupar en front-end i back-end:

Front-end: és la part que analitza el codi font, comprova la seva validesa, genera l'arbre de derivació i omple els valors de la taula de símbols. Aquesta part sol ser independent de la plataforma o sistema per al qual es vagi a compilar, i està composta per les fases compreses entre l'Anàlisi lèxica i la Generació de Codi Intermedi. Back-end: és la part que genera el codi màquina, específic d'una plataforma, a partir dels resultats de la fase d'anàlisi, realitzada pel Front End.

Aquesta divisió permet que el mateix back end s'utilitzi per generar el codi màquina de diversos llenguatges de programació diferents i que el mateix front end que serveix per analitzar el codi font d'un llenguatge de programació concret serveixi per generar codi màquina en diverses plataformes diferents. Sol incloure la generació i optimització del codi dependent de la màquina.

El codi que genera el back-end normalment no es pot executar directament, sinó que ha de menester sun enllaç mitjançant un programa enllaçador (linker).

Història El 1946 es va desenvolupar el primer ordenador numèric. Al principi, aquestes màquines executaven instruccions consistents en codis numèrics que assenyalaven als circuits de la màquina els estats corresponents a cada operació, el que es va denominar llenguatge màquina.

Aviat els primers usuaris d'aquests ordinadors van descobrir l'avantatge d'escriure el programari mitjançant claus més fàcils de recordar que aquests codis, al final, totes aquestes claus juntes es traduïen manualment a llenguatge màquina. Aquestes claus constitueixen els anomenats llenguatges assembladors.

Malgrat tot, el llenguatge d'assemblador romania el llenguatge d'una màquina, però més fàcil de manejar. Els treballs de recerca es van orientar cap a la creació d'un llenguatge que expressés les diferents accions a realitzar d'una manera el més senzilla possible per a una persona. El primer compilador va ser escrit per Grace Hopper, el 1952 per al llenguatge de programació A-0. El 1950 John Backus va dirigir una recercae a IBM sobre un llenguatge algebraic. El 1954 es va començar a desenvolupar un llenguatge que permetia escriure fórmules matemàtiques de manera traduïble per un ordinador, va ser anomenat FORTRAN (Formulae translator). Va ser el primer llenguatge d'alt nivell i es va introduir el 1957 per a l'ús de l'ordinador IBM model 704.

Va sorgir així per primera vegada el concepte d'un traductor com un programa que traduïa un llenguatge a un altre llenguatge. En el cas particular en que el llenguatge a traduir és un llenguatge d'alt nivell i el llenguatge traduït de baix nivell, s'empra el terme compilador.

La tasca de fer un compilador no va ser fàcil. El primer compilador de FORTRAN trigar 18 anys-persona a realitzarse i era molt senzill. Aquest desenvolupament de FORTRAN estava molt influenciat per la màquina objecte on havia de ser implementat. Com a exemple d'això tenim el fet que els espais en blanc fossin ignorats, pel fet que el perifèric que s'utilitzava com a entrada de programes (una lectora de targetes perforades) no comptava correctament els espais en blanc.

El primer compilador autocontingut, és a dir, capaç de compilar el seu propi codi font va ser el creat per a Lisp per Hart i Levin al MIT el 1962. D'aleshores ençà a poc a poc va esdevenir una pràctica comuna escriure el compilador en el mateix llenguatge que aquest compila, encara que Pascal i C van quedar alternatives molt usades.

Crear un compilador autocontingut genera un problema anomenat bootstrapping, és a dir el primer compilador creat per a un llenguatge ha de, o bé ser compilat per un compilador escrit en un altre llenguatge, o bé compilat per a executar el compilador en un intèrpret.

Tipus de compiladors Aquesta taxonomia dels tipus de compiladors no és excloent, pel que pot haver compiladors que s'adscriguin a diverses categories:

Compiladors creuats: generen codi per a un sistema operatiu o arquitectura diferent del que estan funcionant. Compiladors optimitzadors: realitzen canvis en el codi per millorar la seva eficiència, però mantenint la funcionalitat del programa original. Compiladors d'una sola passada: generen el codi màquina a partir d'una única lectura del codi font. Compiladors de diverses passades: necessiten llegir el codi font diverses vegades abans de poder produir el codi màquina. Compiladors JIT (Just In Time): formen part d'un intèrpret i compilen parts del codi segons es necessiten.

Pauta de creació d'un compilador: En les primeres èpoques de la informàtica, el programari dels compiladors era considerat com un dels més complexos existents.

Els primers compiladors es van realitzar programant-los directament en llenguatge màquina o en assemblador. Un cop es disposa d'un compilador, es poden escriure noves versions del compilador (o altres compiladors diferents) en el llenguatge que compila aquest compilador.

Actualment hi ha eines que faciliten la tasca d'escriure compiladors o intèrprets informàtics. Aquestes eines permeten generar l'esquelet de l'analitzador sintàctic a partir d'una definició formal del llenguatge de partida, especificada normalment mitjançant una gramàtica formal i barata, deixant únicament al programador del compilador la tasca de programar les accions semàntiques associades.

Procés de compilació És el procés pel qual es tradueixen les instruccions escrites en un determinat llenguatge de programació a llenguatge màquina. A més d'un traductor, es poden necessitar altres programes per crear un programa objecte executable. Un programa font es pot dividir en mòduls emmagatzemats en arxius diferents. La tasca de reunir el programa font sovint es confia a un programa diferent, anomenat preprocessador. El preprocessador també pot expandir abreviatures, crides a macros, a proposicions del llenguatge font.

Normalment la creació d'un programa executable (un típic.exe per a Microsoft Windows o DOS) comporta dos passos. El primer pas es diu compilació (pròpiament dit) i tradueix el codi font escrit en un llenguatge de programació emmagatzemat en un arxiu a codi de baix nivell (normalment en codi objecte, no directament a llenguatge màquina). El segon pas es diu enllaçat en el qual s'enllaça el codi de baix nivell generat de tots els fitxers i subprogrames que s'han enviat compilar i s'afegeix el codi de les funcions que hi ha a les biblioteques del compilador perquè l'executable pugui comunicar-se directament amb el sistema operatiu, traduint així finalment el codi objecte a codi màquina, i generant un mòdul executable.

Aquests dos passos es poden fer per separat, emmagatzemant el resultat de la fase de compilació en arxius objectes (un típic .obj per a Microsoft Windows, DOS o per a Unix), per a enllaçar-los en fases posteriors, o crear directament l'executable, amb la qual cosa la fase de compilació s'emmagatzema només temporalment. Un programa podria tenir parts escrites en diversos llenguatges (per exemple C, C + + i Asm), que es podrien compilar de forma independent i després enllaçar juntes per formar un únic mòdul executable.

Etapes del procés El procés de traducció es compon internament de diverses etapes o fases, que realitzen diferents operacions lògiques. És útil pensar en aquestes fases com en peces separades dins del traductor, i poden escriure's en realitat com operacions codificades separadament encara que en la pràctica sovint s'integrin juntes.

Fase d'anàlisi Anàlisi lèxica

L'anàlisi lèxica constitueix la primera fase, aquí es llegeix el programa font d'esquerra a dreta i s'agrupa en components lèxics (tokens), que són seqüències de caràcters que tenen un significat. A més, tots els espais en blanc, línies en blanc, comentaris i altra informació innecessària s'elimina del programa font. També es comprova que els símbols del llenguatge (paraules clau, operadors, etc.) S'han escrit correctament.

Com que la tasca que realitza l'analitzador lèxic és un cas especial de coincidència de patrons, es necessiten els mètodes d'especificació i reconeixement de patrons, s'usen principalment els autòmats finits que acceptin expressions regulars. No obstant això, un analitzador lèxic també és la part del traductor que maneja l'entrada del codi font, i ja que aquesta entrada sovint involucra una important despesa de temps, l'analitzador lèxic ha de funcionar de manera tan eficient com sigui possible.

Anàlisi sintàctica

En aquesta fase els caràcters o components lèxics s'agrupen jeràrquicament en frases gramaticals que el compilador utilitza per sintetitzar la sortida. Es comprova si l'obtingut de la fase anterior és sintàcticament correcte (obeeix a la gramàtica del llenguatge). En general, les frases gramaticals del programa font es representen mitjançant un arbre d'anàlisi sintàctica.

L'estructura jeràrquica d'un programa normalment s'expressa utilitzant regles recursives. Per exemple, es poden donar les següents regles com a part de la definició d'expressions :

Qualsevol identificador és una expressió. Qualsevol nombre és una expressió. Si expressió1 i expressió₂ són expressions, llavors també ho són: expressió1 + expressió₂ expressió 1 * expressió₂ (expressió1)

Les regles 1 i 2 són regles bàsiques (no recursives), mentre que la regla 3 defineix expressions en funció d'operadors aplicats a altres expressions.