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.
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:
- Lexikalische Analyse
- Syntaxanalyse
- Semantische Analyse
- Zwischencodegenerator
- Code Optimierer
- Code Generator
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
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.



