SØK

Oversetteren er ... Typer oversettere. Konverter og oversett programmet

Programmer, som mennesker, krever en oversetter eller oversetter å oversette fra ett språk til et annet.

Grunnleggende begreper

Programmet er språkligrepresentasjon av beregningene: i → P → P (i). Tolken er et program som er matet til programmet P og noen inngangsdata x. Den utfører P på x: I (P, x) = P (x). Det faktum at det kun er én oversetter som er i stand til å utføre alle mulige programmer (som kan representeres i det formelle systemet) er en svært dyp og betydelig oppdagelse av Turing.

Prosessoren er programtolken påmaskin språk. Det er vanligvis for dyrt å skrive tolker for språk på høyt nivå, så de blir oversatt til et skjema som er enklere å tolke.

Noen typer oversettere har veldig merkelige navn:

  • Assembler oversetter programmer i assembler til maskinspråk.
  • Kompilatoren oversetter fra et språk på høyt nivå til et språk på lavere nivå.

En oversetter er et program som akseptererSom input programmet i noen språk S og gir ut programmet i språk T slik at de begge har samme semantikk: P → X → Q. Det er, ∀x. P (x) = Q (x).

oversetter er

Hvis du sender hele programmet til noetolket, kalles det en samling før henrettelsen, eller AOT samling. AOT kompilatoren kan brukes i serie, er det sistnevnte som ofte assembler, for eksempel:

Kildekode → Kompilator (kompilator) → Assembler kode → Assembler (oversetter) → Maskinkode → CPU (tolk).

Operativ eller dynamisk kompileringoppstår hvis en del av programmet oversettes når andre kompilerte deler utføres. JIT-oversettere husker hva de allerede har gjort, for ikke å gjenta kildekoden igjen og igjen. De kan til og med produsere adaptiv kompilering og rekompilering, basert på oppførselen til programmets runtime-miljø.

Mange språk lar deg utføre koden under oversettelse og kompilere ny kode under programkjøp.

Stages of broadcast

Oversetteren består av stadier av analyse og syntese:

Kildekode → Analyzer → Konseptuell representasjon → Generator (synthesizer) → Målkode.

Dette skyldes følgende grunner:

  • Enhver annen måte er ikke egnet. Den bokstavelige oversettelsen virker bare ikke.
  • God teknisk løsning: Hvis du trenger å skrive oversettere for M-kildespråk og N-målsspråk, må du bare skrive M + N enkle programmer (semikompilatorer), ikke M × N komplekse programmer (full oversettere).

typer oversettere

Men i praksis, den konseptuelleen representasjon er svært sjelden ekspressiv og kraftig nok til å omfatte alle tenkelige kilder og målrettede språk. Selv om noen var i stand til å komme nær dette.

Ekte kompilatorer går gjennom mangeetapper. Når du lager din egen kompilator, trenger du ikke å gjenta alt det harde arbeidet som folk allerede har gjort mens du lager visninger og generatorer. Du kan kringkaste ditt språk direkte i JavaScript eller C og bruke eksisterende JavaScript-motorer og C-kompilatorer til å gjøre resten. Du kan også bruke eksisterende mellomvisninger og virtuelle maskiner.

Oversetter opptak

En oversetter er et program eller tekniskbetyr hvilke tre språk som er involvert: kilde, mål og grunnleggende. De kan skrives i T-skjemaet, plasserer kilden til venstre, målet til høyre og basen nedenfor.

Det er tre typer kompilatorer:

  • En oversetter er en selvkompiler hvis kildespråket stemmer overens med basisspråket.
  • En kompilator hvis målspråk er lik basen, kalles selvboende.
  • En oversetter er en kryssompiler hvis mål og grunnleggende språk er forskjellige.

kringkasting av programmet

Hvorfor er dette viktig?

Selv om du aldri lager en ekte kompilator, er det godt å vite om teknologien i etableringen, fordi konseptene som brukes til dette formålet, brukes universelt, for eksempel i:

  • tekstformatering;
  • database spørrespråk;
  • utvidede dataarkitekturer;
  • generaliserte optimaliseringsproblemer;
  • grafiske grensesnitt;
  • skriptspråk
  • regulerende midler;
  • virtuelle maskiner;
  • maskinoversettelser.

I tillegg, hvis du trenger å skrive forprosessorer, montører, lastere, debuggere eller profilere, må du gå gjennom de samme trinnene som når du skriver en kompilator.

Du kan også lære å skrive bedre programmer.siden opprettelsen av en oversetter for et språk betyr en bedre forståelse av sine subtiliteter og tvetydigheter. Ved å studere de generelle oversettelsesprinsippene kan du også bli en god språkdesigner. Det spiller ingen rolle hvor kult språket er hvis det ikke kan implementeres effektivt?

Omfattende teknologi

Kompilatorteknologi dekker mange forskjellige områder innen datavitenskap:

  • formell språkteori: grammatikk, parsing, beregningsbarhet;
  • Datamaskinarkitektur: instruksjonssett, RISC eller CISC, pipelining, kjerner, klokkeslett, etc .;
  • programmeringsspråk konsepter: for eksempel utførelse sekvenskontroll, betinget utførelse, iterasjon, rekursjon, funksjonell dekomponering, modularitet, synkronisering, metaprogrammering, omfang, konstanter, undertyper, mønstre, utgangstype, prototyper, annoteringer, strømmer, monader, postkasser, fortsettelser, jokertegn, regulære uttrykk, transaksjonshukommelse, arv, polymorfisme, parametermodi og så videre;
  • abstrakte språk og virtuelle maskiner;
  • algoritmer og datastrukturer: vanlige uttrykk, parsing algoritmer, grafiske algoritmer, dynamisk programmering, trening;
  • programmeringsspråk: syntaks, semantikk (statisk og dynamisk), paradigmestøtte (strukturell, OOP, funksjonell, logisk, stabel, parallellisme, metaprogrammering);
  • programvareopprettelse (kompilatorer, som regel store og komplekse): lokalisering, caching, komponentspesifikasjon, API-grensesnitt, gjenbruk, synkronisering.

programkonvertering

Kompilator design

Noen problemer som oppstår når du utvikler en ekte oversetter:

  • Kildeproblemer. Er det lett å kompilere? Er det en preprosessor? Hvordan håndteres typer? Er det biblioteker tilgjengelig?
  • Gruppering av kompilatorpass: enkelt eller multi-pass?
  • Graden av optimalisering ønsket. Rask og urent kringkasting av programmet med liten eller ingen optimalisering kan være normal. Overdreven optimalisering vil redusere kompilatoren, men den beste koden ved kjøring kan være verdt det.
  • Nødvendig feilvarslingsfrekvens. Kan oversetteren bare stoppe ved den første feilen? Når skal han stoppe? Tillater kompilatoren feilkorreksjon?
  • Tilgjengelighet av verktøy. Hvis kildespråket ikke er veldig lite, er skanneren og analysatorgeneratoren påkrevd. Det er også generatorer av kodegeneratorer, men de er ikke så vanlige.
  • Type målkode som skal genereres. Det bør velges fra ren, forsterket eller virtuell maskinkode. Eller bare skriv et innspill som skaper populære mellomliggende visninger som LLVM, RTL eller JVM. Eller gjør oversettelse fra kilde til kildekode i C eller JavaScript.
  • Formatet til målkoden. Du kan velge monteringsspråk, bærbar maskinkode, maskinskriftsminnebilde.
  • Retargeting. Med mange generatorer er det godt å ha en felles inngang. Av samme grunn er det bedre å ha en generator for mange inngangsdele.

dynamisk kompilering

Kompilatorarkitektur: Komponenter

Dette er de viktigste funksjonelle komponentene til en oversetter som genererer maskinkode (hvis utdataprogrammet er et C-program eller en virtuell maskin, så er det ikke mange trinn som kreves):

  • Inndataprogrammet (strøm av tegn) går inn i skanneren (leksikalanalysator), som konverterer den til en strøm av tokens.
  • Parseren (parseren) bygger et abstrakt syntaks-tre fra dem.
  • Semantisk analysator dekomponerersemantisk informasjon og kontrollerer tre noder for feil. Som et resultat er en semantisk graf bygd - et abstrakt syntaktisk tre med flere egenskaper og etablerte linker.
  • Mellomkodgeneratoren bygger en flytdiagram (tupler er gruppert i hovedblokker).
  • Maskin uavhengig kodeoptimereren utfører somlokalt (innenfor basenheten) og global optimalisering (for alle blokker), hovedsakelig gjenværende innenfor delrutinene. Reduserer redundanskode og forenkler beregninger. Resultatet er en modifisert flytdiagram.
  • Målkodegeneratoren kobler basisblokkene i en lineær kode med overføring av kontroll, og lager en objektfil i en assembler med virtuelle registre (muligens ineffektiv).
  • Maskinspesifikk optimeringslinkertildeler minne mellom registre og utfører kommandobeskrivelse. Det utfører konverteringen av et assemblerprogram til en ekte monterer med god bruk av rørledninger.

I tillegg benyttes delsystemer for feilsøking og symboltabellbehandling.

objektfil

Lexisk analyse (skanning)

Skanneren konverterer en strøm av tegn fra kildekoden til en strøm av tokens, fjerning av mellomrom, kommentarer og utvidelse av makroer.

Skannere støter ofte på problemer som om man skal ta eller ikke ta hensyn til registret, strekkordene, linjematene og nestede kommentarer.

Feil som kan oppstå under skanning kalles leksikalsk og inkluderer:

  • tegn mangler i alfabetet;
  • overskudd av antall tegn i et ord eller en linje;
  • ikke en lukket karakter eller streng bokstavelig;
  • slutten av filen i kommentarer.

Parsing (parsing)

Parseren konverterer en sekvens av tokens tilabstrakt syntakttre. Hvert tre node lagres som et objekt med navngitte felter, hvorav mange er selve tre noder. Det er ingen sykluser på dette stadiet. Når du oppretter en parser, må du være oppmerksom på nivået av grammatikkompleksitet (LL eller LR) og finne ut om det er noen regler for disambiguering. Noen språk krever semantisk analyse.

Feil som oppstår på dette stadiet kalles syntaktisk. For eksempel:

  • k = 5 * (7 - y;
  • j = / 5;
  • 56 = x * 4.

Semantisk analyse

Under den semantiske analysenDet er nødvendig å sjekke regler for tillatbarhet og lenke deler av det syntaktiske treet (løse navneforbindelser, sette inn operasjoner for implisitt type konvertering, etc.) for å danne en semantisk graf.

Tydeligvis er settet med adgangsregler forskjellig for forskjellige språk. Hvis Java-lignende språk er kompilert, kan oversettere finne:

  • flere deklarasjoner av en variabel innenfor sitt omfang
  • referanser til en variabel før erklæringen;
  • referanser til et svart navn;
  • brudd på tilgjengelighet
  • for stort eller utilstrekkelig antall argumenter når man ringer metoden;
  • skriv feil samsvar.

inngangsprogram

generasjon

Generering av en mellomkode gir en strømgraf som består av tupler gruppert i grunnblokker.

Kodegenerering gir ekte maskinkode. I tradisjonelle kompilatorer for RISC-maskiner, i første fase, opprettes en assembler med et uendelig antall virtuelle registre. For CISC-maskiner vil dette nok ikke skje.

  • evaluering: