[JAVA] 9 Correspond à la valeur de retour

introduction

Dans l'article précédent, Supporte plusieurs arguments. Je souhaite continuer à correspondre à la valeur de retour de la fonction.

Ce que vous voulez faire avec la valeur de retour de la fonction

Assurez-vous de vouloir le faire facilement. Par exemple, si vous avez un programme comme celui ci-dessous, la valeur de retour de l'appel de fonction ʻadd3 () est renvoyée et affectée à la variable v`. Nous visons à afficher la valeur «6» de la variable «v» dans la sortie standard.

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

C'est le même que l'article précédent qu'il ne correspond pas à la portée des variables.

Comment mettre en œuvre

Nous examinerons comment l'implémenter dans l'ordre de l'analyse syntaxique (Parser) et de l'interpréteur (Interpreter). L'analyse de phrase (Lexer) n'est pas modifiée.

Comment implémenter l'analyseur

Lors de l'implémentation de l'analyse syntaxique de «return», vous devez faire attention à la syntaxe de «return». La syntaxe de «return» est parfois spécifiée comme valeur de retour, telle que «return 1». Dans certains cas, seul «return» est spécifié et aucune valeur de retour n'est spécifiée. Si la spécification de seulement «return» est correcte dans la syntaxe, Quand return 1 est écrit, Il peut être pris comme syntaxe lorsqu'une valeur de retour est spécifiée, Considérant que «1» est une syntaxe indépendante de «return», Elle peut être considérée comme la syntaxe lorsque la valeur de retour n'est pas spécifiée. Pour résoudre facilement cette situation, nous adopterons une approche bâclée. La méthode est quand le jeton } vient après le jeton return, Considéré comme «return» si aucune valeur de retour n'est spécifiée. Au contraire, si le jeton } ne vient pas, il est considéré comme return lorsque la valeur de retour est spécifiée. L'analyse lorsqu'aucune valeur de retour n'est spécifiée est traitée de la même manière qu'un nom de variable. L'analyse lorsqu'une valeur de retour est spécifiée est traitée de la même manière qu'un opérateur de terme unique tel que «-1».

Comment implémenter Interpreter

L'interpréteur modifie la méthode body (), qui exécute les expressions séquentiellement. S'il s'agit d'un jeton return dans body (), Suspend l'exécution séquentielle et retourne à l'appelant. De plus, return ne peut être appelé que dans une fonction. Il détermine également s'il s'agit d'un appel «return» dans la fonction.

Essayez de mettre en œuvre en Java

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

Parser.java

Une implémentation de Parser.java. Ajoutez une définition de la façon dont cela fonctionne pour la signification du jeton. Puisque return est un mot réservé, J'ai ajouté return là où il y a <-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("=", 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
    }

C'est un changement de pièce à analyser. Ajout d'une instruction if qui analyse return vers où <-Add est. Sauf si le jeton à côté du jeton «return» est «eob», qui représente le type de parenthèse ondulée fermante. Juge comme un «retour» qui renvoie une valeur et contient le jeton qui devient la valeur de retour dans le champ «gauche».

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

Une implémentation d'Interpreter.java.

Ceci est une modification de la méthode body () qui exécute les expressions séquentiellement.

body () était un type void qui ne renvoie pas de valeur de retour, mais il a été changé en type ʻObjectafin de pouvoir renvoyer une valeur de retour. Ajout deboolean [] ret à la signature de body (). reta deux rôles. La première est que si «ret» n'est pas «null», alors «return» est possible. La seconde est que s'il s'agissait de «return», il propagerait à l'appelant qu'il était «return». La raison pour laquelle «ret» est un tableau de type «booléen» est de renvoyer une valeur à l'appelant. Il est utilisé de manière malveillante, pas dans le but d'utiliser le tableau d'origine. Je voulais faciliter le travail comme un argument avec le mot-cléref` en C #.

La première chose dans «for» est de déterminer si le jeton à exécuter séquentiellement est «return». Si ce n'est pas "return", c'est le même processus que le précédent "body ()". S'il s'agit de «retour», on juge si la situation est possible. Remplacez «true» pour dire à l'appelant qu'il devait «retourner» à «ret». Pour un return avec une valeur de retour, exécutez le jeton avec la valeur de retour avec ʻ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;
    }

Ceci est une modification de la méthode ʻinvoke () de la classe DynamicFunc. «<-Update» est le changement. Prend en charge la modification de la signature et de la valeur de retour de la méthode body (). L'affectation d'une instance à l'argument ret indique que la situation peut être renvoyée. La valeur de retour de body ()est utilisée telle quelle comme valeur de retour de ʻ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
        }
    }

Ceci est une modification de la méthode run (). «<-Update» est le changement. Prend en charge la modification de la signature et de la valeur de retour de la méthode body (). La situation où run () est appelé n'est pas à l'intérieur de la fonction. Puisque la situation ne peut pas être «return», l'argument formel «ret» spécifie «null».

Interpreter.java


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

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

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

Pour imprimer la valeur «6» affectée à la variable «v» sur la sortie standard.

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
    }

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-9-return-r2/Calc/src/main/java

Il y a un article de suite.

** Correspond à l'instruction if ** http://qiita.com/quwahara/items/96a68cdee4f2a0452836

Recommended Posts

9 Correspond à la valeur de retour
12 Correspond à l'instruction while
[Rails] Parlez de prêter attention à la valeur de retour de l'endroit
Les méthodes Ruby renvoient la dernière valeur évaluée
Comment passer la valeur à un autre écran
17 Correspond à un tableau
Correspond à la portée
Correspond à 15 chaînes
Comment renvoyer une valeur du modèle au contrôleur en utilisant le protocole [Swift5]
Stocker la valeur de retour du kit SDK AWS dans DynamoDB
Je veux obtenir la valeur en Ruby
8 Correspond à plusieurs arguments
10 Correspond à l'instruction if
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
Essayez la valeur de retour Java
Comment revenir à l'écran précédent par opération Swipe
[Java] Comment obtenir la valeur maximale de HashMap
Je veux retourner la position de défilement de UITableView!
Lors de l'insertion de Java vers MySQL, obtenez Auto_Increment_ID (valeur de numérotation automatique) comme valeur de retour
Passez un argument à la méthode et recevez le résultat de l'opération comme valeur de retour
Laissez le code parler plutôt que commenter (peut-être une valeur de retour)
Comment utiliser le retour Ruby
18 Correspond à la définition d'objet de type JSON
Comment spécifier un tableau pour la valeur de retour / l'argument d'une méthode dans le fichier IDL CORBA
Comment récupérer la valeur de hachage dans un tableau dans Ruby
4 Ajoutez println à l'interpréteur
Git Manière simple de revenir à l'état avant le changement (avant la validation)
Créer une méthode pour renvoyer le taux de taxe en Java
[Java] [jackson] Correspond à la virgule de fin (virgule de fin) lors de l'analyse de JSON.
Comment modifier la valeur de réglage de Springboot Hikari CP
20 Correspond aux appels de méthode statiques
Envoyer la valeur du capteur d'accélération d'Android au PC par UDP
Je souhaite renvoyer plusieurs valeurs de retour pour l'argument saisi
Entrée dans la console Java
Je veux revenir à l'écran précédent avec kotlin et java!
Comment afficher 0 sur le côté gauche de la valeur d'entrée standard
La spécification de retour de compareTo peut se permettre sans aller à la référence
Comment afficher la valeur lorsqu'il y a un tableau dans le tableau
Remplacer par une valeur selon la correspondance avec une expression régulière Java
[Rails] Lire le RSS du site et renvoyer le contenu au premier plan
Je veux changer la valeur de l'attribut dans Selenium of Ruby
Comment incrémenter la valeur de Map sur une ligne en Java
Ajouter des attributs étendus au fichier
À propos de la langue à apprendre à partir de maintenant
11 Correspond aux opérateurs de comparaison et logiques
Basculer dynamiquement la base de données à laquelle se connecter
Comment utiliser la méthode form_with
Passer les paramètres régionaux i18n à JavaScript
[java8] Pour comprendre l'API Stream
Comment trouver l'angle moyen
Comment utiliser la classe wrapper
J'ai essayé d'expliquer la méthode
L'histoire que je voulais développer Zip
Bienvenue dans le marais des bibliothèques Java! !!
Comment ajouter la fonction de suppression