Basisklassen ParserFunctions, Parser, Compiler
Die abstrakte Klasse Parser dient als Basisklasse für einen konkreten Recursive-Descent-Parser. Sie greift ihrerseits zurück auf eine abstrakte Klasse ParserFunctions zurück. Wenn es später nicht nur um das Parsen geht, sondern über die reine Syntaxprüfung hinaus um das Übersetzen, kommt als Basisklasse für konkrete Übersetzer noch die abstrakte Klasse Compiler hinzu (Bild 1).
Bild 1: Klassenhierarchie von Parsern und Compilern
In der Klasse ParserFunctions befinden sich die globalen Variablen inputstring, errormessage und errorposition sowie grundlegende Funktionen zur Abarbeitung des Eingabewortes.
public abstract class ParserFunctions
{
protected String inputstring;
public String errormessage;
public int errorposition;
protected boolean comes(String x)
{
return inputstring.startsWith(x);
}
protected boolean comesDigit()
{
return comes("0") || comes("1") || comes("2") || comes("3") || comes("4") ||
comes("5") || comes("6") || comes("7") || comes("8") || comes("9");
}
protected void match(String x)
{
if (comes(x))
inputstring=inputstring.substring(x.length());
else
throw new RuntimeException("Erwartet: "+x);
}
public String errorPointer()
{
return fill("-", errorposition)+"^";
}
private String fill(String x, int k)
{
String s="";
for (int i=0; i<k; i++)
s+=x;
return s;
}
}
Dies ist nur eine minimale Sammlung von Funktionen, die für das Parsen benötigt werden. Bei Bedarf lassen sich in dieser Klasse weitere nützliche Funktionen unterbingen, zum Beispiel eine Funktion ignoreBlanks, die Leerzeichen abarbeitet, oder eine Funktion getSymbol, die ein Zeichen abarbeitet und zurückgibt.
In der Klasse Parser befindet sich die public-Methode parse(String x). Diese übernimmt das Eingabewort x, weist es der globalen Variablen inputstring zu und ruft die Methode startSymbol() auf. Die Methode startSymbol() ist abstrakt; sie muss in dem jeweiligen konkreten Parser, der von der abstrakten Klasse Parser abgeleitet wird, implementiert werden. Darüber hinaus fängt die Methode parse jegliche Fehler auf, die beim Parsen des Eingabewortes aufgrund von Syntaxfehlern möglicherweise ausgelöst werden.
public abstract class Parser extends ParserFunctions
{
protected abstract void startSymbol();
public void parse(String x)
{
inputstring=x;
errormessage="ok";
try
{
startSymbol();
if (inputstring.length()>0)
throw new RuntimeException("Zuviele Zeichen: "+inputstring);
}
catch (RuntimeException e)
{
errormessage=e.getMessage();
}
errorposition=x.length()-inputstring.length();
}
}
Die Klasse Compiler ist genauso aufgebaut wie die Klasse Parser. Der Unterschied besteht darin, dass der Aufruf des Startsymbols jetzt einen Wert vom Typ Type zurückliefert. Dieser Wert stellt das Ergebnis der Übersetzung dar.
public abstract class Compiler<Type> extends ParserFunctions
{
protected abstract Type startSymbol();
public Type compile(String x)
{
inputstring=x;
Type result=null;
errormessage="ok";
try
{
result=startSymbol();
if (inputstring.length()>0)
throw new RuntimeException("Zuviele Zeichen: "+inputstring);
}
catch (RuntimeException e)
{
errormessage=e.getMessage();
}
errorposition=x.length()-inputstring.length();
return result;
}
}
Weiter mit:
[up]
H.W. Lang mail@hwlang.de Impressum Datenschutz
Created: 06.11.2009 Updated: 17.02.2023
Diese Webseiten sind während meiner Lehrtätigkeit an der Hochschule Flensburg entstanden