给定一个语言的文法,即规则,并且定义一个解释器用来解释语言中的句子。该模式描述了
在怎么样给定一个简单的文法之后,使用该模式来解释这些句子。在解释器模式中定义了一
个代表语言文法命令的类层次结构,在这个结构中可以存在任何的组合规则,每一个具体的
解释器都有相同的解释操作,然而,每个解释器都以不同的方式实现公共的解释操作。再解
释器模式中使用组合的方式将一些类组成一个集合,然后定义出一种语法规则,解释器根据
已经定义的语法规则执行,生成可执行对象。
mydia语言规则:
区分大小写、以PROGRAM开始END结尾、PRINTLN表示打印一行并换行、使用FOR...FROM...TO...END
表示循环
PROGRAM PRINTLN start.... FOR i FROM 10 TO 20 PRINTLN i PRINTLN end.... END 预生成:
start....
10
11
12
13
14
15
16
17
18
19
20
end....
遵循原则:
开闭原则;
封装变化部分;
适用场合:
知识扩展:
JDK中java.text.Format就是解释器模式。
/**
* 该类主要用来保存待执行的语句、当前节点、动态参数内容,以及操作这些数据的公共方法。
* @author xsy
*
*/
public class Context {
//待解析的内容
private final StringTokenizer stringTokenizer;
//当前命令
private String currentToken;
//动态信息
private Map<String, Object> map = new HashMap<String, Object>();
public Context(String string) {
super();
//使用空格表示分隔符
this.stringTokenizer = new StringTokenizer(string);
}
/**
* 解析文本
* @return
*/
public String next(){
if(this.stringTokenizer.hasMoreTokens()){
currentToken = this.stringTokenizer.nextToken();
}else {
currentToken = null;
}
return currentToken;
}
/**
* 判断命令是否正确
* @param command
* @return
*/
public boolean equalsWithCommand(String command){
if(null == command || !command.equals(currentToken)){
return false;
}return true;
}
/**
* 获取当前内容
* @return
*/
public String getCurrentToken(){
return this.currentToken;
}
public String getTokenContent(String text){
String string = text;
if(string != null){
Iterator<String> itr = this.map.keySet().iterator();
while (itr.hasNext()) {
String key = itr.next();
Object object = map.get(key);
string = string.replaceAll(key, object.toString());
}
}
return string;
}
public void put(String key,Object object ){
this.map.put(key,object);
}
public void clear(String key){
this.map.remove(key);
}
}
public interface IExpression {
/**
* 解释
* @param context
*/
public void parse(Context context);
/**
* 执行
*/
public void execute();
}
public class PrimitiveExpression implements IExpression {
private Context context;
private String tokenName;
private String text;
public PrimitiveExpression(Context context) {
this.parse(this.context);
}
@Override
public void execute() {
if("PRINTLN".equals(this.tokenName))
System.out.println(this.context.getTokenContent(text));
}
@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();
}
}
}
public class ListExpression implements IExpression {
private Context context;
private final List<IExpression> list = new ArrayList<IExpression>();
@Override
public void execute() {
Iterator<IExpression> itr = list.iterator();
while (itr.hasNext()) {
itr.next().execute();
}
}
@Override
public void parse(Context context) {
this.context = context;
while (true) {
if(this.context.getCurrentToken() == null){
System.out.println("error!! END is excepted");
break;
}else if(this.context.equalsWithCommand("END")){
this.context.next();
break;
}else {
IExpression expression = new CommandExpression(this.context);
list.add(expression);
}
}
}
}
public class ForExpression implements IExpression {
private final Context context;
private IExpression expression;
private String var;
private int start;
private int end;
public ForExpression(Context context) {
this.context = context;
this.parse(this.context);
}
@Override
public void execute() {
for (int i = start; i <= end; i++) {
this.context.put(""+this.var, i);
this.expression.execute();
}
this.context.clear(""+this.var);
}
@Override
public void parse(Context context) {
this.context.next();
while (true) {
if(this.context.equalsWithCommand("FROM")){
String nextString = this.context.next();
start = Integer.parseInt(nextString);
this.context.next();
}else if(this.context.equalsWithCommand("TO")){
String nextString = this.context.next();
end = Integer.parseInt(nextString);
this.context.next();
break;
}else {
if(this.var == null){
this.var = this.context.getCurrentToken();
}
this.context.next();
}
}
this.expression = new ListExpression();
this.expression.parse(this.context);
}
}
public class ProgramExpression implements IExpression {
private final Context context;
/**
* 当前命令
*/
private final static String COMMAND = "PROGRAM";
/**
* 下一个表达式
*/
private IExpression expression;
public ProgramExpression(String text) {
this.context = new Context(text);
this.parse(this.context);
}
@Override
public void execute() {
if(!this.context.equalsWithCommand(COMMAND)){
System.out.println("error!! PROGRAM is excepted");
}else {
this.context.next();
this.expression = new ListExpression();
this.expression.parse(this.context);
this.expression.execute();
}
}
@Override
public void parse(Context context) {
this.context.next();
}
}
public class CommandExpression implements IExpression {
private final Context context;
private IExpression expression;
public CommandExpression(Context context) {
this.context = context;
this.parse(this.context);
}
@Override
public void execute() {
this.expression.execute();
}
@Override
public void parse(Context context) {
if(this.context.equalsWithCommand("FOR")){
expression = new ForExpression(this.context);
}else{
expression = new PrimitiveExpression(this.context);
}
}
}
测试
public class Client {
public static void main(String[] args) {
String str = "PROGRAM PRINTLN start.... FOR i FROM 10 TO 20 PRINTLN i END";
IExpression expression = new ProgramExpression(str);
expression.execute();
}
}