Ich habe kürzlich die Aufgabe übernommen, eine stapelbasierte Programmiersprache zu schreiben. Bevor ich jedoch anfing, meine Sprache zu entwerfen, hielt ich es für eine gute Idee, vorhandene stapelbasierte Sprachen zu lesen und damit zu experimentieren.
Dies bringt mich zum Thema dieses Beitrags. Ich habe den Wikipedia-Artikel über Forth gelesen , eine stapelbasierte Sprache, die Ausdrücke im Postfix-Stil verwendet. In dem Artikel habe ich folgende Aussage gesehen:
Die Flexibilität von Forth macht eine statische BNF-Grammatik unangemessen und es gibt keinen monolithischen Compiler. Zum Erweitern des Compilers muss nur ein neues Wort geschrieben werden, anstatt eine Grammatik zu ändern und die zugrunde liegende Implementierung zu ändern.
Nach meinem Verständnis scheint der Begriff "Wort" im Forth-Jargon im Grunde genommen gleichbedeutend mit "Unterprogramm" zu sein. Angesichts dessen erscheint die obige Aussage seltsam. Warum genau würde die Fähigkeit, neue Funktionen in Forth zu erstellen, eine formale Grammatik für Forth unangemessen machen? Warum müssen Sie die Grammatik für jede neue Unterroutine, die Sie definieren, neu schreiben? Wie stellt ein neues Wort in der Umgebung Schreiben Verlängerung des Compilers? Die obige Aussage scheint zu sagen, dass eine formale Grammatik für Python ungeeignet ist, da Sie neue Funktionen definieren können.
Tatsächlich habe ich mich entschlossen, eine Grammatik im BNF-Stil für eine einfache Teilmenge von Forth zu schreiben:
program ::= stmt+
stmt ::= func | expr
func ::= ':' expr+ ';'
expr ::= INTEGER | word
word ::= ('+' | '-' | '*' | '/' )
Die obige Grammatik scheint eine gültige Teilmenge von Forth-Anweisungen abzudecken und scheint nicht so schwer zu erweitern, um alle gültigen Anweisungen in der Forth-Sprache abzudecken. Wenn der Parser eines Compilers die obige Grammatik implementiert, sehe ich nicht, wie der Compiler jemals erweitert werden würde. Der Compiler fügt seiner Umgebung einfach neue Wörter hinzu . Nur die Umgebung wird geändert. Es scheint fast so, als würde der obige Auszug aus Wikipedia den unterstrichenen Code, aus dem der Compiler besteht (der sich nicht ändert), mit der Umgebung des Compilers (die sich ändert) zusammenführen.
Zusammenfassend lässt sich sagen, warum Forths Fähigkeit, neue Wörter (Unterprogramme) zu definieren, für eine geschriebene Grammatik ungeeignet ist.
Antworten:
Ein "normales" Wort ist so ziemlich nur eine Unterroutine.
... aber Sie können ein benutzerdefiniertes definierendes Wort schreiben , das die Funktionsweise des Compilers ändert. Beispielsweise beginnt eine Definition normalerweise mit einem Doppelpunkt (":") und endet mit einem Semikolon (";"). Wenn Sie möchten, können Sie (zum Beispiel) ändern, was der Doppelpunkt tut, und dabei ändern, wie eine Wortdefinition "kompiliert" wird, wodurch die Funktionsweise des Compilers und die Grammatik der erkannten Sprache geändert werden.
Aus diesem Grund heißt es, dass eine Grammatik unangemessen ist - die Grammatik kann sich buchstäblich von einem Teil des Programms zum anderen ändern. Durch das Laden eines Wörterbuchs können nicht nur die Unterprogramme geändert werden, deren Namen derzeit erkannt werden, sondern auch die Grammatik, die beim Definieren eines neuen Wortes analysiert wird.
quelle
In Forth können Sie Code zur Kompilierungszeit ausführen.
Insbesondere können Sie Code ausführen, der Wörter aus der Eingabe verbraucht. Sie können beispielsweise einen C-Compiler in Forth schreiben und ihn dann zur Kompilierungszeit aufrufen und dann den Rest Ihres Programms in C schreiben.
In der Regel können Sie Wörter definieren, die Argumente aus dem Quellcode lesen. Traditionell lesen Sie Wörter genauso wie der Compiler, dies ist jedoch nicht erforderlich.
Zum Beispiel
."
liest das Wort (das eine Zeichenfolge druckt) erst im nächsten Leerzeichen, es liest bis zum nächsten"
. Wenn Sie versuchen, den Code: PRINTHELLO ." Hello ; : func2 world!" ;
ohne Sonderfall zu analysieren."
, werden Sie feststellen, dass er nicht korrekt analysiert wird.Sie können
."
Ihrer Grammatik sicherlich einen Sonderfall hinzufügen , aber die Grammatik ist immer noch falsch, wenn der Programmierer sein eigenes Wort wie folgt definiert."
- zum Beispiel hier eines :: MY_PRINT POSTPONE ." ; IMMEDIATE
. Dieses Wort ist äquivalent zu."
; Ich kann schreibenMY_PRINT Hello ; world! "
und Ihre Grammatik muss sie analysieren können. Viel Glück damit.quelle