Übersicht über die Schritte des Compilers

Lexer

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:

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.