Home > Informatik > Formale Sprachen > Folge 22: Codebuffer

22.1 Ein primitiver Codebuffer

22.1 - 22.2 - 22.3

Stackcode speichern

Wir wollen uns nun näher mit der Klasse Codebuffer beschäftigen. Hier noch einmal das zweite Entwurfsdiagramm für das gesamte Projekt des Interpreters.

Das konkretere Entwurfsdiagramm

Die Endversion der Klasse Codebuffer soll den Steuercode der Stackmaschine aus einer Textdatei auslesen und an den Interpreter weitergeben. So weit sind wir allerdings noch nicht. In diesem Abschnitt wollen wir zunächst einen einfachen Codebuffer schreiben, der den Stackcode in einem Array speichert.

In dieser ersten Version soll der Codebuffer einen String-Array zur Verfügung stellen. In jedem Element des String-Arrays steht genau eine Zeile des Stackcodes. Das Auffüllen des Arrays übernimmt dabei eine Methode fill der Klasse Codebuffer:

public class Codebuffer
{
    String[] buffer;
    int max;            // Anzahl der Befehle
    int PC;             // Program counter
    
    public Codebuffer()
    {
       buffer = new String[100];
       max = 0;
       PC  = 0;
    }
    
    public void fill()
    {
       buffer[ 0] = "PUSH 12";
       buffer[ 1] = "PUSH 8";
       buffer[ 2] = "PUSH 3";
       buffer[ 3] = "ADD";
       buffer[ 4] = "ADD";
       buffer[ 5] = "PUSH 4";
       buffer[ 6] = "PUSH 2";
       buffer[ 7] = "MUL";
       buffer[ 8] = "MUL";
       buffer[ 9] = "PUSH 2.7890";
       buffer[10] = "ADD";
       buffer[11] = "PUSH 3";
       buffer[12] = "DIV";
       max = 13;
    }
    				

Hier der Anfang des Quelltextes eines solchen einfachen Codebuffers. Das Attribut buffer ist der eigentliche Speicher, die Attribute max und PC verwalten die Anzahl der Zeilen des Buffers - hier 13 - und den aktuellen Stand des Programmzählers - am Anfang also 0.

In der Methode fill wird der Codebuffer dann mit Stackcode gefüllt. Für die Funktion des Stackinterpreters ist es sehr wichtig, dass zwischen dem eigentlichen Befehl, zum Beispiel "PUSH" und dem Argument, beispielsweise "12", genau ein Leerzeichen steht. Diese strenge Vorgabe erleichtert später das "Auseinanderpflücken" von Befehl und Argument.

In dieser ersten Version des Codebuffers schreiben wir den Stackcode direkt in den Array. Später werden wir die Methode fill durch eine Methode read ersetzen, welche den Stackcode aus einer Textdatei einliest. Vorher müssen wir uns aber noch mit Textdateien näher beschäftigen.

Argumente zurückgeben

getNextCmd()

Schauen wir uns den ersten Stackbefehl an, der im Codebuffer gespeichert ist: PUSH 12.

Die sondierende Methode getNextCmd des Codebuffers muss jetzt einen eindeutigen Rückgabewert liefern. Im einfachsten Fall ist das der String "PUSH". Man könnte das Ganze aber auch so implementieren, dass eine Befehlsnummer zurückgeliefert wird, für den Push-Befehl zum Beispiel die Zahl 1, für den Add-Befehl die Zahl 2 und so weiter.

Hierbei erweist sich die Methode startsWith der Klasse String als sehr hilfreich:

if (buffer[PC].startsWith("PUSH"))
   return 1;
getNextArt()

Bei den Kommandos Add, Sub, Mul und Div wird kein Argument benötigt, beim Push-Befehl aber muss eine Zahl zurückgeliefert werden. Auch hier könnte man wieder darüber diskutieren, ob diese Zahl als "richtige" double-Zahl oder einfach als String zurückgeliefert werden soll. Die folgenden Quelltextzeilen zeigen Ihnen, wie man aus dem Push-Befehl zunächst das Argument isoliert und dann in eine double-Zahl konvertiert:

   ...
   if (buffer[PC].startsWith("PUSH"))
   {
      temp = buffer[PC].substring(5);  
      numArg = new Double(temp);
   }
   ...

Es wurde ja bereits gesagt, dass sich zwischen dem Befehl wie "PUSH" und dem Argument genau ein Leerzeichen befinden muss. Das Zahl-Argument des PUSH-Befehls beginnt also an der Position 5 des Strings.

Program counter

Sobald der aktuelle Befehl des Codebuffers abgearbeitet wurde, wenn also sowohl das Kommando wie auch das eventuelle Argument isoliert worden sind, muss der Programmzähler inkrementiert werden, damit beim nächsten Aufruf von getNextCmd und getNextArg die nächste Zeile des Codebuffers "zerlegt" wird.

Weiter mit 22.2 Testen des Codebuffers...