欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-12-09 16:04:33
本文实例讲述了java基于解释器模式实现定义一种简单的语言功能。分享给大家供大家参考,具体如下: 一 模式定义 解释器模式:就是给定一个语言的文法表示,并且定义一个解释...

本文实例讲述了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 该语言解释树结构

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

3 该语言解释器活动图

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

4 代码示例

4.1 创建上下文环境——context

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

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

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

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

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

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

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

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基于解释器模式实现定义一种简单的语言功能示例

更多java相关内容感兴趣的读者可查看本站专题:《java面向对象程序设计入门与进阶教程》、《java数据结构与算法教程》、《java操作dom节点技巧总结》、《java文件与目录操作技巧汇总》和《java缓存操作技巧汇总

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