Der Lexer liest den Programmtext Zeichen für Zeichen und fasst diese zu kleinsten syntaktischen Einheiten, sogenannten Tokens, zusammen. Unsere Beispielsprache besteht aus folgenden 8 Tokens:
1,278
Die Tokens können im Programmtext unmittelbar hintereinander stehen, sie können aber auch durch Leerzeichen oder Zeilenumbrüche ('whitespace') voneinander getrennt sein. Whitespace wird vom Lexer einfach überlesen.
Den Programmtext
1 + 2 * (4 * a1 - 3)
zerlegt der Lexer also in folgende 11 Tokens:
zahl[1.0] plus zahl[2.0] mal klammerAuf zahl[4.0] mal text[a1] minus zahl[3.0] klammerZ
Damit der Parser die Tokens nachher weiterverarbeiten kann, muss zu jedem Token sein Typ (Zahl, plus, text, …) sowie - im Falle von Zahlen und Variablen - auch die konkrete Zahl bzw. die konkrete Variable gespeichert werden. Ein Token wird daher als Objekt der Klasse Token
abgebildet:
package lexer; public class Token { private TokenType tokenType; // Art des Tokens (z.B. zahl, klammerAuf usw.) private double zahl; // Wird nur belegt, wenn tokenType == zahl private String text; // Wird nur belegt, falls tokenType == bezeichner public Token(double zahl){ this.zahl = zahl; tokenType = TokenType.zahl; } public Token(String text){ this.text = text; tokenType = TokenType.variable; } public Token(TokenType tokenType){ this.tokenType = tokenType; } public TokenType getTokenType() { return tokenType; } public double getZahl() { return zahl; } public String getText() { return text; } /** * Die toString()-Methode dient nur Debuggingzwecken */ @Override public String toString() { String s = "" + tokenType; switch (tokenType) { case zahl: s += "[" + zahl + "]"; break; case variable: s += "[" + text + "]"; break; default: break; } return s; } }
Die Klasse TokenType ist einfach eine Enum-Klasse mit den möglichen Typen:
public enum TokenType { zahl, text, plus, minus, mal, geteilt, klammerAuf, klammerZu, /** * Nur als Knotentyp für Knoten des Syntaxbaums: */ negation }
Da wir die TokenTypen der Einfachheit halber auch als Typen der Knoten des vom Parser generierten Syntaxbaums verwenden, gibt es einen zusätzlichen Typ negation
. Dazu später mehr.