-
Notifications
You must be signed in to change notification settings - Fork 1
Lexer
Der Lexer ist der erste Teil des Frontends eines Übersetzers und ist für die lexikalische Analyse des Quellcodes zuständig. Er teilt den Quelltext in kleinere Einheiten, sogenannte Token, auf und stellt diese dem Parser zur Verfügung.
Um den Aufbau möglichst transparent zu halten und die Komponenten für den FUC (FU Compiler) austauschbar zu machen, wurden Interfaces als Implementierungsgrundlage genutzt.
Die Methode setSourceStream(InputStream stream) wird genutzt um den zu analysierenden Quelltext an den Lexer zu uebergeben. Ein Token wird mithilfe der Methode getNextToken() zurückgegeben. Bei wiederholten Aufruf der Methode, werden jeweils die nächsten Token des Quelltextes geliefert.
Diese Klasse besteht aus einer Enumeration, welche die verschiedenen Arten von Token beinhaltet. Diese sind zum Großteil durch die Sprache spezifiziert.
Das Interface stellt wichtige Methoden bereit, um Informationen über den Token zu erhalten. Mithilfe von getValue() wird die String-Repräsentation des Wertes des Tokens zurückgegeben, getTokenType() liefert den Typ des Tokens, getLine() liefert die Zeile des Quelltextes, in dem der Token vorkommt und getColumn() liefert die Spalte, in der der Token beginnt.
Die folgenden Interfaces erben von dem Token-Interface und beinhalten zusätzlich noch eine weitere Methode, die nicht nur die String-Repräsentation des Wertes wieder gibt, sondern außerdem den Wert mit dem entsprechenden Datentyp.
Die Methode getLongValue() liefert die Long-Repräsentation des übergebenen Wertes zurück.
Die Methode getDoubleValue() liefert die Double-Repräsentation des übergebenen Wertes zurück.
Die Methode getBooleanValue() liefert die boolesche Repräsentation, true oder false, des übergebenen Wertes zurück.
Nach der Initialisierung des Lexers wird mithilfe der Methode setSourceStream(InputStream stream) ein UTF-8 codierter InputStream übergeben, der den Quelltext beinhaltet. Dieser wird für die weitere Verarbeitung zeilenweise in einer ArrayList gespeichert.
Wenn der Parser einen neuen Token anfragt, ruft dieser die Methode getNextToken() auf, welche einen solchen zurückliefert. Der Parser kann nicht alle Token in einem Aufruf anfragen. Der zuletzt Gelieferte besitzt den Typ EOF und signalisiert, dass der Quelltext vollständig lexikalisch analysiert wurde.
Die Klassifizierung des Tokens wird anhand des Tokentyps festgelegt. Der Typ NUM steht für einen ganzzahligen numerischen Wert und wird als NumToken zurückgegeben wird. REAL wird für Fließkommazahlen genutzt und bekommt die Klasse RealToken zugeordnet. BoolToken dient für alle boolschen Werte, d.h. true oder false. Alle restlichen Typen werden keiner speziellen Klasse zugeordnet, sie werden mit der Objekt Token zurückgeliefert.
Das Analysieren der einzelnen Werte übernimmt die Methode abstractToken(). Sie berechnet außerdem, die Zeile und Spalte des nächsten Token. In der aktuellen Zeile wird der Tokenwert anhand des nächsten Trennzeichens definiert. Als Trennzeichen gelten Klammern, Operatoren und Leerzeichen.
Während der Analyse können mehrere Ausnahmen auftreten, bei:
- Strings; diese beginnen und Enden mit Hochkomma, wobei das Maskieren von Zeichen mithilfe von "" möglich ist,
- Kommentaren; diese beginnen mit einer Raute und gelten für den Rest der Zeile.
Nachdem der Wert des Tokens bestimmt wurde, wird dieser mithilfe der Methode matchToken() einem Typen zugeordnet. Diese Zuordnung geschieht durch den Einsatz von regulären Ausdrücken (siehe Terminal-Definition).
Sofern alle Token von einer Zeile analysiert wurden, liest der Lexer die nächste Zeile ein und beginnt diese zu überprüfen, bis der Quelltext vollständig analysiert wurde.