Der BASIC-BASIC Interpreter

Wer in der Programmiersprache BASIC programmiert, der verwendet
zumeist den mit dem Rechner mitgelieferten BASIC Interpreter. Dieser
Interpreter ist ein in der Maschinensprache des Rechners abgefates
Programm, das entweder in einem ROM oder in einer Datei auf der
Diskette untergebracht ist. Sein Inneres ist fr den Anwender nicht
zugnglich. Er kann den Interpreter nicht modifizieren und er hat
keinen Einblick in seine Arbeitsweise. Viele mchten aber Ihren BASIC-
Interpreter gerne um eigene Befehle erweitern oder einfach verstehen,
was mit den eingetippten BASIC Pogrammen passiert. Der hier
beschriebene BASIC-BASIC Interpreter, der ausnahmsweise nicht in einer
Maschinensprache sondern in BASIC selbst geschrieben ist, kann da
vielleicht weiterhelfen. Er ist relativ langsam und verfgt ber recht
wenig Befehle, doch Sie knnen mit ihm nachvollziehen, wie Ihr BASIC
Interpreter arbeitet und Sie knnen eigene Befehle hinzufgen.

---------------------------------------------------------------------

Ein BASIC Interpreter ist zumeist Teil eines dialogorientierten BASIC
Systems. Es enthlt neben dem Interpreter einen einfachen Editor und
eine rudimentre Dateiverwaltung. Die meisten BASIC Systeme arbeiten
kommandozeilenorientiert. Nach der Ausgabe eines Prompts wird die
Eingabe eines Kommandos durch den Benutzer abgewartet. Das Kommando
wird vom Rechner sofort analysiert und bearbeitet, bevor der Benutzer
aufgefordert wird, ein weiteres Kommando einzugeben.

Der Editor des BASIC Systems dient zum Erstellen oder Bearbeiten des
aktuellen, im Hauptspeicher des Rechners untergebrachten BASIC
Programmtextes. Er erlaubt das Eingeben neuer, das Korrigieren und das
Entfernen vorhandener Zeilen dieses Programmtexts. Der Editor wird
angesprochen, wenn die Eingabe des Benutzers mit einer Zeilennummer
beginnt. Insofern ist die Zeilennummer als ein Kommando zu verstehen.

Die Dateiverwaltung des Interpretersystems erlaubt zumindest das Laden
(LOAD) und Abspeichern (SAVE) von BASIC Programmtexten, das Anzeigen
der Dateinamen, unter denen Programme gespeichert sind (FILES, DIR)
und das Lschen von Dateien (KILL). Sie ermglicht dem Programmierer
Zugriff auf das Diskettenlaufwerk oder einen anderen
Hintergrundspeicher.

Der Interpreter erweckt den aktuellen Programmtext zum Leben, wenn er
durch Eingabe des Kommandos RUN gestartet wird. Er geht den
Programmtext der Reihe nach durch, analysiert die in jeder Zeile
enthaltenen Anweisungen und fhrt sie aus. Whrend der Zeit, in der
das BASIC-Programm luft, wird das Verhalten des Rechners von den
Anweisungen dieses Programms bestimmt.

Das Prinzip

Wie schreibt man nun einen solchen Interpreter ? Am Anfang steht eine
Liste der gewnschten Kommandos, Anweisungen, Operatoren, Vergleichen
und Variablen, die der Interpreter verstehen soll. Manche Kommandos
verlangen Parameter (so bentigt SAVE einen Dateinamen), bei den
Anweisungen sind unterschiedliche zustzliche Angaben erforderlich. In
Syntaxdiagrammen wird genau festgelegt, wie die Kommandos und
Anweisungen aufgebaut sein drfen. Die Grundlage fr diese Diagramme
bilden die in abgerundeten Kstchen dargestellten Symbole. Hier gibt
es verschiedene Wrter, Namen, ganze Zahlen, Zahlen mit
Nachkommastellen und Exponenten, Zeichenketten und Sonderzeichen. Es
wird vorausgesetzt, da bekannt ist, aus welchen Zeichen (Buchstaben
etc.) solche Elemente aufgebaut sein drfen. Um die Syntaxdiagramme
nicht zu umfangreich werden zu lassen, sind gleiche Abschnitte in
eigenen Diagrammen zusammengefasst worden. An ihrer Stelle stehen
jetzt die eckigen Kstchen in den Syntaxdiagrammen. Fr jedes gltige
Kommando, bzw. jede gltige Anweisungen gibt es einen Weg durch das
Syntaxdiagramm. Man braucht nur den einzelnen Worten auf der Zeile im
Syntaxdiagramm zu folgen. Erreicht man dabei ein eckiges Kstchen, so
ist der Weg in dem anderen Diagramm fortzusetzen und nachher wieder
hinter dem Kstchen fortzufahren. Gelangt man in eine Sackgasse, so
ist die Eingabe fehlerhaft.

Um das nchste Wort W$ aus einer Zeile zu bekommen, verwendet der
beschriebene Interpreter ein Unterprogramm. Es entnimmt aus der
aktuellen Zeile K$ das nchste Symbol. Dazu merkt sich der Interpreter
in der Variablen I% wie weit die aktuelle Zeile bereits zerlegt worden
ist. Das Unterprogramm entnimmt von dort das nchste einzelne Zeichen
aus der Zeile. Leerzeichen werden bergangen. Wenn als nchstes ein
Buchstabe erscheint, so werden alle folgenden Buchstaben und Ziffern
eingesammelt um einen Namen zu erhalten. Wenn es sich um eine Ziffer
handelte, werden alle folgenden Ziffern entnommen um eine Zahl zu
erhalten. Wenn es ein Gnsefchen war, werden alle folgenden Zeichen
bis zum nchsten Gnsefchen entnommen um eine Zeichenkette zu
erhalten. Ansonsten handelt es sich um ein Sonderzeichen, eventuell
auch eine Sonderzeichenkombination. Eine erweiterte Form desselben
Unterprogramms akzeptiert anstelle von ganzen Zahlen auch Zahlen mit
Nachkommastellen und Exponenten.

Die weiteren Programmteile sttzen sich auf diese Unterprogramme, in
dem sie das jeweils nchste Symbol aus der aktuellen Zeile entnehmen
lassen und auf Korrektheit berprfen. Ist es korrekt, dann wird ein
Weg im Programm eingeschlagen, der zum Durchfhren der verlangten
Operation fhrt. Die mglichen Wege sind durch die Syntaxdiagramme
genau festgelegt. Gibt es fr das nchste Wort nach den
Syntaxdiagrammen keinen Weg, so wird die Analyse abgebrochen und eine
Fehlermeldung ausgegeben. Das Prinzip ist bei der Analyse von
Kommandos und Anweisungen dasselbe.

Die Variablen

Im BASIC-BASIC Interpreter werden vier indizierte Variablen (Felder)
bentigt. Zum einen mu er sich alle zum aktuellen Programmtext
gehrenden Programmtextzeilen merken knnen. Sie werden im Feld P$(),
bestehend aus 100 Zeichenkettenvariablen (Strings), sortiert nach der
Reihenfolge der Zeilennummern aufbewahrt. In P$(1) wird also die
Programmtextzeile mit der kleinsten Zeilennummer abgelegt, in P$(2)
die mit der nchstgreren Zeilennummer und (da wir uns die Anzahl der
eingegebenen Programmtextzeilen in der Variablen A% merken) in P$(A%)
die mit der hchsten Zeilennummer.

Weiter bentigt der Interpreter Speicherpltze fr die Namen und Werte
der im BASIC-BASIC Programm auftauchenden Variablen. Dafr dienen die
jeweils 50 Eintrge umfassenden Felder B$() und V(). Das Feld B$()
enthlt die Namen der bekannten Variablen. In B$(1) befindet sich der
Name der 1. bekannten Variablen, in B$(2) der der 2. bekannten
Variablen und, da wir uns die Anzahl der bekannten Variablen in G%
merken, in B$(G%) der Name der letzten bekannten Variablen.
Im Feld V() legen wir die dazugehrigen Variablenwerte ab, und zwar so,
da sich in V(1) der Wert der Variablen befindet, deren Name in B$(1)
gespeichert ist und in V(G%) der Wert der Variablen, deren Name sich in
B$(G%) befindet.
Wenn uns im Verlaufe der Interpretierung des BASIC-BASIC Programms ein
noch unbekannter Variablenname begegnet, so fgen wir ihn einfach zur
Liste der bekannten Variablen hinzu, wobei wir den Wert der Variablen
auf 0 setzen.

Zuguterletzt mssen beim Ausrechnen einer Rechenformel alle
Zwischenergebnisse aufbewahrt werden. In der Variablen S() kann sich
das Programm bis zu 10 Zwischenergebnisse merken. Wieviele davon dann
jedesmal tatschlich benutzt werden, ist durch den Wert von T%
angegeben. S(T%) enthlt das derzeitige Zwischenergebnis, S(1)
hinterher das Gesamtergebnis.

Bedenken Sie Bitte: Diese Variablen werden von BASIC-BASIC Interpreter
bentigt und tauchen im Programmtext BASIC.BAS auf. Sie haben nichts
mit den Variablen zu tun, die vom BASIC-BASIC Interpreter fr die
Verwendung in BASIC-BASIC Programmen wie ZINSEN.BAS zur Verfgung
gestellt werden. Es gibt hier zwei verschiedene BASICs, zum einen das
GWBASIC, das zum Schreiben des BASIC-BASIC Interpreters verwendet wird
und zum anderen BASIC-BASIC, die Sprache, die der BASIC-BASIC Inter-
preter versteht.

Das Programm

Den Anfang des Programms macht die Ausgabe einer kurzen
Programmerklrung fr den spteren Benutzer. Kommentare ber die
Verwendung der Variablennamen folgen als Hinweis fr andere
Programmierer. Nun kommen alle Anweisungen, die nur zu Beginn des
Programmlaufs durchgefhrt werden sollen. Dazu zhlt die
Dimensionierung der indizierten Variablen (Feldern) und das Setzen der
Funktionstastenbelegung fr dieses Programm.

Damit der Benutzer gleich mit der Eingabe eines Programmtextes
beginnen kann, wird zuerst der Programmtextspeicher gelscht, indem
einfach die Anzahl der gespeicherten Zeilen auf Null gesetzt wird.
Praktisch derselbe Code wird verwendet, wenn spter irgendwann das
Kommando NEW ausgefhrt werden soll.

Danach erwartet der Rechner die Eingabe des nchsten Kommandos. Damit
spter nicht unendlich viele Vergleiche zwischen unterschiedlich
klein- und grogeschriebenen Worten notwendig werden, wird die Eingabe
in Grobuchstaben umgewandelt. Das Programm entnimmt dann das erste
Symbol aus der Kommandozeile und springt zu einem von 8
Programmteilen, die jeweils das Kommando bearbeiten oder zu einer
Fehlermeldung.

Jedes dieser Programmstcke prft, ob der Rest der Kommandozeile exakt
die von dem Kommando bentigten Angaben enthlt. Das LIST Kommando
wird mit wenigen Programmtextzeilen erledigt. Es schreibt lediglich
alle Zeilen aus dem Programmtextspeicher P$() auf den Bildschirm,
deren Zeilennummer nicht kleiner ist als die kleinste gewnschte Zeilen-
nummer und nicht grer ist als die grte gewnschte Zeilennummer.

Beginnt das Kommando mit einer Zeilennummer, so sind vier verschiedene
Kombinationen mglich. Je nach dem, ob es sich um eine neue oder eine
bereits verwendete Zeilennummer handelt und ob hinter der Zeilennummer
eine Anweisung angegeben wurde oder nicht, mu eine Programmtextzeile
in den aktuellen Programmtext eingefgt, eine bereits vorhandenen
ersetzt oder entfernt werden. Die Programmabschnitte, die diese
Funktionen bernehmen, folgen unmittelbar. Dabei mssen die Funktionen
dafr Sorge tragen, da die Zeilen im Programmtextspeicher nach den
Zeilennummern sortiert bleiben.

Durch das RUN Kommando wird der Interpreter in Aktion versetzt. Bevor
die im Programmtextspeicher vorhandenen Programmtextzeilen der Reihe
nach abgearbeitet werden, lscht das System alle Variablen, in dem
es die Anzahl der bekannten Variablen (G%) auf 0 setzt. Dann wird das
Schlsselwort am Beginn der ersten Programmtextzeile entnommen und
ein dazu passendes Programmstck aufgerufen. Der Interpreter nimmt
sich der Reihe nach alle Programmtextzeilen vor, lediglich durch die
Sprunganweisung GOTO vom Weg abgebracht.

Beim LOAD Kommando wird ein Programmtext von der Diskette gelesen. Er
ersetzt den aktuellen Programmtext in der Variablen P$(). Beim SAVE
Kommando wird der aktuelle Programmtext in eine Datei geschrieben.
Hier machen die Anweisungen zum Abfangen von Fehlern (ON ERROR GOTO)
den wesentlichen Teil der Programmabschnitte aus. Das Anzeigen des
Inhaltsverzeichnisses nach einem DIR Kommando bernimmt
freundlicherweise die FILES Anweisung von GWBASIC. Beim BYE Kommando
zum Verlassen des BASIC-BASIC Interpreters werden die Funktionstasten
wieder auf die Werte gesetzt, die sie beim Start des Programmes hatten
und das Programm beendet.

Es folgen kleinere Programmstcke, die jeweils eine spezielle
Anweisung des BASIC Programmes bearbeiten. Sie werden vom Interpreter
verwendet, wenn am Anfang der aktuellen Programmtextzeile das
Schlsselwort der jeweiligen Anweisung gefunden wird. Sie analysieren
den Rest der Programmtextzeile Wort fr Wort und fhren die
angegebenen Aktionen aus. Bei der Analyse wird stur nach dem
Syntaxdiagramm fr die jeweilige Anweisungen verfahren.

An verschiedenen Stellen kann in einer Anweisung eine Rechnenformel
verwendet werden. Die Analyse einer Rechenformel wurde hier in einem
Unterprogramm untergebracht. Das entspricht auch der Aufteilung der
Syntaxdiagramme. Entsprechend der Prioritt der Operatoren beginnen
wir mit der Strichrechnung, es folgt die Punktrechnung und dann der
eigentliche Wert, der eine Zahl, der Wert einer Variablen oder das
Ergebnis einer in Klammern gesetzten weiteren Rechenformel sein kann.

Es folgt ein Unterprogramm, welches den Namen einer Variablen (in W$)
in der Tabelle der Namen der bekannten Variablen (B$(1)..B$(G%)) sucht,
ihn ggf. hinzufgt und die Position, an der der Variablenname in der
Liste eingetragen ist in der Variablen E% zurckliefert.

Nun kommen die zuvor erwhnten Unterprogramme, die das jeweils nchste
Wort aus der aktuellen Zeile entnehmen.

Da im Programm mehrmals eine Ja/Nein Antwort verlangt wird, wir jedoch
den Aufwand der berprfung der Eingabe nicht mehrmals wiederholen
mchten, wird eine solche Eingabe mithilfe des letzten Unterprogramms
entgegengenommen.

Die Erweiterungen

Sie werden bei diesem Interpreter Zeichenkettenvariablen, Felder, und
eine Reihe von Kommandos und Anweisungen Ihres Rechners vermissen.
Erweitern Sie das Programm um alle Funktionen, die Ihnen sinnvoll
erscheinen. 

Warum sind die unter dem BASIC-BASIC Interpreter ablaufenden
Programme (z.B. ZINSEN.B) so langsam ? Nun, ein Interpreter mu
nicht nur die gewnschten Anweisungen ausfhren, sondern sie
vorher auch verstehen, d.h. das BASIC-BASIC Programm analysieren.
Dieser Proze des Verstehens kostet zustzliche Zeit und verlangsamt
die Programmausfhrung erheblich, etwa um den Faktor 10. Da Sie nun
ZINSEN.B unter dem BASIC-BASIC Interpreter ausfhren und dieser
wiederum unter dem GWBASIC Interpreter luft, verlangsamt sich das
ganze pltzlich um 10 x 10, den Faktor 100.

Die Geschwindigkeit des Programms kann erheblich vergrert werden,
wenn es mit einem BASIC Compiler in Maschinensprache bersetzt wird.
Dann entfllt die Stufe des GWBASIC Interpretes und pltzlich ist
ZINSEN.B unter BASIC-BASIC fast genau so schnell, wie ZINSEN.BAS
unter GWBASIC.

Das Programm ist unter Microsoft GWBASIC 3.20, Viktor VBASICA 2.20,
IBM BASCOM und MS QuickBasic 2.01 getestet worden. Bei den Compilern
muss die Option /e angegeben werden, sonst werden die ON ERROR GOTO
Anweisungen nicht akzeptiert.

M. Winterhoff

Happy Computing...
