[JAVA] 11 Correspond aux opérateurs de comparaison et logiques

introduction

Dans l'article précédent, Prend en charge les déclarations if. Puisqu'il n'y a aucun opérateur qui peut être spécifié dans l'instruction conditionnelle de l'instruction if, je voudrais la soutenir.

Ce que vous voulez faire avec l'opérateur de comparaison et la correspondance d'opérateur logique

Assurez-vous de vouloir le faire facilement. Par exemple, il existe le programme suivant. Puisque le nombre d'inégalité est correct sur la première ligne, «1» qui représente la vérité est affiché. La deuxième ligne renvoie «0», qui représente le mensonge, car l'inégalité avec le nombre égal est incorrecte. La troisième ligne renvoie «1» car le résultat de l'opération logique est vrai. Dans l'exemple, il s'agit uniquement d'une sortie, mais elle peut être décrite comme une expression conditionnelle dans l'instruction if.

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

Comment mettre en œuvre

Pour savoir comment mettre en œuvre, voir Implémentation de l'analyse syntaxique et Implémentation de l'interpréteur. À cause de ça Veuillez vous y référer car il n'y a rien de nouveau.

Essayez de mettre en œuvre en Java

Passez à la mise en œuvre. À propos de l'analyse de phrases (Lexer), de l'analyse syntaxique (Parser), de l'interpréteur (Interpreter) Jetons un coup d'œil aux modifications et aux ajouts dans l'ordre.

Lexer.java

Une implémentation de Lexer.java. Correspond à l'opérateur ajouté. Jusqu'à présent, tous les opérateurs utilisaient une lettre, mais il est peut-être nouveau que les opérateurs à deux lettres aient également augmenté.

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

Une implémentation de Parser.java. Ajoutez une définition de la façon dont cela fonctionne pour la signification du jeton. Un nouvel opérateur a été ajouté à partir de <-Add. Puisque ! Est un opérateur à terme unique, il est ajouté à <-Update.

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

Une implémentation d'Interpreter.java.

Puisqu'il est pratique pour la méthode de juger si l'expression conditionnelle est vraie, nous avons ajouté de la variété par différents types d'arguments.

Interpreter.java


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

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

Dans ce langage, les valeurs booléennes sont représentées par des entiers, préparez donc une méthode pour convertir le type de valeur logique en entier. True est converti en «1».

Interpreter.java


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

Une méthode qui exécute un opérateur mononome. Ajout d'un refus logique à <-Add.

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");
        }
    }

Une méthode qui exécute un opérateur binaire. À partir de <-Add, nous ajoutons une nouvelle implémentation arithmétique.

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");
        }
    }

Le programme ci-dessous utilisant l'implémentation ci-dessus

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

Est exécuté, et "1", "0" et "1" sont envoyés à la sortie standard.

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
    }

C'est tout pour la mise en œuvre. Merci beaucoup.

en conclusion

La source complète est disponible ici.

Calc https://github.com/quwahara/Calc/tree/article-11-compare-r2/Calc/src/main/java

Il y a un article de suite.

** Correspond à l'instruction while ** http://qiita.com/quwahara/items/36f6704ae9c756240068

Recommended Posts

11 Correspond aux opérateurs de comparaison et logiques
Points à prendre en compte lors de la combinaison d'instructions if et d'opérateurs logiques
17 Correspond à un tableau
Correspond à la portée
Correspond à 15 chaînes
8 Correspond à plusieurs arguments
[Java] Comparaison des chaînes de caractères et && et ||
À propos de l'évaluation des opérateurs logiques
10 Correspond à l'instruction if
[Ruby] Difficulté à refactoriser les opérateurs logiques (précision et lisibilité)
14 Correspond à une expression de fonction
5 Correspond aux parenthèses prioritaires
19 Correspond à la création d'objet
16 Correspond à l'invocation de méthode
Opérateurs et opérations de base
9 Correspond à la valeur de retour
12 Correspond à l'instruction while
Gradle pour toucher et se souvenir
18 Correspond à la définition d'objet de type JSON
20 Correspond aux appels de méthode statiques