[JAVA] 11 Entspricht Vergleichs- und logischen Operatoren

Einführung

Im vorherigen Artikel Unterstützt if-Anweisungen. Da es keinen Operator gibt, der in der bedingten Anweisung der if-Anweisung angegeben werden kann, möchte ich ihn unterstützen.

Was Sie mit der Korrespondenz von Vergleichsoperatoren und logischen Operatoren tun möchten

Stellen Sie sicher, dass Sie es einfach machen möchten. Zum Beispiel gibt es das folgende Programm. Da die Ungleichungszahl in der ersten Zeile korrekt ist, wird "1" ausgegeben, die die Wahrheit darstellt. Da die Ungleichungszahl mit der gleichen Zahl in der zweiten Zeile falsch ist, wird "0" ausgegeben, was falsch anzeigt. Die dritte Zeile gibt "1" aus, da das Ergebnis der logischen Operation wahr ist. Im Beispiel wird es nur ausgegeben, es kann jedoch als bedingter Ausdruck in der if-Anweisung beschrieben werden.

println(10 > 1)
println(5 <= 1)
println(!(1 == 2) && (3 != 4))

Wie zu implementieren

Informationen zur Implementierung finden Sie unter Implementierung der Syntaxanalyse und Implementierung des Interpreters. Deswegen Bitte beziehen Sie sich darauf, da es nichts Neues gibt.

Versuchen Sie, in Java zu implementieren

Fahren Sie mit der Implementierung fort. Informationen zur Phrasenanalyse (Lexer), Syntaxanalyse (Parser), Interpreter (Interpreter) Schauen wir uns die Änderungen und Ergänzungen der Reihe nach an.

Lexer.java

Eine Implementierung von Lexer.java. Entspricht dem hinzugefügten Operator. Bisher waren alle Operatoren Ein-Buchstaben-Operatoren, aber es ist möglicherweise neu, dass auch Zwei-Buchstaben-Operatoren zugenommen haben.

Lexer.java


    private boolean isSignStart(char c) {
        return c == '=' || c == '+' || c == '-' || c == '*' || c == '/' || c == '!' || c == '<' || c == '>' || c == '&'
                || c == '|';
    }

    private Token sign() throws Exception {
        Token t = new Token();
        t.kind = "sign";
        char c1 = next();
        char c2 = (char) 0;
        if (!isEOT()) {
            if (c1 == '=' || c1 == '!' || c1 == '<' || c1 == '>') {
                if (c() == '=') {
                    c2 = next();
                }
            } else if (c1 == '&') {
                if (c() == '&') {
                    c2 = next();
                }
            } else if (c1 == '|') {
                if (c() == '|') {
                    c2 = next();
                }
            }
        }
        String v;
        if (c2 == (char) 0) {
            v = Character.toString(c1);
        } else {
            v = Character.toString(c1) + Character.toString(c2);
        }
        t.value = v;
        return t;
    }

Parser.java

Eine Implementierung von Parser.java. Fügen Sie eine Definition hinzu, wie es für die Bedeutung des Tokens funktioniert. Ein neuer Operator wurde von <-Add hinzugefügt. Da ! Ein einzelner Termoperator ist, wird er zu <-Update hinzugefügt.

Parser.java


    public Parser() {
        degrees = new HashMap<>();
        degrees.put("(", 80);
        degrees.put("*", 60);
        degrees.put("/", 60);
        degrees.put("+", 50);
        degrees.put("-", 50);
        degrees.put("==", 40); // <-- Add
        degrees.put("!=", 40);
        degrees.put("<", 40);
        degrees.put("<=", 40);
        degrees.put(">", 40);
        degrees.put(">=", 40);
        degrees.put("&&", 30);
        degrees.put("||", 30);
        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[] { "+", "-", "!" });                 // <-- Update
        reserved = Arrays.asList(new String[] { "function", "return", "if", "else" });
    }

Interpreter.java

Eine Implementierung von Interpreter.java.

Da es für die Methode praktisch ist, zu beurteilen, ob der bedingte Ausdruck wahr ist, haben wir die Vielfalt durch verschiedene Arten von Argumenten hinzugefügt.

Interpreter.java


    public boolean isTrue(Token token) throws Exception {
        return isTrue(value(expression(token)));
    }

    public boolean isTrue(Integer value) throws Exception {
        return 0 != value;
    }

In dieser Sprache werden boolesche Werte durch Ganzzahlen dargestellt. Bereiten Sie daher eine Methode vor, um den logischen Werttyp in eine Ganzzahl zu konvertieren. True wird in "1" umgewandelt.

Interpreter.java


    public Integer toInteger(boolean b) {
        return b ? 1 : 0;
    }

Eine Methode, die einen mononomischen Operator ausführt. Logische Ablehnung zu <-Add hinzugefügt.

Interpreter.java


    public Object unaryCalc(Token expr) throws Exception {
        Integer left = value(expression(expr.left));
        if (expr.value.equals("+")) {
            return left;
        } else if (expr.value.equals("-")) {
            return -left;
        } else if (expr.value.equals("!")) { // <-- Add
            return toInteger(!isTrue(left));
        } else {
            throw new Exception("Unknown sign for unary calc");
        }
    }

Eine Methode, die einen binären Operator ausführt. Ab <-Add fügen wir eine neue arithmetische Implementierung hinzu.

Interpreter.java


    public Object calc(Token expr) throws Exception {
        Integer left = value(expression(expr.left));
        Integer right = value(expression(expr.right));
        if (expr.value.equals("+")) {
            return left + right;
        } else if (expr.value.equals("-")) {
            return left - right;
        } else if (expr.value.equals("*")) {
            return left * right;
        } else if (expr.value.equals("/")) {
            return left / right;
        } else if (expr.value.equals("==")) { // <-- Add
            return toInteger(left == right);
        } else if (expr.value.equals("!=")) {
            return toInteger(left != right);
        } else if (expr.value.equals("<")) {
            return toInteger(left < right);
        } else if (expr.value.equals("<=")) {
            return toInteger(left <= right);
        } else if (expr.value.equals(">")) {
            return toInteger(left > right);
        } else if (expr.value.equals(">=")) {
            return toInteger(left >= right);
        } else if (expr.value.equals("&&")) {
            return toInteger(isTrue(left) && isTrue(right));
        } else if (expr.value.equals("||")) {
            return toInteger(isTrue(left) || isTrue(right));
        } else {
            throw new Exception("Unknown sign for Calc");
        }
    }

Das folgende Programm verwendet die obige Implementierung

println(10 > 1)
println(5 <= 1)
println(!(1 == 2) && (3 != 4))

Wird ausgeführt und "1", "0" und "1" werden an die Standardausgabe ausgegeben.

Interpreter.java


    public static void main(String[] args) throws Exception {
        String text = "";
        text += "println(10 > 1)";
        text += "println(5 <= 1)";
        text += "println(!(1 == 2) && (3 != 4))";
        List<Token> tokens = new Lexer().init(text).tokenize();
        List<Token> blk = new Parser().init(tokens).block();
        new Interpreter().init(blk).run();
        // --> 1
        // --> 0
        // --> 1
    }

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-11-compare-r2/Calc/src/main/java

Es gibt einen Folgeartikel.

** Entspricht der while-Anweisung ** http://qiita.com/quwahara/items/36f6704ae9c756240068

Recommended Posts

11 Entspricht Vergleichs- und logischen Operatoren
Dinge, die beim Kombinieren von if-Anweisungen und logischen Operatoren zu beachten sind
17 Entspricht einem Array
Entspricht dem Geltungsbereich
Entspricht 15 Zeichenfolgen
8 Entspricht mehreren Argumenten
[Java] Vergleich von Zeichenketten und && und ||
Über die Auswertung logischer Operatoren
10 Entspricht der if-Anweisung
[Ruby] Schwierigkeiten beim Refactoring logischer Operatoren (Genauigkeit und Lesbarkeit)
14 Entspricht einem Funktionsausdruck
5 Entspricht priorisierten Klammern
19 Entspricht der Objekterstellung
16 Entspricht dem Methodenaufruf
Grundlegende Bediener und Operationen
9 Entspricht dem Rückgabewert
12 Entspricht der while-Anweisung
Gradle zum Anfassen und Erinnern
18 Entspricht der JSON-ähnlichen Objektdefinition
20 Entspricht statischen Methodenaufrufen