This article describes the implementation of Java to define a simple language function based on the interpreter pattern. Share it for your reference, as follows:
A pattern definition
Interpreter pattern: It is to give a grammatical representation of a language and define an interpreter to interpret sentences in the language. The interpreter pattern describes how to interpret these statements using pattern design after a simple grammar.
Examples of the second mode
1 Pattern Analysis
We designed a language to illustrate this pattern ourselves
(1) The language is case sensitive (2) The language starts with PROGRAM and ends with END (3) PRINTLN means printing a line and breaking it (4) Use FOR…FROM…TO…END means loop
The example language content is as follows:
PROGRAM PRINTLN start... FOR i FROM 90 TO 100 PRINTLN i END PRINTLN end...END
The meaning of this sentence is: first print the line break with "start...", then cycle through the line break with "90", "91", ... "100", and finally print the line break with "end...".
2 This language explains the tree structure
3 Activity diagram of the language interpreter
4 Code Examples
4.1 Create a context environment - Context
package com.demo.interpreter.context;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.StringTokenizer;/** * Context environment* * @author * */public class Context { // The text content to be parsed private final StringTokenizer stringTokenizer; // The current command private String currentToken; // Used to store dynamically changing information content private final Map<String, Object> map = new HashMap<String, Object>(); /** * Constructor sets parsing content* * @param text */ public Context(String text) { // Use spaces to separate the text to be parsed this.stringTokenizer = new StringTokenizer(text); } /** * Parsing text*/ public String next() { if (this.stringTokenizer.hasMoreTokens()) { currentToken = this.stringTokenizer.nextToken(); } else { currentToken = null; } return currentToken; } /** * Determine whether the command is correct* * @param command * @return */ public boolean equalsWithCommand(String command) { if (command == null || !command.equals(this.currentToken)) { return false; } return true; } /** * Get the current command content* * @return */ public String getCurrentToken() { return this.currentToken; } /** * Get the content of the node* * @return */ public String getTokenContent(String text) { String str = text; if (str != null) { // Replace the dynamically changing content in the map and return Iterator<String> // Replace the dynamically changing content in the map and return Iterator<String> iterator = this.map.keySet().iterator(); while (iterator.hasNext()) { String key = iterator.next(); Object obj = map.get(key); str = str.replaceAll(key, obj.toString()); } } return str; } public void put(String key, Object value) { this.map.put(key, value); } public void clear(String key) { this.map.remove(key); }}4.2 Expression interface - IExpressions
package com.demo.interpreter.express;import com.demo.interpreter.context.Context;/** * * Expression interface* * @author * */public interface IExpressions { /** * parsing* * @param context */ public void parse(Context context); /** * Execution method* * @param context */ public void interpret();}4.3 Main expression - ProgramExpression
package com.demo.interpreter.express;import com.demo.interpreter.context.Context;/** * program expression* * @author * */public class ProgramExpression implements IExpressions { // context environment private final Context context; // current command private final static String COMMAND = "PROGRAM"; // store the next expression reference private IExpressions expressions; /** * Constructor passes the content to be parsed into * * @param text */ public ProgramExpression(String text) { this.context = new Context(text); this.parse(this.context); } @Override public void parse(Context context) { // Get the first command node this.context.next(); } /** * Implementation explanation method*/ @Override public void interpret() { // Determine whether it starts with PROGRAM if (!this.context.equalsWithCommand(COMMAND)) { System.out.println("The '" + COMMAND + "' is Excepted For Start!"); } else { // Start this.context.next() with PROGRAM; this.expressions = new ListExpression(); this.expressions.parse(this.context); // ListExpression expression starts parsing this.expressions.interpret(); } }}4.4 List Expression - ListExpression
package com.demo.interpreter.express;import java.util.ArrayList;import java.util.Iterator;import com.demo.interpreter.context.Context;/** * List expression* * @author * */public class ListExpression implements IExpressions { private Context context; private final ArrayList<IExpressions> list = new ArrayList<IExpressions>(); /** * Constructor passes the context to be parsed into * * @param context */ public void parse(Context context) { this.context = context; // In ListExpression parsing expression, loop to interpret each word in the statement until the terminator expression or exception exits while (true) { if (this.context.getCurrentToken() == null) { // Get the current node. If null, it means that the END expression is missing System.out.println("Error: The Expersion Missing 'END'! "); break; } else if (this.context.equalsWithCommand("END")) { this.context.next(); // parsing normally ends break; } else { // Create Command expression IExpressions expressions = new CommandExpersion(this.context); // Add to list.add(expressions); } } } /** * Implement explanation method*/ @Override public void interpret() { // Loop the explanation of each expression in the list list to execute Iterator<IExpressions> iterator = list.iterator(); while (iterator.hasNext()) { (iterator.next()).interpret(); } }}4.5 Command Expression - CommandExpersion
package com.demo.interpreter.express;import com.demo.interpreter.context.Context;/** * Command expression* * @author * */public class CommandExpersion implements IExpressions { private final Context context; private IExpressions expressions; /** * Construct method passes the context to be parsed into * * @param context */ public CommandExperssion(Context context) { this.context = context; this.parse(this.context); } public void parse(Context context) { // judging the current command category, only distinguish For and the original command if (this.context.equalsWithCommand("FOR")) { // Create For expression for parsing expressions = new ForExpression(this.context); } else { // Create original command expression for content parsing expressions = new PrimitiveExpression(this.context); } } /** * Parsing content*/ @Override public void interpret() { // Parsing content this.expressions.interpret(); }}4.6 Loop expression - ForExpression
package com.demo.interpreter.express;import com.demo.interpreter.context.Context;/** * For expression* * @author * */public class ForExpression implements IExpressions { private final Context context; // Store the current index key value private String variable; // Store the start position of the loop private int start_index; // Store the end position of the loop private int end_index; private IExpressions expressions; /** * Constructor passes the context to be parsed into * * @param context */ public ForExpression(Context context) { this.context = context; this.parse(this.context); } /** * Parsing expression*/ @Override public void parse(Context context) { // First get the current node this.context.next(); while (true) { // Judge the node if (this.context.equalsWithCommand("FROM")) { // Set the start index content String nextStr = this.context.next(); try { this.start_index = Integer.parseInt(nextStr); } catch (Exception e) { System.out .println("Error: After 'FROM' Expression Exist Error!Please Check the Format Of Expression is Correct!"); break; } // Get the next node this.context.next(); } else if (this.context.equalsWithCommand("TO")) { // Set the end index content String nextStr = this.context.next(); try { this.end_index = Integer.parseInt(nextStr); } catch (Exception e) { System.out .println("Error: After 'TO' Expression Exist Error!Please Check the Format Of Expression is Correct!"); } this.context.next(); break; } else { // Set the content of the current index variable if (this.variable == null) { this.variable = this.context.getCurrentToken(); } // Get the next node this.context.next(); } } // Create a list expression this.expressions = new ListExpression(); this.expressions.parse(this.context); } /** * Implement the explanation method*/ @Override public void interpret() { // Create a command expression for (int x = this.start_index; x <= this.end_index; x++) { // Set the variable content this.context.put("" + this.variable, x); // Execute the explanation method this.expressions.interpret(); } // Remove the temporary variable content used this.context.clear("" + this.variable); }}4.7 Basic expressions - PrimitiveExpression
package com.demo.interpreter.express;import com.demo.interpreter.context.Context;/** * The most basic expression* * @author * */public class PrimitiveExpression implements IExpressions { private Context context; // node name private String tokenName; // text content private String text; /** * Constructor passes the context to be parsed into * * @param context */ public PrimitiveExpression(Context context) { this.parse(context); } @Override public void parse(Context context) { this.context = context; this.tokenName = this.context.getCurrentToken(); this.context.next(); if ("PRINTLN".equals(this.tokenName)) { this.text = this.context.getCurrentToken(); this.context.next(); } } /** * Implementation explanation method*/ @Override public void interpret() { // First get the current node content if ("PRINTLN".equals(tokenName)) { // Obtain content information // Print content System.out.println(this.context.getTokenContent(this.text)); } }}4.8 Let the language interpreter start working - Client
package com.demo.interpreter;import com.demo.interpreter.express.IExpressions;import com.demo.interpreter.express.ProgramExpression;/** * Main application* * @author * */public class Client { /** * @param args */ public static void main(String[] args) { // myida language statement String str = "PROGRAM PRINTLN start... FOR i FROM 90 TO 100 PRINTLN i END PRINTLN end... END"; System.out.println("str:" + str); // Create PROGRAM expression IExpressions expressions = new ProgramExpression(str); // Explain the execution of expressions.interpret(); }}5 Running results
str:PROGRAM PRINTLN start... FOR i FROM 90 TO 100 PRINTLN i END PRINTLN end... END
Start...
90
91
92
93
94
95
96
97
98
99
100
end...
Three design principles
1 "Open-Close" principle
2 The principle of closed change
Four usage occasions
(1) A specific type of problem occurs at a high frequency, and business rules change frequently, and similar situations occur repeatedly.
(2) Business rules are not too complicated and cumbersome, and it is easier to abstract grammatical rules.
(3) Efficiency is not a main factor considered in software systems.
Five interpreter mode static class diagram
For more Java-related content, readers who are interested in this site can view the topics: "Introduction and Advanced Tutorial on Java Object-Oriented Programming", "Tutorial on Java Data Structure and Algorithm", "Summary of Java Operation DOM Node Skills", "Summary of Java File and Directory Operation Skills" and "Summary of Java Cache Operation Skills"
I hope this article will be helpful to everyone's Java programming.