[JAVA] 9 Entspricht dem Rückgabewert

Einführung

Im vorherigen Artikel Mehrere Argumente unterstützen. Ich möchte weiterhin dem Rückgabewert der Funktion entsprechen.

Was Sie mit dem Rückgabewert der Funktion tun möchten

Stellen Sie sicher, dass Sie es einfach machen möchten. Wenn Sie beispielsweise ein Programm wie das folgende haben, wird der Rückgabewert des Funktionsaufrufs "add3 ()" zurückgegeben und der Variablen "v" zugewiesen. Wir wollen den Wert "6" der Variablen "v" an die Standardausgabe ausgeben.

function add3(a1, a2, a3) {
  return a1 + a2 + a3
}
v = add3(1,2,3)
println(v)

Es ist dasselbe wie im vorherigen Artikel, dass es nicht dem Umfang der Variablen entspricht.

Wie zu implementieren

Wir werden überlegen, wie es in der Reihenfolge Syntaxanalyse (Parser) und Interpreter (Interpreter) implementiert werden kann. Die Phrasenanalyse (Lexer) wird nicht geändert.

So implementieren Sie Parser

Bei der Implementierung der Syntaxanalyse von "return" müssen Sie auf die Syntax von "return" achten. Die Syntax von "return" wird manchmal als Rückgabewert angegeben, z. B. "return 1". In einigen Fällen wird nur "return" angegeben und kein Rückgabewert angegeben. Wenn die Angabe von nur "return" in der Syntax korrekt ist, Wenn "return 1" geschrieben ist, Es kann als Syntax verwendet werden, wenn ein Rückgabewert angegeben wird. In Anbetracht dessen, dass "1" eine von "return" unabhängige Syntax ist, Es kann als Syntax verwendet werden, wenn der Rückgabewert nicht angegeben ist. Um diese Situation leicht zu lösen, werden wir einen schlampigen Ansatz verfolgen. Die Methode ist, wenn das } Token nach dem return Token kommt, Wird als "Rückgabe" betrachtet, wenn kein Rückgabewert angegeben ist. Im Gegenteil, wenn das Token "}" nicht kommt, wird es als "return" angesehen, wenn der Rückgabewert angegeben wird. Das Parsen, wenn kein Rückgabewert angegeben ist, wird wie ein Variablenname behandelt. Das Parsen, wenn ein Rückgabewert angegeben wird, wird genauso behandelt wie ein einzelner Termoperator wie "-1".

So implementieren Sie Interpreter

Der Interpreter nimmt Änderungen an der Methode body () vor, die Ausdrücke nacheinander ausführt. Wenn es sich um ein "Return" -Token in "body ()" handelt, Unterbricht die sequentielle Ausführung und kehrt zum Anrufer zurück. Außerdem kann "return" nur innerhalb einer Funktion aufgerufen werden. Es wird auch bestimmt, ob es sich um einen Rückruf innerhalb der Funktion handelt.

Versuchen Sie, in Java zu implementieren

Fahren Sie mit der Implementierung fort. Informationen zu Syntaxparser (Parser) und Interpreter (Interpreter) Schauen wir uns die Änderungen und Ergänzungen der Reihe nach an.

Parser.java

Eine Implementierung von Parser.java. Fügen Sie eine Definition hinzu, wie es für die Bedeutung des Tokens funktioniert. Da "return" ein reserviertes Wort ist, Ich habe "return" hinzugefügt, wo es "<-Update" gibt.

Parser.java


    public Parser() {
        degrees = new HashMap<>();
        degrees.put("(", 80);
        degrees.put("*", 60);
        degrees.put("/", 60);
        degrees.put("+", 50);
        degrees.put("-", 50);
        degrees.put("=", 10);
        factorKinds = Arrays.asList(new String[] { "digit", "ident" });
        binaryKinds = Arrays.asList(new String[] { "sign" });
        rightAssocs = Arrays.asList(new String[] { "=" });
        unaryOperators = Arrays.asList(new String[] { "+", "-" });
        reserved = Arrays.asList(new String[] { "function", "return" });    // <-- Update
    }

Es ist eine Änderung des zu analysierenden Teils. Es wurde eine if-Anweisung hinzugefügt, die return dahin analysiert, wo <-Add ist. Es sei denn, das Token neben dem "Return" -Token ist "eob", was die Art der schließenden schließenden Klammer darstellt Beurteilt als "Rückgabe", die einen Wert zurückgibt, und enthält das Token, das der Rückgabewert im Feld "Links" ist.

Parser.java


    private Token lead(Token token) throws Exception {
        if (token.kind.equals("ident") && token.value.equals("function")) {
            return func(token);
        } else if (token.kind.equals("ident") && token.value.equals("return")) {    // <-- Add
            token.kind = "ret";
            if (!token().kind.equals("eob")) {
                token.left = expression(0);
            }
            return token;
        } else if (factorKinds.contains(token.kind)) {
            return token;
        } else if (unaryOperators.contains(token.value)) {
            token.kind = "unary";
            token.left = expression(70);
            return token;
        } else if (token.kind.equals("paren") && token.value.equals("(")) {
            Token expr = expression(0);
            consume(")");
            return expr;
        } else {
            throw new Exception("The token cannot place there.");
        }
    }

Interpreter.java

Eine Implementierung von Interpreter.java.

Dies ist eine Änderung der Methode body (), die Ausdrücke nacheinander ausführt.

body () war ein void Typ, der keinen Rückgabewert zurückgibt, aber in einen Object Typ geändert wurde, damit er einen Rückgabewert zurückgeben kann. Boolean [] ret zur Signatur von body () hinzugefügt. ret hat zwei Rollen. Das erste ist, dass, wenn "ret" nicht "null" ist, "return" möglich ist. Das zweite ist, dass wenn es "return" wäre, es an den Anrufer weitergeben würde, dass es "return" wäre. Der Grund, ret zu einem Array-Typ von boolean zu machen, besteht darin, einen Wert an den Aufrufer zurückzugeben. Es wird auf böse Weise verwendet, nicht zum Zweck der Verwendung des ursprünglichen Arrays. Ich wollte es einfacher machen, wie ein Argument mit dem Schlüsselwort "ref" in C # zu arbeiten.

Das erste, was in "for" ist, ist zu bestimmen, ob das Token, das nacheinander ausgeführt werden soll, "return" ist. Wenn es nicht "return" ist, ist es der gleiche Prozess wie der vorherige "body ()". Wenn es sich um "Rückkehr" handelt, wird beurteilt, ob eine "Rückkehr" möglich ist. Ersetzen Sie "true", um dem Anrufer mitzuteilen, dass er zu "ret" zurückkehren soll. Wenn es einen Rückgabewert für "return" gibt, führen Sie das Token aus, das der Rückgabewert ist, mit "expression ()".

Interpreter.java


    public Object body(List<Token> body, boolean[] ret) throws Exception {
        for (Token exprs : body) {
            if (exprs.kind.equals("ret")) {
                if (ret == null) {
                    throw new Exception("Can not return");
                }
                ret[0] = true;
                if (exprs.left == null) {
                    return null;
                } else {
                    return expression(exprs.left);
                }
            } else {
                expression(exprs);
            }
        }
        return null;
    }

Dies ist eine Modifikation der Methode "invoke ()" der Klasse "DynamicFunc". <-Update ist die Änderung. Unterstützt das Ändern der Signatur und des Rückgabewerts der Methode "body ()". Das Zuweisen einer Instanz zum Argument "ret" zeigt an, dass die Situation "zurückgegeben" werden kann. Der Rückgabewert von "body ()" wird genauso verwendet wie der Rückgabewert von "invoke ()".

Interpreter.java


    public static class DynamicFunc extends Func {

        public Interpreter context;
        public List<Token> params;
        public List<Token> block;

        @Override
        public Object invoke(List<Object> args) throws Exception {
            for (int i = 0; i < params.size(); ++i) {
                Token param = params.get(i);
                Variable v = context.variable(context.ident(param));
                if (i < args.size()) {
                    v.value = context.value(args.get(i));
                } else {
                    v.value = null;
                }
            }
            boolean[] ret = new boolean[1]; // <-- Update
            return context.body(block, ret); // <-- Update
        }
    }

Dies ist eine Modifikation der Methode run (). <-Update ist die Änderung. Unterstützt das Ändern der Signatur und des Rückgabewerts der Methode "body ()". Die Situation, in der run () aufgerufen wird, befindet sich nicht innerhalb der Funktion. Da die Situation nicht "return" sein kann, gibt das formale Argument "ret" "null" an.

Interpreter.java


    public Map<String, Variable> run() throws Exception {
        body(body, null); // <-- Update
        return variables;
    }

Das folgende Programm verwendet die obige Implementierung

function add3(a1, a2, a3) {
  return a1 + a2 + a3
}
v = add3(1,2,3)
println(v)

Drucken des der Variablen "v" zugewiesenen Werts "6" an die Standardausgabe.

Interpreter.java


    public static void main(String[] args) throws Exception {
        String text = "";
        text += "function add3(a1, a2, a3) {";
        text += "  return a1 + a2 + a3";
        text += "}";
        text += "v = add3(1,2,3)";
        text += "println(v)";
        List<Token> tokens = new Lexer().init(text).tokenize();
        List<Token> blk = new Parser().init(tokens).block();
        new Interpreter().init(blk).run();
        // --> 6
    }

Das ist alles für die Implementierung. Vielen Dank.

abschließend

Die vollständige Quelle finden Sie hier.

Calc https://github.com/quwahara/Calc/tree/article-9-return-r2/Calc/src/main/java

Es gibt einen Folgeartikel.

** Entspricht der if-Anweisung ** http://qiita.com/quwahara/items/96a68cdee4f2a0452836

Recommended Posts

9 Entspricht dem Rückgabewert
12 Entspricht der while-Anweisung
[Rails] Sprechen Sie darüber, wie Sie auf den Rückgabewert von where achten
Ruby-Methoden geben den zuletzt ausgewerteten Wert zurück
So übergeben Sie den Wert an einen anderen Bildschirm
17 Entspricht einem Array
Entspricht dem Geltungsbereich
Entspricht 15 Zeichenfolgen
Zurückgeben eines Werts vom Modell an den Controller mithilfe des [Swift5] -Protokolls
Speichern Sie den Rückgabewert des AWS SDK in DynamoDB
Ich möchte den Wert in Ruby erhalten
8 Entspricht mehreren Argumenten
10 Entspricht der if-Anweisung
14 Entspricht einem Funktionsausdruck
5 Entspricht priorisierten Klammern
19 Entspricht der Objekterstellung
16 Entspricht dem Methodenaufruf
Versuchen Sie es mit dem Java-Rückgabewert
So kehren Sie durch Wischen zum vorherigen Bildschirm zurück
[Java] So erhalten Sie den Maximalwert von HashMap
Ich möchte die Bildlaufposition von UITableView zurückgeben!
Beim Einfügen von Java in MySQL erhalten Sie Auto_Increment_ID (automatischer Nummerierungswert) als Rückgabewert
Übergeben Sie ein Argument an die Methode und erhalten Sie das Ergebnis der Operation als Rückgabewert
Lassen Sie den Code sprechen anstatt zu kommentieren (möglicherweise Rückgabewert)
Verwendung von Ruby return
18 Entspricht der JSON-ähnlichen Objektdefinition
So geben Sie ein Array für den Rückgabewert / das Rückgabeargument einer Methode in der CORBA IDL-Datei an
So rufen Sie den Hashwert in einem Array in Ruby ab
4 Fügen Sie dem Interpreter println hinzu
Git Einfache Möglichkeit, vor der Änderung in den Status zurückzukehren (vor dem Festschreiben)
Erstellen Sie eine Methode, um den Steuersatz in Java zurückzugeben
[Java] [jackson] Entspricht dem nachfolgenden Komma (nachgestellten Komma) beim Parsen von JSON.
So ändern Sie den Einstellwert von Springboot Hikari CP
20 Entspricht statischen Methodenaufrufen
Senden Sie den Wert des Beschleunigungssensors per UDP von Android an den PC
Ich möchte mehrere Rückgabewerte für das eingegebene Argument zurückgeben
Eingabe in die Java-Konsole
Ich möchte mit Kotlin und Java zum vorherigen Bildschirm zurückkehren!
So zeigen Sie 0 auf der linken Seite des Standardeingabewerts an
Die Rückgabespezifikation von compareTo kann es sich leisten, ohne auf die Referenz zuzugreifen
So geben Sie den Wert aus, wenn sich ein Array im Array befindet
Ersetzen Sie durch einen Wert entsprechend der Übereinstimmung mit einem regulären Java-Ausdruck
[Rails] Lesen Sie das RSS der Site und geben Sie den Inhalt an die Vorderseite zurück
Ich möchte den Wert von Attribute in Selenium of Ruby ändern
So erhöhen Sie den Wert von Map in einer Zeile in Java
Fügen Sie der Datei erweiterte Attribute hinzu
Über die Sprache, die von nun an zu lernen ist
11 Entspricht Vergleichs- und logischen Operatoren
Wechseln Sie dynamisch die Datenbank, zu der eine Verbindung hergestellt werden soll
Verwendung der Methode form_with
Übergeben Sie das Gebietsschema i18n an JavaScript
[java8] Um die Stream-API zu verstehen
So finden Sie den durchschnittlichen Winkel
Verwendung der Wrapper-Klasse
Ich habe versucht, die Methode zu erklären
Willkommen im Sumpf der Java-Bibliotheken! !!
So fügen Sie die Löschfunktion hinzu