The interpreter pattern is the behavior pattern of a class. Given a language, the interpreter pattern can define a representation of its grammar and provide an interpreter at the same time. The client can use this interpreter to interpret sentences in the language.

Structure of the interpreter schema

The roles involved in the pattern are as follows: (1) Abstract Expression role: Declares an abstract interface that all concrete Expression roles need to implement. This interface is primarily a interpret() method, called the interpret operation. (2) Terminal Expression role: it implements the interface required by the abstract Expression role, mainly a interpret() method; Each terminator in a grammar has a concrete terminating expression corresponding to it. For example, there is a simple formula R=R1+R2, in which R1 and R2 are terminal expressions, and the corresponding interpreter that parses R1 and R2 is the terminal expression. (3) Nonterminal Expression role: Every rule in a grammar requires a specific non-terminal expression, which is usually an operator or other keyword in the grammar. For example, in R=R1+R2, “+” is a non-terminal expression, and the interpreter that parses” +” is a non-terminal expression. (4) Context role: The task of this role is generally used to store the specific values corresponding to each terminator in the grammar, for example, R=R1+R2, we assign R1 100, R2 200. This information needs to be stored in the environment role, and in many cases it is sufficient to use a Map to act as the environment role.

In order to illustrate the implementation of the interpreter pattern, here is a simple grammar and the corresponding implementation of the interpreter pattern, which is to simulate the Java language for Boolean expressions to operate and evaluate.

In this language terminators are Boolean variables, the constants true and false. Non-terminal expressions contain Boolean expressions such as the operators AND, OR, and not. The simple grammar is as follows:

Expression ::= Constant | Variable | Or | And | Not

And ::= Expression ‘And’ Expression

Or: : = Expression ‘Or’ Expression

Not: : = ‘Not’ Expression

Variable::= Any identifier

Constant ::= ‘true’ | ‘false’

The structure of the interpreter pattern looks like this:

Abstract Expression role

Public abstract Class Expression {/** * This method interprets any given Expression, depending on the Context */ public abstract Boolean interpret(Context CTX); Public Boolean equals(Object obj); public Boolean equals(Object obj); /** * Return the hash code of the expression */ public abstract int hashCode(); Public toString(); public toString(); }Copy the code

A Constant object represents a Boolean Constant

public class Constant extends Expression{
    
    private boolean value;

    public Constant(boolean value){
        this.value = value;
    }
    
    @Override
    public boolean equals(Object obj) {
        if(obj != null && obj instanceof Constant){
            return this.value == ((Constant)obj).value;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return this.toString().hashCode();
    }

    @Override
    public boolean interpret(Context ctx) {
        
        return value;
    }

    @Override
    public String toString() {
        return new Boolean(value).toString();
    }
    
}
Copy the code

A Variable object represents a named Variable

public class Variable extends Expression {

    private String name;

    public Variable(String name){
        this.name = name;
    }
    @Override
    public boolean equals(Object obj) {
        
        if(obj != null && obj instanceof Variable)
        {
            return this.name.equals(
                    ((Variable)obj).name);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return this.toString().hashCode();
    }

    @Override
    public String toString() {
        return name;
    }

    @Override
    public boolean interpret(Context ctx) {
        return ctx.lookup(this);
    }

}
Copy the code

The And class that represents the logical And operation, representing the operation by which two Boolean expressions give a new Boolean expression through the logical And operation

public class And extends Expression {

    private Expression left,right;
    
    public And(Expression left , Expression right){
        this.left = left;
        this.right = right;
    }
    @Override
    public boolean equals(Object obj) {
        if(obj != null && obj instanceof And)
        {
            return left.equals(((And)obj).left) &&
                right.equals(((And)obj).right);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return this.toString().hashCode();
    }

    @Override
    public boolean interpret(Context ctx) {
        
        return left.interpret(ctx) && right.interpret(ctx);
    }

    @Override
    public String toString() {
        return "(" + left.toString() + " AND " + right.toString() + ")";
    }

}
Copy the code

The Or class that represents a logical Or operation, representing an operation in which two Boolean expressions give a new Boolean expression through a logical Or operation

public class Or extends Expression {
    private Expression left,right;

    public Or(Expression left , Expression right){
        this.left = left;
        this.right = right;
    }
    @Override
    public boolean equals(Object obj) {
        if(obj != null && obj instanceof Or)
        {
            return this.left.equals(((Or)obj).left) && this.right.equals(((Or)obj).right);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return this.toString().hashCode();
    }

    @Override
    public boolean interpret(Context ctx) {
        return left.interpret(ctx) || right.interpret(ctx);
    }

    @Override
    public String toString() {
        return "(" + left.toString() + " OR " + right.toString() + ")";
    }

}
Copy the code

The Not class, which represents a logical Not operation, represents an operation by which a Boolean expression gives a new Boolean expression through a logical Not operation

public class Not extends Expression { private Expression exp; public Not(Expression exp){ this.exp = exp; } @Override public boolean equals(Object obj) { if(obj ! = null && obj instanceof Not) { return exp.equals( ((Not)obj).exp); } return false; } @Override public int hashCode() { return this.toString().hashCode(); } @Override public boolean interpret(Context ctx) { return ! exp.interpret(ctx); } @Override public String toString() { return "(Not " + exp.toString() + ")"; }}Copy the code

The Context class defines a mapping from variables to Booleans

public class Context { private Map<Variable,Boolean> map = new HashMap<Variable,Boolean>(); public void assign(Variable var , boolean value){ map.put(var, new Boolean(value)); } public boolean lookup(Variable var) throws IllegalArgumentException{ Boolean value = map.get(var); if(value == null){ throw new IllegalArgumentException(); } return value.booleanValue(); }}Copy the code

The client class

public class Client { public static void main(String[] args) { Context ctx = new Context(); Variable x = new Variable("x"); Variable y = new Variable("y"); Constant c = new Constant(true); ctx.assign(x, false); ctx.assign(y, true); Expression exp = new Or(new And(c,x) , new And(y,new Not(x))); System.out.println("x=" + x.interpret(ctx)); System.out.println("y=" + y.interpret(ctx)); System.out.println(exp.toString() + "=" + exp.interpret(ctx)); }}Copy the code

reference

www.cnblogs.com/java-my-lif…