设计模式学习笔记——解释器(Interpreter)模式
@(设计模式)[设计模式, 解释器模式, Interpreter]
设计模式学习笔记解释器Interpreter模式
基本介绍解释器案例
类图实现代码
Node抽象类ParseException类ProgramNode类CommandListNode类CommandNode类RepeatCommandNode类PrimitiveCommandNode类Context类测试类运行结果 解释器模式中的角色
AbstractExpression抽象表达式TerminalExpression终结符表达式NonterminalExpression非终结符表达式Context文脉上下文Client请求者类图
基本介绍
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
解释器案例
类图
实现代码
Node抽象类
package com.pc.interpreter.example;
/**
* 节点类
*/
public abstract class Node {
/**
* 解析
*
* @param context 上下文
* @throws ParseException 解析异常
*/
public abstract void parse(Context context)
throws ParseException;
}
ParseException类
package com.pc.interpreter.example;
/**
* 解析异常类
*/
public class ParseException extends Exception {
public ParseException(String msg) {
super(msg);
}
}
ProgramNode类
package com.pc.interpreter.example;
/**
* 程序节点类
* <program> ::= program <command list>
*/
public class ProgramNode extends Node {
/**
* 命令列表节点
*/
private Node commandListNode;
@Override
public void parse(Context context)
throws ParseException {
context.skipToken(
"program");
commandListNode =
new CommandListNode();
commandListNode.parse(context);
}
@Override
public String
toString() {
return "[program " + commandListNode +
"]";
}
}
CommandListNode类
package com.pc.interpreter.example;
import java.util.ArrayList;
/**
* 命令列表节点类
* <command list> ::= <command>* end
*/
public class CommandListNode extends Node {
/**
* 命令列表
*/
private ArrayList list =
new ArrayList();
@Override
public void parse(Context context)
throws ParseException {
while (
true) {
if (context.currentToken() ==
null) {
throw new ParseException(
"Missing 'end'");
}
else if (context.currentToken().equals(
"end")) {
context.skipToken(
"end");
break;
}
else {
Node commandNode =
new CommandNode();
commandNode.parse(context);
list.add(commandNode);
}
}
}
@Override
public String
toString() {
return list.toString();
}
}
CommandNode类
package com.pc.interpreter.example;
/**
* 命令节点类
* <command> ::= <repeat command> | <primitive command>
*/
public class CommandNode extends Node {
/**
* 节点
*/
private Node node;
@Override
public void parse(Context context)
throws ParseException {
if (context.currentToken().equals(
"repeat")) {
node =
new RepeatCommandNode();
node.parse(context);
}
else {
node =
new PrimitiveCommandNode();
node.parse(context);
}
}
@Override
public String
toString() {
return node.toString();
}
}
RepeatCommandNode类
package com.pc.interpreter.example;
/**
* 重复命令节点类
* <repeat command> ::= repeat <number> <command list>
*/
public class RepeatCommandNode extends Node {
/**
* 重复次数
*/
private int number;
/**
* 命令列表节点
*/
private Node commandListNode;
@Override
public void parse(Context context)
throws ParseException {
context.skipToken(
"repeat");
number = context.currentNumber();
context.nextToken();
commandListNode =
new CommandListNode();
commandListNode.parse(context);
}
@Override
public String
toString() {
return "[repeat " + number +
" " + commandListNode +
"]";
}
}
PrimitiveCommandNode类
package com.pc.interpreter.example;
/**
* 原始命令节点类
* <primitive command> ::= go | right | left
*/
public class PrimitiveCommandNode extends Node {
/**
* 名字
*/
private String name;
@Override
public void parse(Context context)
throws ParseException {
name = context.currentToken();
context.skipToken(name);
if (!name.equals(
"go") && !name.equals(
"right") && !name.equals(
"left")) {
throw new ParseException(name +
" is undefined");
}
}
@Override
public String
toString() {
return name;
}
}
Context类
package com.pc.interpreter.example;
import java.util.StringTokenizer;
/**
* 上下文类
*/
public class Context {
/**
* 分词器
*/
private StringTokenizer tokenizer;
/**
* 当前符号
*/
private String currentToken;
public Context(String text) {
this.tokenizer =
new StringTokenizer(text);
this.nextToken();
}
/**
* 返回下一个符号
*
* @return 下一个符号
*/
public String
nextToken() {
if (tokenizer.hasMoreTokens()) {
this.currentToken =
this.tokenizer.nextToken();
}
else {
this.currentToken =
null;
}
return this.currentToken;
}
/**
* 返回当前符号
*
* @return 当前符号
*/
public String
currentToken() {
return this.currentToken;
}
/**
* 跳过指定符号
*
* @param token 指定符号
* @throws ParseException 解析异常
*/
public void skipToken(String token)
throws ParseException {
if (!token.equals(
this.currentToken)) {
throw new ParseException(
"Warning: " + token +
" is expected, but " + currentToken +
" is found.");
}
this.nextToken();
}
/**
* 解析数值
*
* @return 数值
* @throws ParseException 解析异常
*/
public int currentNumber()
throws ParseException {
int number =
0;
try {
number = Integer.parseInt(currentToken);
}
catch (NumberFormatException e) {
throw new ParseException(
"Warning: " + e);
}
return number;
}
}
测试类
package com.pc.interpreter.example.test;
import com.pc.interpreter.example.Context;
import com.pc.interpreter.example.Node;
import com.pc.interpreter.example.ProgramNode;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.FileReader;
/**
* Interpreter Tester.
*
* @author Switch
* @version 1.0
*/
public class InterpreterTest {
/**
* 测试解释器模式
*/
@Test
public void testInterpreter() {
try {
BufferedReader reader =
new BufferedReader(
new FileReader(System.getProperty(
"user.dir")
+
"/src/main/java/com/pc/interpreter/example/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();
}
}
}
运行结果
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]]]]
解释器模式中的角色
AbstractExpression(抽象表达式)
AbstractExpression角色定义了语法树节点的共同接口(API)。在案例中,由Node类扮演此角色。在案例中,共同接口(API)的名字是parse,不过在类图中它的名字是interpreter。
TerminalExpression(终结符表达式)
TerminalExpression角色对应BNF中的终结特表达式。在案例中,由PrimitiveCommandNode类扮演此角色。
NonterminalExpression(非终结符表达式)
NonterminalExpression角色对应BNF中的非终结符表达式。在案例中,由ProgramNode类、CommandNode类、RepeatCommandNode类和CommandListNode 类扮演此角色。
Context(文脉、上下文)
Context 角色为解释器进行语法解析提供了必要的信息。在案例中,由Context 类扮演此角色。
Client(请求者)
为了推导语法树, C li ent 角色会调用TerminalExpression 角色和Nonterm inalExpress i on 角色。在案例中,由Ma 工n 类扮演此角色。
类图
GitHub:DesignPatternStudy
——————参考《图解设计模式》
转载请注明原文地址: https://ju.6miu.com/read-665196.html