Ce este un design al compilatorului? Tipuri, instrumente de construcție, exemplu

⚡ Rezumat inteligent

Fazele compilatorului descriu cele șase etape care transformă codul sursă în cod mașină: analiza lexicală, analiza sintactică, analiza semantică, generarea de cod intermediar, optimizarea codului și generarea de cod, susținută de gestionarea tabelului de simboluri și tratarea erorilor.

  • 🔤 Analiza lexicala: Scanerul grupează caracterele în jetoane și le înregistrează în tabela de simboluri.
  • 🌳 Analiza sintaxei: Analizatorul verifică gramatica și construiește un arbore de analiză ierarhică din jetoane.
  • ✔️ Analiza semantică: Această fază verifică compatibilitatea tipurilor și semnificația folosind arborele sintactic.
  • ⚙️ Code Generaţie: Codul intermediar este generat, optimizat și în final tradus în cod mașină țintă.
  • 📋 Rutine de asistență: O tabelă de simboluri și o rutină de tratare a erorilor interacționează cu fiecare fază de compilare.

Fazele compilatorului cu exemplu: Procesul și pașii de compilare

Care sunt fazele de proiectare a compilatorului?

A compilator funcționează în diferite faze, iar fiecare fază transformă programul sursă dintr-o reprezentare în alta. Fiecare fază preia intrări din etapa anterioară și transmite ieșirea sa către următoarea fază a compilatorului. Există 6 faze într-un compilator. Fiecare dintre aceste faze ajută la convertirea limbajului de nivel înalt în cod mașină. Fazele unui compilator sunt:

  1. Analiza lexicală
  2. Analiza sintaxei
  3. Analiza semantică
  4. Generator de cod intermediar
  5. Code Instrumentul de optimizare a
  6. Code generator

Fazele compilatorului

Fazele compilatorului

Toate aceste faze convertesc codul sursă prin împărțirea acestuia în token-uri, crearea de arbori de parse și optimizarea codului sursă prin diferite faze.

Faza 1: Analiza lexicală

Analiza lexicală este prima fază, în care compilatorul scanează codul sursă. Acest proces poate fi efectuat de la stânga la dreapta, caracter cu caracter, și grupează aceste caractere în token-uri.

Aici, fluxul de caractere din programul sursă este grupat în secvențe semnificative prin identificarea token-urilor. Se efectuează introducerea token-urilor corespunzătoare în tabela de simboluri și se transmite acel token fazei următoare.

Funcțiile principale ale acestei faze sunt:

  • Identificați unitățile lexicale dintr-un cod sursă.
  • Clasificați unitățile lexicale în clase precum constante, cuvinte rezervate și introduceți-le în tabele diferite. Comentariile din programul sursă vor fi ignorate.
  • Identificați un token care nu face parte din limbaj.

Exemplu: x = y + 10

Simbol Tip
X identificator
= Operator de misiune
Y identificator
+ Operator de adaos
10 Număr

Faza 2: Analiza sintaxei

Analiza sintaxei are ca scop descoperirea structurii unui cod. Aceasta determină dacă un text respectă sau nu formatul așteptat. Scopul principal al acestei faze este de a se asigura că codul sursă scris de programator este corect sau nu.

Analiza sintactică se bazează pe regulile limbajului de programare specific prin construirea arborelui de analiză sintactică cu ajutorul unor token-uri. De asemenea, determină structura limbajului sursă și gramatica sau sintaxa limbajului.

Iată o listă de sarcini efectuate în această fază:

  • Obțineți jetoane de la analizatorul lexical.
  • Verificați dacă expresia este corectă din punct de vedere sintactic sau nu.
  • Raportați toate erorile de sintaxă.
  • Construiți o structură ierarhică cunoscută sub numele de arbore de analiză sintactică.

Exemplu

Orice identificator/număr este o expresie. Dacă x este un identificator și y+10 este o expresie, atunci x = y+10 este o instrucțiune. Luați în considerare arborele de analiză sintactică pentru următorul exemplu:

(a+b)*c

Exemplu de analiză de sintaxă

În arborele de analiză:

  • Nod interior: înregistrare cu un câmp operator și două câmpuri pentru copii.
  • Frunză: înregistrări cu 2 sau mai multe câmpuri; unul pentru token și alte informații despre token.
  • Asigurați-vă că componentele programului se potrivesc între ele în mod semnificativ.
  • Colectează informații despre tipuri și verifică compatibilitatea tipurilor.
  • Operanzii de verificare sunt permiși de limbajul sursă.

Faza 3: Analiza semantică

Analiza semantică verifică consistența semantică a codului. Utilizează arborele de sintaxă al fazei anterioare împreună cu tabelul de simboluri pentru a verifica dacă codul sursă dat este consistent din punct de vedere semantic. De asemenea, verifică dacă codul transmite un sens adecvat.

Analizatorul semantic va verifica neconcordanțe de tip, operanzi incompatibili, o funcție apelată cu argumente improprii, o variabilă nedeclarată etc.

Funcțiile fazei de analiză semantică sunt:

  • Vă ajută să stocați informațiile de tip colectate și să le salvați în tabelul de simboluri sau în arborele sintactic.
  • Vă permite să efectuați verificarea tipului.
  • În cazul unei nepotriviri de tip, unde nu există reguli exacte de corecție a tipului care să satisfacă operația dorită, se afișează o eroare semantică.
  • Colectează informații despre tipuri și verifică compatibilitatea tipurilor.
  • Verifică dacă limbajul sursă permite operanzii sau nu.

Exemplu

float x = 20.2;
float y = x*30;

În codul de mai sus, analizorul semantic va converti numărul întreg 30 la un număr mobil 30.0 înainte de înmulțire.

Faza 4: Intermediară Code Generație

Odată ce faza de analiză semantică este finalizată, compilatorul generează cod intermediar pentru mașina țintă. Acesta reprezintă un program pentru niște abstracmașină t.

Codul intermediar se află între limbajul de nivel înalt și cel de nivel mașină. Acest cod intermediar trebuie generat într-un mod care să faciliteze traducerea sa în codul mașină țintă.

Funcțiile intermediarului Code generaţie:

  • Ar trebui să fie generat din reprezentarea semantică a programului sursă.
  • Păstrează valorile calculate în timpul procesului de traducere.
  • Te ajută să traduci codul intermediar în limba țintă.
  • Vă permite să mențineți ordinea de prioritate a limbii sursă.
  • Conține numărul corect de operanzi ai instrucțiunii.

Exemplu

De exemplu:

total = count + rate * 5

Codul intermediar cu ajutorul metodei codului de adresă este:

t1 := int_to_float(5)
t2 := rate * t1
t3 := count + t2
total := t3

Faza 5: Code Optimizare

Următoarea fază este optimizarea codului intermediar. Această fază elimină liniile de cod inutile și aranjează secvența de instrucțiuni pentru a accelera execuția programului fără a irosi resurse. Scopul principal al acestei faze este de a îmbunătăți codul intermediar pentru a genera un cod care rulează mai rapid și ocupă mai puțin spațiu.

Funcțiile principale ale acestei faze sunt:

  • Te ajută să stabilești un compromis între viteza de execuție și cea de compilare.
  • Îmbunătățește timpul de execuție al programului țintă.
  • Generează cod simplificat încă în reprezentare intermediară.
  • Eliminarea codului inaccesibil și eliminarea variabilelor neutilizate.
  • Eliminarea instrucțiunilor care nu sunt modificate din buclă.

Exemplu: Luați în considerare următorul cod:

a = intofloat(10)
b = c * a
d = e + b
f = d

Poate deveni:

b = c * 10.0
f = e + b

Faza 6: Code Generație

Code Generarea este ultima și finala fază a unui compilator. Aceasta primește date de intrare din faza de optimizare a codului și produce codul paginii sau codul obiect ca rezultat. Obiectivul acestei faze este de a aloca spațiu de stocare și de a genera cod mașină relocabil.

De asemenea, alocă locații de memorie pentru variabile. Instrucțiunile din codul intermediar sunt convertite în instrucțiuni mașină. Această fază convertește codul optimizat sau intermediar în limbajul țintă.

Limbajul țintă este codul mașină. Prin urmare, toate locațiile de memorie și registrele sunt, de asemenea, selectate și alocate în timpul acestei faze. Codul generat de această fază este executat pentru a prelua intrări și a genera ieșirile așteptate.

Exemplu

a = b + 60.0 ar putea fi tradus în registre astfel:

MOVF a, R1
MULF #60.0, R2
ADDF R1, R2

Managementul tabelului de simboluri

Un tabel de simboluri conține o înregistrare pentru fiecare identificator, cu câmpuri pentru atributele identificatorului. Această componentă facilitează căutarea înregistrării identificatorului de către compilator și recuperarea rapidă a acesteia. Tabelul de simboluri vă ajută, de asemenea, la gestionarea domeniului de aplicare. Tabelul de simboluri și instrumentul de tratare a erorilor interacționează cu toate fazele, iar tabelul de simboluri este actualizat în mod corespunzător.

Rutina de gestionare a erorilor

În procesul de proiectare a compilatorului, pot apărea erori în toate fazele de mai jos:

  • Analizator lexical: Jetoane scrise greșit.
  • Analizator de sintaxă: Paranteză lipsă.
  • Generator de cod intermediar: Operanzi nepotriviți pentru un operator.
  • Code Optimizator: Când afirmația nu este accesibilă.
  • Code Generator: Când memoria este plină sau nu sunt alocate registrele corespunzătoare.
  • Tabele de simboluri: Eroare la declararea mai multor identificatori.

Cele mai frecvente erori sunt secvențele de caractere nevalide la scanare, secvențele de token-uri nevalide în tip, erorile de domeniu și analiza semantică.

Eroarea poate apărea în oricare dintre fazele de mai sus. După identificarea erorilor, faza trebuie să le trateze pentru a continua procesul de compilare. Aceste erori trebuie raportate către handlerul de tratare a erorilor, care gestionează eroarea pentru a efectua procesul de compilare. În general, erorile sunt raportate sub forma unui mesaj.

Întrebări frecvente

Da. Asistenții cu inteligență artificială pot explica fiecare fază, trace. cum se transformă codul exemplu în token-uri și arbori de analiză sintactică și indică unde apare o eroare sintactică sau semantică. Sunt instrumente utile pentru studiu, dar verifică explicațiile în raport cu materialul cursului.

Învățarea automată poate prezice care etape de optimizare produc cel mai rapid cod pentru un anumit program și mașină, ajustând alegerile care odinioară erau euristici elaborate manual. Compilatorul trebuie să garanteze în continuare că programul optimizat se comportă exact ca originalul.

Frontend-ul se ocupă de analiza lexicală, sintactică și semantică, plus codul intermediar și depinde de limbajul sursă. Backend-ul se ocupă de optimizare și generarea de cod și depinde de mașina țintă. Această divizare simplifică retargetarea.

Nu. Analiza lexicală (scanare) grupează caracterele în token-uri, în timp ce parsarea (analiza sintactică) aranjează aceste token-uri într-un arbore de analiză conform regulilor gramaticale. Analiza lexicală rulează mai întâi și transmite token-urile sale către parser.

Rezumați această postare cu: