Phasen des Compilers mit Beispiel, Prozess und Schritten

โšก Intelligente Zusammenfassung

Die Phasen des Compilers beschreiben, wie ein Compiler Quellcode in Maschinencode umwandelt. Dies geschieht in sechs Schritten: lexikalische Analyse, Syntaxanalyse, semantische Analyse, Zwischencodegenerierung, Codeoptimierung und Codegenerierung, unterstรผtzt durch Symboltabellenverwaltung und Fehlerbehandlung.

  • ๐Ÿ”ค Lexikalische Analyse: In der ersten Phase wird der Quellcode gescannt und die Zeichen werden zu Token gruppiert, wodurch die Symboltabelle gefรผllt wird.
  • ๐ŸŒณ Syntaxanalyse: Tokens werden anhand von Grammatikregeln geprรผft und in einem Syntaxbaum angeordnet.
  • โœ… Semantische Analyse: Der Compiler รผberprรผft die Typkompatibilitรคt und -bedeutung mithilfe des Syntaxbaums und der Symboltabelle.
  • ๐Ÿ” Fortgeschrittener Code: Zur einfachen รœbersetzung wird eine maschinenunabhรคngige Darstellung, wie beispielsweise ein Drei-Adressen-Code, generiert.
  • โšก Optimierung: Redundanter und unerreichbarer Code wird entfernt, um das Programm schneller und kleiner zu machen.
  • ๏ธ Code Generation: In der letzten Phase wird der optimierte Code in den Zielmaschinencode umgewandelt, wobei Register und Speicher zugewiesen werden.

Was sind die Phasen des Compiler-Designs?

Compiler arbeitet in verschiedenen Phasen. Jede Phase transformiert das Quellprogramm von einer Darstellung in eine andere. Jede Phase รผbernimmt Eingaben aus der vorherigen Phase und gibt ihre Ausgabe an die nรคchste Phase des Compilers weiter.
Es gibt 6 Phasen in einem Compiler. Jede dieser Phasen hilft bei der Konvertierung der Hochsprache in den Maschinencode. Die Phasen eines Compilers sind:

  1. Lexikalische Analyse
  2. Syntaxanalyse
  3. Semantische Analyse
  4. Zwischencodegenerator
  5. Code Optimierer
  6. Code Generator
Phasen des Compilers
Phasen des Compilers

Alle diese Phasen konvertieren den Quellcode, indem sie ihn in Token aufteilen, Parse-Bรคume erstellen und den Quellcode in verschiedenen Phasen optimieren.

Phase 1: Lexikalische Analyse

Die lexikalische Analyse ist die erste Phase, in der der Compiler den Quellcode scannt. Dieser Vorgang kann Zeichen fรผr Zeichen von links nach rechts erfolgen und diese Zeichen in Token gruppieren.
Hierbei wird der Zeichenstrom aus dem Quellprogramm durch die Identifizierung der Token in sinnvolle Sequenzen gruppiert. Es fรผhrt den Eintrag der entsprechenden Tickets in die Symboltabelle durch und รผbergibt diesen Token an die nรคchste Phase.
Die Hauptfunktionen dieser Phase sind:

  • Identifizieren Sie die lexikalischen Einheiten in einem Quellcode
  • Klassifizieren Sie lexikalische Einheiten in Klassen wie Konstanten und reservierte Wรถrter und geben Sie sie in verschiedene Tabellen ein. Kommentare im Quellprogramm werden ignoriert
  • Identifizieren Sie ein Token, das nicht Teil der Sprache ist

Beispiel:
x = y + 10

Tokens

X Kennzeichnung
= Aufgabenverwalter
Y Kennzeichnung
+ Additionsoperator
10 Nummer

Phase 2: Syntaxanalyse

Bei der Syntaxanalyse geht es darum, die Struktur im Code zu entdecken. Es bestimmt, ob ein Text dem erwarteten Format folgt oder nicht. Das Hauptziel dieser Phase besteht darin, sicherzustellen, dass der vom Programmierer geschriebene Quellcode korrekt ist oder nicht.
Die Syntaxanalyse basiert auf den Regeln, die auf der spezifischen Programmiersprache basieren, indem der Analysebaum mithilfe von Token erstellt wird. Es bestimmt auch die Struktur der Ausgangssprache und die Grammatik oder Syntax der Sprache.
Hier ist eine Liste der in dieser Phase ausgefรผhrten Aufgaben:

  • Erhalten Sie Token vom lexikalischen Analysator
  • รœberprรผft, ob der Ausdruck syntaktisch korrekt ist oder nicht
  • Melden Sie alle Syntaxfehler
  • Konstruieren Sie eine hierarchische Struktur, die als Parse-Baum bezeichnet wird.

Beispiel

Jeder Bezeichner/jede Zahl ist ein Ausdruck
Wenn x ein Bezeichner und y+10 ein Ausdruck ist, dann ist x= y+10 eine Anweisung.
Betrachten Sie den Parse-Baum fรผr das folgende Beispiel

(a+b)*c

Beispiel einer Syntaxanalyse

Im Analysebaum

  • Innerer Knoten: Datensatz mit einem Operatorfeld und zwei Dateien fรผr untergeordnete Elemente
  • Blatt: Datensรคtze mit 2/mehr Feldern; eine fรผr Token und andere Informationen รผber den Token
  • Stellen Sie sicher, dass die Programmbestandteile sinnvoll zusammenpassen
  • Sammelt Typinformationen und prรผft die Typkompatibilitรคt
  • รœberprรผft, ob Operanden in der Quellsprache zulรคssig sind

Phase 3: Semantische Analyse

Die semantische Analyse รผberprรผft die semantische Konsistenz des Codes. Es verwendet den Syntaxbaum der vorherigen Phase zusammen mit der Symboltabelle, um zu รผberprรผfen, ob der angegebene Quellcode semantisch konsistent ist. AuรŸerdem wird geprรผft, ob der Code eine angemessene Bedeutung vermittelt.
Der semantische Analysator sucht nach Typkonflikten, inkompatiblen Operanden, einer mit falschen Argumenten aufgerufenen Funktion, einer nicht deklarierten Variable usw.
Die Funktionen der Phase der semantischen Analyse sind:

  • Hilft Ihnen, gesammelte Typinformationen zu speichern und in einer Symboltabelle oder einem Syntaxbaum zu speichern
  • Ermรถglicht die Durchfรผhrung einer Typprรผfung
  • Im Falle einer Typ-Nichtรผbereinstimmung, bei der es keine genauen Typ-Korrekturregeln gibt, die die gewรผnschte Operation erfรผllen, wird ein semantischer Fehler angezeigt
  • Sammelt Typinformationen und prรผft die Typkompatibilitรคt
  • รœberprรผft, ob die Quellsprache die Operanden zulรคsst oder nicht

Beispiel

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

Im obigen Code wandelt der Semantikanalysator die Ganzzahl 30 vor der Multiplikation in Float 30.0 um

Phase 4: Mittelstufe Code Generation

Sobald die semantische Analysephase abgeschlossen ist, generiert der Compiler Zwischencode fรผr die Zielmaschine. Dieser reprรคsentiert ein Programm fรผr eine bestimmte Zielgruppe.tract-Maschine.
Der Zwischencode liegt zwischen der Hochsprache und der Maschinensprache. Dieser Zwischencode muss so generiert werden, dass er leicht in den Zielmaschinencode รผbersetzt werden kann.
Funktionen auf Zwischenebene Code Generation:

  • Es sollte aus der semantischen Darstellung des Quellprogramms generiert werden
  • Enthรคlt die wรคhrend des รœbersetzungsprozesses berechneten Werte
  • Hilft Ihnen, den Zwischencode in die Zielsprache zu รผbersetzen
  • Ermรถglicht Ihnen, die Rangfolge der Ausgangssprache beizubehalten
  • Es enthรคlt die richtige Anzahl von Operanden der Anweisung

Beispiel

Zum Beispiel,

total = count + rate * 5

Der Zwischencode mit Hilfe der Adresscode-Methode lautet:

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

Phase 5: Code Optimierung

Die nรคchste Phase ist die Codeoptimierung oder der Zwischencode. In dieser Phase werden unnรถtige Codezeilen entfernt und die Anweisungsfolge so angeordnet, dass die Ausfรผhrung des Programms beschleunigt wird, ohne Ressourcen zu verschwenden. Das Hauptziel dieser Phase besteht darin, den Zwischencode zu verbessern, um einen Code zu generieren, der schneller ausgefรผhrt wird und weniger Platz einnimmt.
Die Hauptfunktionen dieser Phase sind:

  • Es hilft Ihnen, einen Kompromiss zwischen Ausfรผhrungs- und Kompilierungsgeschwindigkeit zu finden
  • Verbessert die Laufzeit des Zielprogramms
  • Erzeugt optimierten Code noch in Zwischendarstellung
  • Entfernen von nicht erreichbarem Code und Entfernen nicht verwendeter Variablen
  • Entfernen von Anweisungen, die nicht geรคndert werden, aus der Schleife

Ejemplo:
Betrachten Sie den folgenden Code

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

Kann werden

b =c * 10.0
f = e+b

Phase 6: Code Generation

Code Die Generierung ist die letzte Phase eines Compilers. Sie erhรคlt Eingaben aus den Codeoptimierungsphasen und erzeugt als Ergebnis den Seitencode oder Objektcode. Ziel dieser Phase ist die Speicherzuweisung und die Generierung von verschiebbarem Maschinencode.
AuรŸerdem werden Speicherplรคtze fรผr die Variable zugewiesen. Die Anweisungen im Zwischencode werden in Maschinenanweisungen umgewandelt. In dieser Phase wird der Optimierungs- oder Zwischencode in die Zielsprache umgewandelt.
Die Zielsprache ist der Maschinencode. Daher werden in dieser Phase auch alle Speicherplรคtze und Register ausgewรคhlt und zugewiesen. Der in dieser Phase generierte Code wird ausgefรผhrt, um Eingaben entgegenzunehmen und erwartete Ausgaben zu generieren.

Beispiel

a = b + 60.0
Wรผrde mรถglicherweise in Register รผbersetzt.

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

Symboltabellenverwaltung

Eine Symboltabelle enthรคlt fรผr jeden Bezeichner einen Datensatz mit Feldern fรผr die Attribute des Bezeichners. Diese Komponente erleichtert es dem Compiler, den Bezeichnerdatensatz zu durchsuchen und ihn schnell abzurufen. Die Symboltabelle hilft Ihnen auch bei der Scope-Verwaltung. Die Symboltabelle und der Fehlerhandler interagieren mit allen Phasen und die Symboltabelle wird entsprechend aktualisiert.

Fehlerbehandlungsroutine

Im Compiler-Designprozess kรถnnen in allen unten aufgefรผhrten Phasen Fehler auftreten:

  • Lexikalischer Analysator: Falsch geschriebene Token
  • Syntaxanalysator: Fehlende Klammer
  • Zwischencodegenerator: Nicht รผbereinstimmende Operanden fรผr einen Operator
  • Code Optimierer: Wenn die Anweisung nicht erreichbar ist
  • Code Generator: Wenn der Speicher voll ist oder nicht die richtigen Register zugewiesen sind
  • Symboltabellen: Fehler bei mehreren deklarierten Bezeichnern

Die hรคufigsten Fehler sind ungรผltige Zeichenfolgen beim Scannen, ungรผltige Tokensequenzen beim Typ, Bereichsfehler und Parsing bei der semantischen Analyse.
Der Fehler kann in jeder der oben genannten Phasen auftreten. Nachdem Fehler gefunden wurden, muss sich die Phase mit den Fehlern befassen, um mit dem Kompilierungsprozess fortzufahren. Diese Fehler mรผssen dem Fehlerhandler gemeldet werden, der den Fehler behandelt, um den Kompilierungsprozess durchzufรผhren. Im Allgemeinen werden die Fehler in Form einer Nachricht gemeldet.

Hรคufig gestellte Fragen

Die Analysephase (Frontend) zerlegt den Quellcode durch lexikalische, syntaktische und semantische Analyse. Die Synthesephase (Backend) erstellt das Zielprogramm durch Zwischencodegenerierung, Optimierung und erneute Codegenerierung.

Ein Compiler รผbersetzt das gesamte Quellprogramm in Maschinencode, bevor es ausgefรผhrt wird. Ein Interpreter รผbersetzt und fรผhrt den Code Zeile fรผr Zeile aus, was die Fehlersuche erleichtert, aber zur Laufzeit in der Regel langsamer ist.

Der Drei-Adress-Code ist eine Zwischenreprรคsentation, bei der jede Anweisung hรถchstens drei Operanden hat, z. B. t1 = a + b. Er ist einfach zu optimieren und leicht in Zielmaschinencode zu รผbersetzen.

Kรผnstliche Intelligenz und maschinelles Lernen unterstรผtzen moderne Compiler bei intelligenteren Optimierungsentscheidungen, beispielsweise bei der Auswahl von Schleifentransformationen, Inlining und Registerzuweisung. Sie prognostizieren, welche Optimierungen die Leistung eines bestimmten Programms und Zielsystems verbessern.

Ja. Die KI kann jede Phase anhand von Beispielen erklรคren. tracErklรคren Sie, wie eine Beispielanweisung von Tokens in Maschinencode umgewandelt wird, und beantworten Sie anschlieรŸende Fragen. Dies erleichtert Studierenden das Erlernen des Compilerbaus.

Fassen Sie diesen Beitrag mit folgenden Worten zusammen: