10 Corresponds to if statement

Introduction

Corresponding to the return value of the function in the previous article. Next, I would like to support if statements.

What you want to do with if statement support

Make sure you want to do it easily. For example, if you have a program like the one below, the first println () will output 3 and The next println () aims to print 4. For the sake of simplicity, the authenticity of the if statement is determined by assuming that non-zero is true and 0 is false.

function f(a) {
  if (a) {
    return 3
  } else {
    return 4
  }
}
println(f(1))
println(f(0))

How to implement

We will consider how to implement it in the order of parser and interpreter. Lexical analysis (Lexer) is not changed.

How to implement parsing

For how to implement if statement parsing, see [Function definition parsing](http://qiita.com/quwahara/items/be71bac4b4359f5e6727#%E6%A7%8B%E6%96] implemented in the previous article. % 87% E8% A7% A3% E6% 9E% 90parser% E3% 81% AE% E5% AE% 9F% E8% A3% 85% E3% 81% AE% E4% BB% 95% E6% 96% B9 ) Is similar. Since there is a keyword ʻif` at the beginning and the order of appearance of the tokens that follow it is also decided, the tokens are traced and analyzed in order.

How to implement the Interpreter

In the interpreter, the method body (), which executes expressions sequentially, Change to handle if statements. This is because it is easy to handle when there is a return in the if statement.

Try to implement in Java

Move on to implementation. About parser and interpreter Let's take a look at the changes and additions in order.

Parser.java

An implementation of Parser.java. Add a definition of how it works for the meaning of the token. Since ʻif and ʻelse are reserved words, I added them where there is <-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", "if", "else" });  // <-- Update
    }

It is a change of the part to be analyzed. Added a function call to parse ifwhere<-Add` is.

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")) {
            token.kind = "ret";
            if (!token().kind.equals("eob")) {
                token.left = expression(0);
            }
            return token;
        } else if (token.kind.equals("ident") && token.value.equals("if")) {    // <-- Add
            return if_(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.");
        }
    }

It is a change of the part to be analyzed. Added the method ʻif_ ()to parse if statements. The analysis result of the if statement is summarized in the argument token. To summarize, we are adding field variables to the Token class. The added field variable isblockOfElse. Added to hold the processing block on the ʻelse side of the if statement. The type is List \ <Token >.

The processing in the ʻif_ ()method is designed to trace the tokens in the if statement definition in order. First, assigning totoken.kind determines the meaning of the token to ʻif. Then it consumes the ( at the beginning of the conditional statement. The ʻexpression () method parses the conditional statement of the if statement and holds it in token.left. Then it consumes the end )` of the conditional statement.

Analysis of processing blocks. If there is a { at the beginning of the block, it is surrounded by {tokens and} tokens. Call the body () method that parses the processing block and hold it in token.block. If there is no { at the beginning of the block, it is considered that there is only one processing block and it is stored in token.block.

The analysis of the processing block on the else side is almost the same.

Parser.java


    private Token if_(Token token) throws Exception {
        token.kind = "if";
        consume("(");
        token.left = expression(0);
        consume(")");
        if (token().value.equals("{")) {
            token.block = body();
        } else {
            token.block = new ArrayList<Token>();
            token.block.add(expression(0));
        }
        if (token().value.equals("else")) {
            consume("else");
            if (token().value.equals("{")) {
                token.blockOfElse = body();
            } else {
                token.blockOfElse = new ArrayList<Token>();
                token.blockOfElse.add(expression(0));
            }
        }
        return token;
    }

Parses the processing block enclosed by the { token and the } token. Even in the part that parses the processing block of the func () method I was doing the same thing, so I changed it to call this method.

Parser.java


    private List<Token> body() throws Exception {
        consume("{");
        List<Token> block = block();
        consume("}");
        return block;
    }

Interpreter.java

An implementation of Interpreter.java.

A change to the method body () that executes expressions sequentially.

Added a method call to process if statement to // <-Add. So that if return is called in the processing block of the if statement, it can return to the upper level. Determines if ret [0] is true and aborts thebody ()method.

Interpreter.java


    public Object body(List<Token> body, boolean[] ret) throws Exception {
        for (Token exprs : body) {
            if (exprs.kind.equals("if")) {      // <-- Add
                Object val = if_(exprs, ret);
                if (ret != null && ret[0]) {
                    return val;
                }
            } else 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;
    }

A ʻif_ ()method that executes an if statement. token.left holds the conditional expression. The ʻisTrue () method determines if the conditional expression is true. If the conditional expression is true, execute token.block. If false, run token.blockOfElse.

Interpreter.java


    public Object if_(Token token, boolean[] ret) throws Exception {
        List<Token> block;
        if (isTrue(token.left)) {
            block = token.block;
        } else {
            block = token.blockOfElse;
        }
        if (block != null) {
            return body(block, ret);
        } else {
            return null;
        }
    }

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

The program below using the above implementation

function f(a) {
  if (a) {
    return 3
  } else {
    return 4
  }
}
println(f(1))
println(f(0))

To print 3 and 4 to standard output in sequence.

Interpreter.java


    public static void main(String[] args) throws Exception {
        String text = "";
        text += "function f(a) {";
        text += "  if (a) {";
        text += "    return 3";
        text += "  } else {";
        text += "    return 4";
        text += "  }";
        text += "}";
        text += "println(f(1))";
        text += "println(f(0))";
        List<Token> tokens = new Lexer().init(text).tokenize();
        List<Token> blk = new Parser().init(tokens).block();
        new Interpreter().init(blk).run();
        // --> 3
        // --> 4
    }

That's all for the implementation. Thank you very much.

in conclusion

The full source is available here.

Calc https://github.com/quwahara/Calc/tree/article-10-if-r2/Calc/src/main/java

There is a continuation article.

** Corresponds to comparison and logical operators ** http://qiita.com/quwahara/items/162d01c5af7c69cfa0ed

Recommended Posts

10 Corresponds to if statement
12 Corresponds to the while statement
if statement
Corresponds to 17 arrays
Corresponds to Scope
Corresponds to 15 strings
8 Corresponds to multiple arguments
How to write an if statement to improve readability-java
Studying Java-Part 10-if statement
14 Corresponds to function expressions
5 Corresponds to prioritizing parentheses
19 Corresponds to object creation
16 Corresponds to method invocation
If Pikachu counts up to 100
About for statement and if statement
9 Corresponds to the return value
18 Corresponds to JSON-like object definitions
Points for refactoring (if statement)
[Ruby] Introduction to Ruby Error statement
20 Corresponds to static method invocation
[Ruby] problem with if statement
[Ruby] conditional branch if statement
11 Corresponds to comparison and logical operators
Java study # 4 (conditional branching / if statement)
About if statement and branch processing
to_ ○
[Introduction to Java] Conditional branching (if statement, if-else statement, else if statement, ternary operator, switch statement)
[Ruby] I tried to diet the if statement code with the ternary operator
If you dare to compare Integer with "==" ...
Java, if statement / switch statement starting from beginner
[Ruby] if statement concept of conditional expression
What to do if you install Ubuntu
Basics of java basics ② ~ if statement and switch statement ~