Parser und Übersetzer

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 

Bild 1: Klassenhierarchie von Parsern und Compilern

 

Klasse ParserFunctions

In der Klasse ParserFunctions befinden sich die globalen Variablen inputstring, errormessage und errorposition sowie grundlegende Funktionen zur Abarbeitung des Eingabe­wortes.

 

/** Grundlegende Funktionen für Parser und Compiler
 */

public abstract class ParserFunctions
{
    protected String inputstring;
    public String errormessage;
    public int errorposition;

    // liefert true, wenn das Eingabewort mit String x beginnt
    protected boolean comes(String x)
    {
        return inputstring.startsWith(x);
    }

    // liefert true, wenn das Eingabewort mit einer Ziffer beginnt
    protected boolean comesDigit()
    {
        return comes("0") || comes("1") || comes("2") || comes("3") || comes("4") ||
            comes("5") || comes("6") || comes("7") || comes("8") || comes("9");
    }

    // wenn das Eingabewort mit String x beginnt, wird
    // der String x am Anfang des Eingabewortes entfernt;
    // anderenfalls wird eine Exception ausgelöst
    protected void match(String x)
    {
        if (comes(x))
            inputstring=inputstring.substring(x.length());
        else
            throw new RuntimeException("Erwartet: "+x);
    }

    // zeigt die Position eines Syntaxfehlers an
    public String errorPointer()
    {
        return fill("-", errorposition)+"^";
    }

    // liefert den String x hoch k
    private String fill(String x, int k)
    {
        String s="";
        for (int i=0; i<k; i++)
            s+=x;
        return s;
    }

}    // end class ParserFunctions

 

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.

Klasse Parser

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 Eingabe­wortes aufgrund von Syntax­fehlern möglicher­weise ausgelöst werden.

 

/** Basisklasse für einen Parser
 */

public abstract class Parser extends ParserFunctions
{

    // Aufruf des Startsymbols; muss in der abgeleiteten
    // Klasse implementiert werden
    protected abstract void startSymbol();

    // übernimmt einen Eingabestring und ruft das Startsymbol
    // der Grammatik auf; erzeugt ggf. Fehlermeldung und
    // Position des Fehlers im Eingabestring
    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();
    }

}    // end class Parser

Compiler

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.

 

/** Basisklasse für einen Compiler
 */

public abstract class Compiler<Typeextends ParserFunctions
{

    // Aufruf des Startsymbols; muss in der abgeleiteten
    // Klasse implementiert werden
    protected abstract Type startSymbol();

    // übernimmt einen Eingabestring und ruft das Startsymbol
    // der Grammatik auf; erzeugt ggf. Fehlermeldung und
    // Position des Fehlers im Eingabestring
    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;
    }

}    // end class Compiler

 

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