解释器模式

没太明白怎么区分终结符与非终结符,只是简单记录一下,不推荐看

解释器模式概述

什么是解释器: 定义一个语言,并定义该语言的文法表示,再设计一个解析器来解释语言中的句子,简单来说,就是为了解释一种语言,为这个语言创建的解释器,例如java语言,C语言,各种语言都有对应的编译器进行编译,这个编译器就相当于解释器

解释器模角色分析

  • 抽象表达式 AbstractExpression:定义解释器的接口,约定解释器的解释操作,主要包含解释方法。
  • 终结符表达式 TerminalExpression:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
  • 非终结符表达式 NonterminalExpression:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。
  • 环境 Context:通常包含各个解释器需要的数据或是公共的功能,持有解释器对象, 后面的解释器可以从这里获取这些值。

解释器模式案例

案例
设计一个可以加减的计算器

  1. 创建抽象表达式
//抽象表达式,通过HashMap的键值对可以获取到变量的值
abstract class Expression{
    //解释公式与数值的关系,key就是公式参数例如(a+b-c),key就是里面的abc
    //value就是具体的值
    public abstract int interpreter(HashMap<String,Integer> var);
}
  1. 创建变量解析器,继承抽象表达式
//变量解析器
class VarExpression extends Expression{
    private String key; //key=a,key=b,key=c

    public VarExpression(String key) {
        this.key = key;
    }
    //根据变量的名称返回对应的值
    @Override
    public int interpreter(HashMap<String, Integer> var) {
        return var.get(this.key );
    }
}
  1. 创建抽象符号解析器,此处也充当了默认没有符号的解释器(是否是必须要的?是否必须继承Expression)
//抽象符号解析器
class SymbolExpression extends Expression{
    //符号左右两个的数据,符号左右两个可能还是一个具体的表达式
    //所以使用 Expression 类型
    public Expression left;
    public Expression right;

    public SymbolExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    //抽象符号解析器中提供默认实现(根据需求在子类中进行具体实现
    @Override
    public int interpreter(HashMap<String, Integer> var) {
        return 0;
    }
}
  1. 创建"+"符号解析器,继承抽象符号解释器
//加法符号解析器
class AddExpression extends SymbolExpression{
    public AddExpression(Expression left, Expression right) {
        super(left, right);
    }

    public int interpreter(HashMap<String, Integer> var) {
        //返回left表达式对应的值 + 返回right表达式对应的值
        return super.left.interpreter(var) + super.right.interpreter(var);
    }
}
  1. 创建"-"符号解析器,继承抽象符号解释器
//减法符号解析器 非终结符表达式
class SubExpression extends SymbolExpression{
    public SubExpression(Expression left, Expression right) {
        super(left, right);
    }

    public int interpreter(HashMap<String, Integer> var) {
        //返回left表达式对应的值 - 返回right表达式对应的值
        return super.left.interpreter(var) - super.right.interpreter(var);
    }
}
  1. 创建上下文
class Calculator{
    private Expression expression;

    public Calculator(String expStr) {
        //安排运算的先后顺序
        Stack<Expression> stack = new Stack<>();
        //将运算符号转换为字符数组
        char[] charArray = expStr.toCharArray();

        Expression left = null;
        Expression right = null;
        for(int i =0; i< charArray.length; i++) {
            switch(charArray[i]) {
                //一个运算表达式'a+b'如果转换为数组变成了[a,+,b]
                //遍历出'+',可以判断'+'下标的前一个元素与后一个元素
                //都是运算数据的变量名,在遍历时如果是变量名,会存入Stack
                //取出stack中最后添加的数据,也就是"+"的上一个元素
                //然后'+'的下标+1获取下一个变量元素,初始化AddExpression
                //对象存入stack中
                case '+':
                    left = stack.pop();
                    right = new VarExpression(String.valueOf(charArray[++i]));
                    stack.push(new AddExpression(left, right));
                    break;
                case '-':
                    left = stack.pop();
                    right = new VarExpression(String.valueOf(charArray[++i]));
                    stack.push(new SubExpression(left, right));
                    break;
                default:
                    //如果遍历charArray得到的是英文字符,说明是符号两边的变量数据
                    //获取变量数据,push到stack中
                    stack.push(new VarExpression(String.valueOf(charArray[i])));
                    break;
            }
        }
        //当整个charArray数组遍历完毕后,整个运算公式也就组合完毕了,
        //并且全都存入了stack中,在stack中弹出
        this.expression = stack.pop();
    }

    public int run(HashMap<String, Integer> var) {
        //解析表达式
        return this.expression.interpreter(var);
    }

}
  1. 调用测试
	public static void main(String[]args) {
        Calculator calculator = new Calculator("a+b-c");
        HashMap<String,Integer> map = new HashMap<>();
        map.put("a", 10);
        map.put("b", 20);
        map.put("c", 1);

        System.out.println(calculator.run(map));
    }

使用不是太多,并且没太明白怎么区分终结符与非终结符,不是太明白,只是简单记录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值