[JAVA] Weg zur REPL (?) Schöpfung (1)

Einführung

Vorerst werde ich versuchen, REPL in Java 8 zu erstellen.

REPL (Lesen (Leseeingabe) - Val (Ausführung) - Drucken (Ergebnisdrucken) - Loop (Schleife mit 3 Funktionen links)) ist eine Umgebung zum interaktiven Ausführen von Programmen, hauptsächlich Python. Es ist eine vertraute Funktion im Skriptprogramm und in Common Lisp. Darüber hinaus verfügen Konsolentools (wie SQLPlus), die mit DBMS geliefert werden, über ähnliche Funktionen hinsichtlich der Interpretation und Ausführung von Eingabe- und Ausgabeergebnissen.

Wir schaffen die Grundlage für ein Java-Konsolenprogramm und nicht für das letztere, sondern für die ziemlich breite REPL und nicht für die interaktive Shell der Programmiersprache.

Ich habe auf den folgenden Artikel verwiesen. (Entschuldigung für die Verzögerung in der Beschreibung) Erstellen Sie eine REPL (Read-Eval-Print-Schleife).

wichtiger Punkt

Bedarf

Zunächst müssen die Anforderungen für die REPL erstellt werden.

Programmstil

Bitte beachten Sie, dass es sich um einen Oleore-Stil handelt, der von der allgemeinen Beschreibung von Java abweicht. Es gibt die folgenden Gründe. Es ist ein Nachdruck + α des vorherigen Eintrags Erstellen einer Phrasenanalyse mit Java 8 (Teil 1).

BaseREPL-Klasse

Beim Schreiben des Artikels habe ich mich gefragt, ob ich ihn von oben nach unten oder von unten nach oben erklären soll, aber um das ganze Bild zu verdeutlichen, werde ich es von oben erklären. Wenn Sie auf einen Klassennamen stoßen, den Sie nicht kennen, betrachten Sie ihn bitte mit dem Gefühl: "Ich werde die Details von nun an erklären."

Zunächst das Gesamtbild der abstrakten Klasse BaseREPL.

BaseREPL.java


abstract class BaseREPL {
   enum States {
        Quit,           //Ende
        Finished,       // Cleanup()Erledigt
        Error,          //Error
        NotFind,        //Kein Zielbefehl
        Input,          //Eingang(default)
        Incomplete,     //Unvollständige Eingabe(Wird zur Unterstützung der mehrzeiligen Eingabe verwendet)
        Complete,       //Eingabe abgeschlossen
    }

    BaseREPL(String encoding) {
        if ( encoding == null  ||  encoding.trim().isEmpty() ) { encoding = "UTF-8"; }
        console_ = Service.Console.create(encoding);
    }

    /**Hauptschleife.(template method) */
    public final void run() {
        if ( state_ == States.Finished ) { return; }

        try {
            welcome();
            while (state_ != States.Quit) {
                state_ = response( eval( accept(prompt_) ) );
            }
            goodbye();
        } finally {
            cleanup();
            state_ = States.Finished;
        }
    }

    // user defined methods ==========================================================================
    abstract protected String accept(String prompt);    //Sofortiger Anzeige- / Eingangsempfang
    abstract protected States eval(String input);       //Interpretation / Ausführung der Eingabezeichenfolge
    abstract protected States response(States state);   // eval()Nachbearbeitung
    abstract protected void   cleanup();                //Am Ende von REPL aufräumen

    abstract protected void welcome();                  //Anzeige der REPL-Startzeichenfolge
    abstract protected void goodbye();                  //Anzeige der REPL-Endzeichenfolge
    abstract protected void help();                     //Hilfezeichenfolge anzeigen

    // print strings to console ======================================================================
    public final void print(String format, Object... args)   { console_.print(format, args);     }
    public final void print(String s)                        { console_.print(s);                }
    public final void print(String[] sz)                     { for (String s : sz) { print(s); } }
    public final void print(java.util.Collection<String> sz) { for (String s : sz) { print(s); } }

    // internal fields ===============================================================================
    protected final Interface.Console console_ = Service.Console.get();
    protected       String prompt_ = "REPL> ";
    protected       States state_ = States.Input;
}

Kommentar

Eine Beschreibung der Quelle. Da es sich jedoch um eine abstrakte Klasse handelt, ist sie fast leer.

Konstrukteur

** Hinzugefügt am 28. Oktober 2018 ** Es wurde ein Konstruktor hinzugefügt, der den Codierungsnamen der Konsole erhält. Wenn null oder leer übergeben wird, wird standardmäßig "UTF-8" verwendet.

python


    BaseREPL(String encoding) {
        if ( encoding == null  ||  encoding.trim().isEmpty() ) { encoding = "UTF-8"; }
        console_ = Service.Console.create(encoding);
    }

    protected final Interface.Console console_;

Hauptschleife

Die Hauptschleife ist ein fester Prozess.

enum statesIst ein Aufzählungstyp, der den Status von repl darstellt. Diese Klasse verwendet nur States.Finished und States.Quit. Die anderen Enumeratoren haben trotz der Kommentare nicht entschieden, wie sie verwendet werden sollen. Sie können es am Vererbungsziel beliebig verwenden. (Ich kann mir keine andere Verwendung als States.input, States.Error und States.Missing vorstellen ...)

Da davon ausgegangen wird, dass cleanup () die verwendeten Objekte und Ressourcen bereinigt, besteht nach dem Beenden der run () -Methode eine hohe Wahrscheinlichkeit, dass sie aufgrund fehlender Ressourcen abnormal endet, also zu Beginn der Methode Ich habe geprüft, ob es abgeschlossen wurde. Wie ich in den Notizen geschrieben habe, werde ich auch in einem Stil beschreiben, der nicht so viele Ausnahmen wie möglich auslöst, aber selbst wenn eine Ausnahme ohne Unterbrechung auftritt, lautet der Verarbeitungskörper "try", sodass cleanup () sicher ausgeführt wird. Schließen Sie es in {} `ein und rufen Sie die cleanup () -Methode in der` finally {} `` `-Klausel auf. Verwenden Sie daher nicht exit ().

    enum States {
        Quit,           //Ende
        Finished,       // Cleanup()Erledigt
        Error,          //Error
        NotFind,        //Kein Zielbefehl
        Input,          //Eingang(default)
        Incomplete,     //Unvollständige Eingabe(Wird zur Unterstützung der mehrzeiligen Eingabe verwendet)
        Complete,       //Eingabe abgeschlossen
    }

    /**Hauptschleife.(template method) */
    public final void run() {
        if ( state_ == States.Finished ) { return; }

        try {
            welcome();
            while (state_ != States.Quit) {
                state_ = response( eval( accept(prompt_) ) );
            }
            goodbye();
        } finally {
            cleanup();
            state_ = States.Finished;
        }
    }

    protected String prompt_ = "REPL> ";
    protected States state_ = States.Input;

Benutzerdefinierte Methode

Die hier enthaltenen Methoden sind Klassen, die von Klassen implementiert werden müssen, die von BaseREPL erben. Ich habe erklärt, was die Methode in der Hauptschleife macht, also werde ich sie weglassen.

help()Wird in der Hauptschleife nicht verwendet. Diese Methodeeval()Wenn es als Anzeige von Hilfe interpretiert wird und Hilfetext unterstützt, wird es in der geerbten Klasse implementiert.

python


    abstract protected String accept(String prompt);    //Sofortiger Anzeige- / Eingangsempfang
    abstract protected States eval(String input);       //Interpretation / Ausführung der Eingabezeichenfolge
    abstract protected States response(States state);   //Nachbearbeitung nach Auswertung
    abstract protected void   cleanup();                //Am Ende von REPL aufräumen

    abstract protected void welcome();                  //Anzeige der REPL-Startzeichenfolge
    abstract protected void goodbye();                  //Anzeige der REPL-Endzeichenfolge
    abstract protected void help();                     //Hilfezeichenfolge anzeigen

Ausgabedienstmethode

Eine Methode, die die Ausgabe an die Konsole liefert. Alle Methodennamen werden zum Drucken vereinheitlicht, und je nach Art des Arguments werden 4 Arten von Überladungen vorbereitet.

Diese Methoden delegieren letztendlich die Verarbeitung an das Interface.Console-Objekt. Dieses Objekt wird zu einem späteren Zeitpunkt (wahrscheinlich beim nächsten Mal) erklärt.

    public final void print(String format, Object... args)   { console_.print(format, args);     }
    public final void print(String s)                        { console_.print(s);                }
    public final void print(String[] sz)                     { for (String s : sz) { print(s); } }
    public final void print(java.util.Collection<String> sz) { for (String s : sz) { print(s); } }

    protected final Interface.Console console_;

Zusammenfassung

Das Obige ist die Erklärung der Basisklasse von REPL.

Wie Sie der Quelle entnehmen können, lautet die Methode `run ()` GoF [Entwurfsmuster](https: // qiita). com / tags /% E3% 83% 87% E3% 82% B6% E3% 82% A4% E3% 83% B3% E3% 83% 91% E3% 82% BF% E3% 83% BC% E3% 83 Es entspricht Template Method von% B3). Um es auszudrücken, wird es als abstrakte Klasse definiert, nicht als Schnittstelle. Darüber hinaus wurden mit dem endgültigen Modifikator Methoden implementiert, die nicht von der Implementierung des Vererbungsziels abhängen.

Basierend auf dieser abstrakten Klasse möchte ich beim nächsten Mal eine konkrete REPL-Klasse implementieren, aber da ich verschiedene Wünsche habe, plane ich, einen Mechanismus zu erstellen, der in der geerbten Klasse verwendet wird.

Weg zur Erstellung von REPL (?) (2)

Recommended Posts

Weg zur REPL (?) Schöpfung (1)
Weg zur REPL (?) Schöpfung (2)
19 Entspricht der Objekterstellung
Straße nach Java SE 11 Silberakquisition
Der Weg von JavaScript nach Java
to_ ○
Der Weg zur Erstellung eines Soundspiels 2
Java SE8 Silber ~ Der Weg zum Pass ~
Einführung in Kotlin für iOS-Entwickler lin ー Kotlin-Erstellung
Der Weg zur Erstellung eines Soundspiels 3
Der Weg zur Erstellung eines Soundspiels 1