Java基于解释器模式实现定义一种简单的语言功能示例

时间:2021-05-02

本文实例讲述了java基于解释器模式实现定义一种简单的语言功能。分享给大家供大家参考,具体如下:

一 模式定义

解释器模式:就是给定一个语言的文法表示,并且定义一个解释器,用来解释语言中的句子。解释器模式描述了怎样在有了一个简单的文法后,使用模式设计解释这些语句。

二 模式举例

1 模式分析

我们自己设计一种语言来说明这一模式

(1)该语言区分大小写
(2)该语言以program开头,end结尾
(3)println表示打印一行并换行
(4)使用for…from…to…end表示循环

示例语言内容如下:

program println start... for i from 90 to 100 println i end println end...end

该句表示的意思是:首先打印“start…”换行,然后循环打印“90”换行、“91”换行、……“100”换行,最后打印“end…”换行。

2 该语言解释树结构

3 该语言解释器活动图

4 代码示例

4.1 创建上下文环境——context

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 package com.demo.interpreter.context; import java.util.hashmap; import java.util.iterator; import java.util.map; import java.util.stringtokenizer; /** * 上下文环境 * * @author * */ public class context { // 待解析的文本内容 private final stringtokenizer stringtokenizer; // 当前命令 private string currenttoken; // 用来存储动态变化信息内容 private final map<string, object> map = new hashmap<string, object>(); /** * 构造方法设置解析内容 * * @param text */ public context(string text) { // 使用空格分隔待解析文本内容 this.stringtokenizer = new stringtokenizer(text); } /** * 解析文本 */ 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 (command == null || !command.equals(this.currenttoken)) { return false; } return true; } /** * 获得当前命令内容 * * @return */ public string getcurrenttoken() { return this.currenttoken; } /** * 获得节点的内容 * * @return */ public string gettokencontent(string text) { string str = text; if (str != null) { // 替换map中的动态变化内容后返回 iterator<string> // 替换map中的动态变化内容后返回 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 表达式接口——iexpressions

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.demo.interpreter.express; import com.demo.interpreter.context.context; /** * * 表达式接口 * * @author * */ public interface iexpressions { /** * 解析 * * @param context */ public void parse(context context); /** * 执行方法 * * @param context */ public void interpret(); }

4.3 主表达式——programexpression

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 package com.demo.interpreter.express; import com.demo.interpreter.context.context; /** * program 表达式 * * @author * */ public class programexpression implements iexpressions { // 上下文环境 private final context context; // 当前命令 private final static string command = "program"; // 存储下一个表达式引用 private iexpressions expressions; /** * 构造方法将待解析的内容传入 * * @param text */ public programexpression(string text) { this.context = new context(text); this.parse(this.context); } @override public void parse(context context) { // 获取第一个命令节点 this.context.next(); } /** * 实现解释方法 */ @override public void interpret() { // 判断是否是以program 开始 if (!this.context.equalswithcommand(command)) { system.out.println("the '" + command + "' is excepted for start!"); } else { // 是以program 开始 this.context.next(); this.expressions = new listexpression(); this.expressions.parse(this.context); // listexpression表达式开始解析 this.expressions.interpret(); } } }

4.4 列表表达式——listexpression

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 package com.demo.interpreter.express; import java.util.arraylist; import java.util.iterator; import com.demo.interpreter.context.context; /** * 列表表达式 * * @author * */ public class listexpression implements iexpressions { private context context; private final arraylist<iexpressions> list = new arraylist<iexpressions>(); /** * 构造方法将待解析的context传入 * * @param context */ public void parse(context context) { this.context = context; // 在listexpression解析表达式中,循环解释语句中的每一个单词,直到终结符表达式或者异常情况退出 while (true) { if (this.context.getcurrenttoken() == null) { // 获取当前节点如果为 null 则表示缺少end表达式 system.out.println("error: the experssion missing 'end'! "); break; } else if (this.context.equalswithcommand("end")) { this.context.next(); // 解析正常结束 break; } else { // 建立command 表达式 iexpressions expressions = new commandexperssion(this.context); // 添加到列表中 list.add(expressions); } } } /** * 实现解释方法 */ @override public void interpret() { // 循环list列表中每一个表达式 解释执行 iterator<iexpressions> iterator = list.iterator(); while (iterator.hasnext()) { (iterator.next()).interpret(); } } }

4.5 命令表达式——commandexperssion

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package com.demo.interpreter.express; import com.demo.interpreter.context.context; /** * 命令表达式 * * @author * */ public class commandexperssion implements iexpressions { private final context context; private iexpressions expressions; /** * 构造方法将待解析的context传入 * * @param context */ public commandexperssion(context context) { this.context = context; this.parse(this.context); } public void parse(context context) { // 判断当前命令类别 在此只对for和最原始命令进行区分 if (this.context.equalswithcommand("for")) { // 创建for表达式进行解析 expressions = new forexpression(this.context); } else { // 创建原始命令表达式进行内容解析 expressions = new primitiveexpression(this.context); } } /** * 解析内容 */ @override public void interpret() { // 解析内容 this.expressions.interpret(); } }

4.6 循环表达式——forexpression

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 package com.demo.interpreter.express; import com.demo.interpreter.context.context; /** * for表达式 * * @author * */ public class forexpression implements iexpressions { private final context context; // 存储当前索引key值 private string variable; // 存储循环起始位置 private int start_index; // 存储循环结束位置 private int end_index; private iexpressions expressions; /** * 构造方法将待解析的context传入 * * @param context */ public forexpression(context context) { this.context = context; this.parse(this.context); } /** * 解析表达式 */ @override public void parse(context context) { // 首先获取当前节点 this.context.next(); while (true) { // 判断节点 if (this.context.equalswithcommand("from")) { // 设置开始索引内容 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; } // 获取下一个节点 this.context.next(); } else if (this.context.equalswithcommand("to")) { // 设置结束索引内容 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 { // 设置当前索引变量内容 if (this.variable == null) { this.variable = this.context.getcurrenttoken(); } // 获取下一个节点 this.context.next(); } } // 建立列表表达式 this.expressions = new listexpression(); this.expressions.parse(this.context); } /** * 实现解释方法 */ @override public void interpret() { // 建立命令表达式 for (int x = this.start_index; x <= this.end_index; x++) { // 设置变量内容 this.context.put("" + this.variable, x); // 执行解释方法 this.expressions.interpret(); } // 移除使用的临时变量内容 this.context.clear("" + this.variable); } }

4.7 基础表达式——primitiveexpression

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 package com.demo.interpreter.express; import com.demo.interpreter.context.context; /** * 最基础的表达式 * * @author * */ public class primitiveexpression implements iexpressions { private context context; // 节点名称 private string tokenname; // 文本内容 private string text; /** * 构造方法将待解析的context传入 * * @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(); } } /** * 实现解释方法 */ @override public void interpret() { // 首先获取当前节点内容 if ("println".equals(tokenname)) { // 获得内容信息 // 打印内容 system.out.println(this.context.gettokencontent(this.text)); } } }

4.8 让语言解释器开始工作——client

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.demo.interpreter; import com.demo.interpreter.express.iexpressions; import com.demo.interpreter.express.programexpression; /** * 主应用程序 * * @author * */ public class client { /** * @param args */ public static void main(string[] args) { // myida语言语句 string str = "program println start... for i from 90 to 100 println i end println end... end"; system.out.println("str:" + str); // 创建program表达式 iexpressions expressions = new programexpression(str); // 解释执行 expressions.interpret(); } }

5 运行结果

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...

三 设计原则

1 “开-闭”原则

2 封闭变化原则

四 使用场合

(1)一种特定类型的问题发生的频率足够高,并且业务规则频繁变化,不断重复出现类似情况。

(2)业务规则不是过于复杂烦琐,比较容易抽象出语法规则。

(3)效率不是软件系统中主要考虑的因素。

五 解释器模式静态类图

希望本文所述对大家java程序设计有所帮助。

原文链接:https://blog.csdn.net/chengqiuming/article/details/70139382

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章