Fragen zur Programmierung eines Interpreters
Verfasst: 27.04.2019 11:23
Hallo Kollegen,
ich möchte mein Programm mit einer Art kleinen Skriptsprache versehen, so dass der Anwender eigene Skripte erstellen kann, die mein Programm dann verarbeitet bzw. ausführt. Es geht dabei um die Bearbeitung von Texten.
Bei bestimmten Teilen der Umsetzung ist mir noch nicht klar wie ich es am besten realisieren sollte, daher richtet sich meine Frage an Leute die so etwas schon mal programmiert haben.
Aber erst nochmal kurz erklärt was das eigentlich werden soll. Im Prinzip soll diese Skriptsprache wie eine Macrosprache mit den Textdaten in einem Texteditor arbeiten können. Das vom User erstellte Script soll in der Lage sein ein Ergebnis-Array mit Daten zu füllen die aus einer Textdatei extrahiert werden. Ein Script kann dabei immer nur mit einer Textdatei arbeiten.
Denkbare Befehle wären z.B.: Die komplexeren Dinge wie Variablen und Bedingungen (If, Else, Endif) lasse ich erstmal außen vor.
Ich würde die Behandlung und Ausführung der Sprache in zwei Schritten durchführen.
1) Tokenizen, also die Befehle und deren Parameter und ggf. Operatoren in numerische Tokens wandeln, die ich dann als 2-dimensionales Array im Speicher halte.
2) Das 2D-Array stellt dann quasi das Script-Programm dar und wird von einer "virtuellen CPU" sequentiell abgearbeitet.
Das Array könnte so aussehen:
Ich würde in diesem Array Felder für alle möglichen Parametertypen haben, es würden dann aber nur jene ausgefüllt werden, die der entsprechende Token benötigt. Bei dem Token für GotoLine würde also nur IntParamerter1 genutzt werden, weil "GotoLine" nur einen numerischen Parameter hat.
Das ganze geht sicherlich eleganter, mir ist bisher nur noch nichts anderes dafür eingefallen.
Was mir auch noch nicht ganz klar ist:
Wie gestalte ich den Aufruf der zu einem Token gehörenden Prozedur? Ich könnte ein weiteres Array nutzen in dem ich zu jedem Token die Prozedure-Adresse eingetrage (oder der Tokenizer schreibt die entsprechende Prozedur-Adresse bereits in das Token-Array, dann spart man sich das weitere Adressen-Array):
So könnte man dann mit einem Prototype arbeiten und die Prozedur ungefähr so aufrufen:
Hier fragt sich wie man es am besten mit den Parametern und den Operatoren macht. Die Parameter kann ich beim Prototype nicht mit angeben, weil sie unter Umständen für jeden Skriptbefehl anders sind. Ich könnte ein globales "Parameter-Übergabearray" bzw. eine Struktur nutzen, welches wieder jeweils ein Feld für alle möglichen Parameter/Operatoren aufnimmt. Die "virtuelle CPU", die den tokenisierten Code abarbeitet, muss dann die entsprechenden Werte des Tokens dort hinein übertragen und die danach aufgerufene Prozedur müsste sich die für sie passenden Werte von dort herausnehmen.
Globales Parameter-Array: Hierrauf greift jede der aufgerufenen "Befehls-Prozeduren" zu.
Das würde vermutlich alles irgendwie gehen, aber sicherlich funktioniert es auch eleganter bzw. einfacher, so dass man nicht immer die Felder für alle möglich vorkommenden Parameter in den Arrays/Strukturen bereithalten muss.
Leider ist dies mein allererster Interpreter, den ich schreibe. Habt ihr dazu ein paar Tipps für mich?
Vielen Dank
Kurzer
ich möchte mein Programm mit einer Art kleinen Skriptsprache versehen, so dass der Anwender eigene Skripte erstellen kann, die mein Programm dann verarbeitet bzw. ausführt. Es geht dabei um die Bearbeitung von Texten.
Bei bestimmten Teilen der Umsetzung ist mir noch nicht klar wie ich es am besten realisieren sollte, daher richtet sich meine Frage an Leute die so etwas schon mal programmiert haben.
Aber erst nochmal kurz erklärt was das eigentlich werden soll. Im Prinzip soll diese Skriptsprache wie eine Macrosprache mit den Textdaten in einem Texteditor arbeiten können. Das vom User erstellte Script soll in der Lage sein ein Ergebnis-Array mit Daten zu füllen die aus einer Textdatei extrahiert werden. Ein Script kann dabei immer nur mit einer Textdatei arbeiten.
Denkbare Befehle wären z.B.:
Code: Alles auswählen
GotoLine 30 ; Setzt den Lesepointer in der Textdatei auf den Anfang der 30.ten Zeile
GotoOffset 185 ; Setzt den Lesepointer in der Textdatei vor das 185.te Zeichen
GetString(5) ; Gibt ausgehened vom aktuellen Lesepointer die nächsten 5 Zeichen als String zurück
Ich würde die Behandlung und Ausführung der Sprache in zwei Schritten durchführen.
1) Tokenizen, also die Befehle und deren Parameter und ggf. Operatoren in numerische Tokens wandeln, die ich dann als 2-dimensionales Array im Speicher halte.
2) Das 2D-Array stellt dann quasi das Script-Programm dar und wird von einer "virtuellen CPU" sequentiell abgearbeitet.
Das Array könnte so aussehen:
Code: Alles auswählen
Token, StringParameter1, StringParameter2, IntParamerter1, IntParamerter2, OperatorDas ganze geht sicherlich eleganter, mir ist bisher nur noch nichts anderes dafür eingefallen.
Was mir auch noch nicht ganz klar ist:
Wie gestalte ich den Aufruf der zu einem Token gehörenden Prozedur? Ich könnte ein weiteres Array nutzen in dem ich zu jedem Token die Prozedure-Adresse eingetrage (oder der Tokenizer schreibt die entsprechende Prozedur-Adresse bereits in das Token-Array, dann spart man sich das weitere Adressen-Array):
Code: Alles auswählen
Token, Prozedure-Adresse
1, @GotoLine() ; Adresse von Prozedure GotoLine() / 1 = GotoLine
2, @GotoOffset() ; Adresse von Prozedure GotoOffset() / 2 = GotoOffset
3, @GetString() ; Adresse von Prozedure GetString .... usw.
Code: Alles auswählen
Prototype.i Command()
Cmd.Command = [Adresse] ; Hier die Prozedur-Adresse aus der o.g. Tokenliste eintragen.
Cmd() ; Und die Prozedur aufrufenGlobales Parameter-Array: Hierrauf greift jede der aufgerufenen "Befehls-Prozeduren" zu.
Code: Alles auswählen
StringParameter1, StringParameter2, IntParamerter1, IntParamerter2, OperatorLeider ist dies mein allererster Interpreter, den ich schreibe. Habt ihr dazu ein paar Tipps für mich?
Vielen Dank
Kurzer