[JAVA] Design pattern ~ Interpreter ~

1.First of all

Here is a summary of the ** Interpreter pattern ** in the GoF design pattern.

2. What is the Interpreter pattern?

--The English word Interpreter means ** interpreter **. ――The Interpreter pattern is a method that ** analyzes and expresses the contents of a file written in some format with a program that acts as an "interpreter" **. --The GoF design patterns are classified as ** behavioral design patterns **.

3. Sample class diagram

Interpreter.PNG

4. Sample program

A program that parses the language written in a text file. BNF notation is used in the grammar of the language used in the text to be parsed.

<program> ::= program <command list>
<command list> ::= <command>* end
<command> ::= <repeat command> | <primitive command>
<repeat command> ::= repeat <number> <command list>
<primitive command> ::= go | right | left

--<program> ・ ・ ・ The token program is followed by the command column . --<command list> ・ ・ ・ is repeated 0 or more, followed by token end. --<command> ・ ・ ・ Either the repeat command or the basic command . (| Represents or) --<repeat command> ・ ・ ・ The token repeat is followed by the number of repetitions , followed by the command column . --<primitive command> ・ ・ ・ go or right or left.

4-1. Context class

A class that represents the context for parsing.

Context.java


import java.util.StringTokenizer;

public class Context {

	private StringTokenizer tokenizer;
	private String currentToken;

	public Context(String text) {
		tokenizer = new StringTokenizer(text);
		nextToken();
	}

	public String nextToken() {
		if (tokenizer.hasMoreTokens()) {
			currentToken = tokenizer.nextToken();
		} else {
			currentToken = null;
		}
		return currentToken;
	}

	public String currentToken() {
		return currentToken;
	}

	public void skipToken(String token) throws Exception {
		if (!token.equals(currentToken)) {
			throw new Exception("Warning: " + token + " is expected, but " + currentToken + " is found.");
		}
		nextToken();
	}

	public int currentNumber() throws Exception {
		int number = 0;
		try {
			number = Integer.parseInt(currentToken);
		} catch (NumberFormatException e) {
			throw new Exception("Warning: " + e);
		}
		return number;
	}
}

4-2. Node class

A class that is a "node" in the syntax tree.

Node.java


public abstract class Node {
	public abstract void parse(Context context) throws Exception;
}

4-3. ProgramNode class

This class corresponds to .

ProgramNode.java


// <program> ::= program <command list>
public class ProgramNode extends Node {

	private Node commandListNode;

	public void parse(Context context) throws Exception {
		context.skipToken("program");
		commandListNode = new CommandListNode();
		commandListNode.parse(context);
	}

	public String toString() {
		return "[program " + commandListNode + "]";
	}
}

4-4. CommandNode class

This class corresponds to .

CommandNode.java


// <command> ::= <repeat command> | <primitive command>
public class CommandNode extends Node {

	private Node node;

	public void parse(Context context) throws Exception {
		if (context.currentToken().equals("repeat")) {
			node = new RepeatCommandNode();
			node.parse(context);
		} else {
			node = new PrimitiveCommandNode();
			node.parse(context);
		}
	}

	public String toString() {
		return node.toString();
	}
}

4-5. RepeatCommandNode class

This class corresponds to .

RepeatCommandNode.java


// <repeat command> ::= repeat <number> <command list>
public class RepeatCommandNode extends Node {

	private int number;
	private Node commandListNode;

	public void parse(Context context) throws Exception {
		context.skipToken("repeat");
		number = context.currentNumber();
		context.nextToken();
		commandListNode = new CommandListNode();
		commandListNode.parse(context);
	}

	public String toString() {
		return "[repeat " + number + " " + commandListNode + "]";
	}
}

4-6. CommandListNode class

This class corresponds to .

CommandListNode.java


import java.util.ArrayList;

// <command list> ::= <command>* end
public class CommandListNode extends Node {

	private ArrayList list = new ArrayList();

	public void parse(Context context) throws Exception {
		while (true) {
			if (context.currentToken() == null) {
				throw new Exception("Missing 'end'");
			} else if (context.currentToken().equals("end")) {
				context.skipToken("end");
				break;
			} else {
				Node commandNode = new CommandNode();
				commandNode.parse(context);
				list.add(commandNode);
			}
		}
	}

	public String toString() {
		return list.toString();
	}
}

4-7. PrimitiveCommandNode class

This class corresponds to .

PrimitiveCommandNode.java


// <primitive command> ::= go | right | left
public class PrimitiveCommandNode extends Node {

	private String name;

	public void parse(Context context) throws Exception {
		name = context.currentToken();
		context.skipToken(name);
		if (!name.equals("go") && !name.equals("right") && !name.equals("left")) {
			throw new Exception(name + " is undefined");
		}
	}

	public String toString() {
		return name;
	}
}

4-8. Text to be parsed

The text to be parsed.

program.txt


program end
program go end
program go right go right go right go right end
program repeat 4 go right end end
program repeat 4 repeat 3 go right go left end right end end

4-9. Main class

This class performs the main processing.

Main.java


import java.io.BufferedReader;
import java.io.FileReader;

public class Main {
	public static void main(String[] args) {
		try {
			BufferedReader reader = new BufferedReader(new FileReader("program.txt"));
			String text;
			while ((text = reader.readLine()) != null) {
				System.out.println("text = \"" + text + "\"");
				Node node = new ProgramNode();
				node.parse(new Context(text));
				System.out.println("node = " + node);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

4-10. Execution result

text = "program end"
node = [program []]
text = "program go end"
node = [program [go]]
text = "program go right go right go right go right end"
node = [program [go, right, go, right, go, right, go, right]]
text = "program repeat 4 go right end end"
node = [program [[repeat 4 [go, right]]]]
text = "program repeat 4 repeat 3 go right go left end right end end"
node = [program [[repeat 4 [[repeat 3 [go, right, go, left]], right]]]]

5. Benefits

The Interpreter pattern makes it easy to add or change rules. One of the characteristics of the Interpreter pattern is that "one rule is represented by one class". In other words, if you want to add a new rule, all you have to do is add a subclass of the Node class. Also, if you modify the rule, you only need to modify the subclass of the Node class.

  1. GitHub

7. List of design patterns

-** GoF design pattern summary **

8. Reference

This article and sample program were created based on the following books.

-** Introduction to design patterns learned in Java language **

It was very easy to understand and I learned a lot. Thank you. The detailed explanations of the design patterns and sample programs are written, so please take a look at the books as well.

Recommended Posts

Design pattern ~ Interpreter ~
Design pattern ~ Visitor ~
Java design pattern
Design pattern ~ Proxy ~
Design pattern ~ State ~
Design pattern ~ Strategy ~
Design pattern ~ Singleton ~
Design pattern ~ Composite ~
Design pattern (2): Builder
Design pattern (1): AbstractFactory
Design pattern ~ Command ~
Design pattern ~ Iterator ~
Design pattern ~ Bridge ~
Design pattern ~ Mediator ~
Design pattern ~ Decorator ~
Design pattern ~ Observer ~
Design pattern ~ Prototype ~
Design pattern ~ Memento ~
Design pattern ~ Adapter ~
Design pattern ~ Flyweight ~
C ++ design pattern (TemplateMethod pattern)
Design pattern ~ Factory Method ~
Design pattern ~ Abstract Factory ~
GoF design pattern summary
Design pattern ~ Template Method ~
Java design pattern summary
Design pattern ~ Chain of Responsibility ~
[Design pattern] Java core library
Ruby design pattern template method pattern memo
C # chewed design pattern: Template Method
Application example of design pattern (No. 1)
Java beginner design pattern (Factory Method pattern)
Prototype pattern
Mediator pattern
Iterator pattern
Composite pattern
Observer Pattern
Builder pattern
Bridge Pattern
Command Pattern
Builder Pattern
Strategy pattern
Iterator Pattern
Visitor pattern
Adapter Pattern
Proxy Pattern
Strategy Pattern
Composite Pattern
Singleton Pattern
Singleton pattern
Prototype Pattern
[Design pattern] Common logic with Template Method
Facade Pattern
Decorator pattern
Flyweight Pattern
Decorator Pattern
Mediator Pattern
Facade pattern
Visitor Pattern
Bridge pattern
PrintObserver "Observer Design Pattern: Description and Implementation Example"