Was ist ein Compiler-Design? Typen, Bauwerkzeuge, Beispiel

โšก Intelligente Zusammenfassung

Die Phasen des Compilers beschreiben die sechs Stufen, die Quellcode in Maschinencode umwandeln: lexikalische Analyse, Syntaxanalyse, semantische Analyse, Zwischencodegenerierung, Codeoptimierung und Codegenerierung, unterstรผtzt durch Symboltabellenverwaltung und Fehlerbehandlung.

  • ๐Ÿ”ค Lexikalische Analyse: Der Scanner gruppiert Zeichen zu Tokens und speichert diese in der Symboltabelle.
  • ๐ŸŒณ Syntaxanalyse: Der Parser prรผft die Grammatik und erstellt aus den Tokens einen hierarchischen Syntaxbaum.
  • โœ”๏ธ Semantische Analyse: In dieser Phase werden die Typkompatibilitรคt und die Bedeutung mithilfe des Syntaxbaums รผberprรผft.
  • โš™๏ธ Code Generation: Es wird Zwischencode generiert, optimiert und schlieรŸlich in den Zielmaschinencode รผbersetzt.
  • ๐Ÿ“‹ Unterstรผtzungsroutinen: Eine Symboltabelle und eine Fehlerbehandlungsroutine interagieren mit jeder Kompilierungsphase.

Phasen des Compilers mit Beispiel: Kompilierungsprozess und Schritte

Was sind die Phasen des Compiler-Designs?

A Compiler Der Compiler arbeitet in verschiedenen Phasen, wobei jede Phase das Quellprogramm von einer Darstellungsform in eine andere transformiert. Jede Phase verarbeitet die Eingaben der vorherigen Phase und leitet ihre Ausgabe an die nรคchste Phase weiter. Ein Compiler besteht aus sechs Phasen. Jede dieser Phasen trรคgt zur รœbersetzung der Hochsprache in Maschinencode bei. 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

In all diesen Phasen wird der Quellcode umgewandelt, indem er in Tokens unterteilt, Syntaxbรคume erstellt und der Quellcode durch verschiedene Phasen optimiert wird.

Phase 1: Lexikalische Analyse

Die lexikalische Analyse ist die erste Phase, in der der Compiler den Quellcode durchsucht. Dieser Prozess kann von links nach rechts, Zeichen fรผr Zeichen, erfolgen und gruppiert diese Zeichen zu Token.

Hier wird der Zeichenstrom aus dem Quellprogramm durch die Identifizierung der Token in sinnvolle Sequenzen gruppiert. Die entsprechenden Token werden in die Symboltabelle eingetragen und an die nรคchste Phase รผbergeben.

Die Hauptfunktionen dieser Phase sind:

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

Ejemplo: x = y + 10

Token Typ
X Kennzeichnung
= Aufgabenverwalter
Y Kennzeichnung
+ Additionsoperator
10 Nummer

Phase 2: Syntaxanalyse

Bei der Syntaxanalyse geht es darum, die Struktur von Code zu erkennen. Sie ermittelt, ob ein Text dem erwarteten Format entspricht. Hauptziel dieser Phase ist es, sicherzustellen, dass der vom Programmierer geschriebene Quellcode korrekt ist.

Die Syntaxanalyse basiert auf den Regeln der jeweiligen Programmiersprache und erstellt mithilfe von Token einen Syntaxbaum. Sie bestimmt auรŸerdem die Struktur der Quellsprache sowie deren Grammatik bzw. Syntax.

Hier ist eine Liste der in dieser Phase durchgefรผhrten Aufgaben:

  • Tokens vom lexikalischen Analysator abrufen.
  • Prรผfen Sie, ob der Ausdruck syntaktisch korrekt ist oder nicht.
  • Alle Syntaxfehler melden.
  • Erstellen Sie eine hierarchische Struktur, die als Syntaxbaum 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 Syntaxbaum fรผr das folgende Beispiel:

(a+b)*c

Beispiel einer Syntaxanalyse

Im Syntaxbaum:

  • Innerer Knoten: Datensatz mit einem Operatorfeld und zwei Feldern fรผr untergeordnete Elemente.
  • Blatt: Datensรคtze mit 2 oder mehr Feldern; eines fรผr das Token und weitere Informationen รผber das Token.
  • Stellen Sie sicher, dass die Programmkomponenten sinnvoll zusammenpassen.
  • Sammelt Typinformationen und prรผft auf Typkompatibilitรคt.
  • Die Quellsprache erlaubt Prรผfoperanden.

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 prรผft auf Typenkonflikte, inkompatible Operanden, Funktionsaufrufe mit unzulรคssigen Argumenten, nicht deklarierte Variablen usw.

Die Funktionen der semantischen Analysephase sind:

  • Hilft Ihnen dabei, gesammelte Typinformationen zu speichern und in der Symboltabelle oder im Syntaxbaum abzulegen.
  • Ermรถglicht die Durchfรผhrung von Typรผberprรผfungen.
  • Im Falle einer Typenabweichung, bei der es keine exakten Typkorrekturregeln gibt, die die gewรผnschte Operation erfรผllen, wird ein semantischer Fehler angezeigt.
  • Sammelt Typinformationen und prรผft auf Typkompatibilitรคt.
  • Prรผft, ob die Quellsprache die Operanden zulรคsst oder nicht.

Beispiel

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

Im obigen Code wird der semantische Analysator den Integer 30 vor der Multiplikation in float 30.0 umwandeln.

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 bildet die Schnittstelle zwischen der Hochsprache und der Maschinensprache. Dieser Zwischencode muss so generiert werden, dass er sich leicht in den Zielmaschinencode รผbersetzen lรคsst.

Funktionen von Zwischen Code Generation:

  • Sie sollte aus der semantischen Reprรคsentation des Quellprogramms generiert werden.
  • Speichert die wรคhrend des รœbersetzungsprozesses berechneten Werte.
  • Hilft Ihnen dabei, den Zwischencode in die Zielsprache zu รผbersetzen.
  • Ermรถglicht es Ihnen, die Rangfolge der Quellsprache beizubehalten.
  • Es enthรคlt die korrekte Anzahl an Operanden der Anweisung.

Beispiel

Beispielsweise:

total = count + rate * 5

Der Zwischencode, der mithilfe der Adresscodemethode erstellt wurde, 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 des Zwischencodes. Dabei werden unnรถtige Codezeilen entfernt und die Abfolge der Anweisungen so angeordnet, dass die Programmausfรผhrung beschleunigt und gleichzeitig Ressourcen geschont werden. Hauptziel dieser Phase ist die Verbesserung des Zwischencodes, um einen schnelleren und speicherschonenderen Code zu generieren.

Die Hauptfunktionen dieser Phase sind:

  • Es hilft Ihnen, einen Kompromiss zwischen Ausfรผhrungs- und Kompilierungsgeschwindigkeit zu finden.
  • Verbessert die Laufzeit des Zielprogramms.
  • Erzeugt weiterhin in Zwischenreprรคsentation รผbersichtlichen Code.
  • Nicht erreichbaren Code entfernen und ungenutzte Variablen lรถschen.
  • Anweisungen, die nicht verรคndert werden, werden aus der Schleife entfernt.

Ejemplo: Betrachten Sie den folgenden Code:

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

Kann werden zu:

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 der Codeoptimierungsphase 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 Variablen reserviert. Die Anweisungen im Zwischencode werden in Maschinenbefehle umgewandelt. In dieser Phase wird der optimierte oder Zwischencode in die Zielsprache รผbersetzt.

Die Zielsprache ist der Maschinencode. Daher werden in dieser Phase auch alle Speicheradressen und Register ausgewรคhlt und zugewiesen. Der in dieser Phase generierte Code wird ausgefรผhrt, um Eingaben zu verarbeiten und die erwarteten Ausgaben zu erzeugen.

Beispiel

a = b + 60.0 kรถnnte mรถglicherweise wie folgt in Register รผbersetzt werden:

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

Symboltabellenverwaltung

Eine Symboltabelle enthรคlt fรผr jeden Bezeichner einen Eintrag mit Feldern fรผr dessen Attribute. Diese Komponente erleichtert dem Compiler die Suche nach dem Bezeichnereintrag und ermรถglicht dessen schnellen Abruf. Die Symboltabelle unterstรผtzt zudem die Bereichsverwaltung. Symboltabelle und Fehlerbehandlung 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 die richtigen Register nicht zugewiesen sind.
  • Symboltabellen: Fehler: Mehrere Bezeichner wurden deklariert.

Die hรคufigsten Fehler sind ungรผltige Zeichenketten beim Scannen, ungรผltige Token-Sequenzen beim Typisieren, Bereichsfehler und Parsing-Fehler bei der semantischen Analyse.

Der Fehler kann in jeder der oben genannten Phasen auftreten. Nach dem Auffinden eines Fehlers muss die jeweilige Phase diesen behandeln, um den Kompilierungsprozess fortsetzen zu kรถnnen. Diese Fehler mรผssen an die Fehlerbehandlungsroutine gemeldet werden, die den Fehler behandelt, um den Kompilierungsprozess fortzusetzen. In der Regel werden die Fehler in Form einer Fehlermeldung ausgegeben.

Hรคufig gestellte Fragen

Ja. KI-Assistenten kรถnnen jede Phase erklรคren. tracSehen Sie, wie Beispielcode in Tokens und Syntaxbรคume umgewandelt wird und weisen Sie auf Syntax- oder Semantikfehler hin. Sie sind hilfreiche Lernhilfen, aber รผberprรผfen Sie die Erklรคrungen anhand der Kursmaterialien.

Maschinelles Lernen kann vorhersagen, welche Optimierungsschritte den schnellsten Code fรผr ein gegebenes Programm und eine gegebene Maschine erzeugen, und optimiert so Entscheidungen, die zuvor manuell entwickelte Heuristiken waren. Der Compiler muss jedoch weiterhin gewรคhrleisten, dass sich das optimierte Programm exakt wie das Original verhรคlt.

Das Frontend รผbernimmt die lexikalische, syntaktische und semantische Analyse sowie die Generierung von Zwischencode und ist von der Quellsprache abhรคngig. Das Backend optimiert Anwendungen und generiert Code und ist vom Zielsystem abhรคngig. Diese Aufteilung vereinfacht das Retargeting.

Nein. Die lexikalische Analyse (Scanning) gruppiert Zeichen zu Tokens, wรคhrend das Parsen (Syntaxanalyse) diese Tokens gemรครŸ den Grammatikregeln in einem Syntaxbaum anordnet. Die lexikalische Analyse wird zuerst ausgefรผhrt und รผbergibt ihre Tokens an den Parser.

Fassen Sie diesen Beitrag mit folgenden Worten zusammen: