设计模式(二十三)-解释器模式(Interpreter Pattern)——语法规则也是类

原创 2018年02月11日 17:29:03

解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。

Node.java

package com.test.dp.Interpreter.Sample;

//表示语法树“节点”的类
public abstract class Node {
    public abstract void parse(Context context) throws ParseException;
}
ProgramNode.java

package com.test.dp.Interpreter.Sample;

// <program> ::= program <command list>
public class ProgramNode extends Node {
    private Node commandListNode;
    public void parse(Context context) throws ParseException {
        context.skipToken("program");
        commandListNode = new CommandListNode();
        commandListNode.parse(context);
    }
    public String toString() {
        return "[program " + commandListNode + "]";
    }
}
CommandListNode.java

package com.test.dp.Interpreter.Sample;

import java.util.ArrayList;

// <command list> ::= <command>* end
public class CommandListNode extends Node {
    private ArrayList list = new ArrayList();
    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);
            }
        }
    }
    public String toString() {
        return list.toString();
    }
}
CommandNode.java

package com.test.dp.Interpreter.Sample;

// <command> ::= <repeat command> | <primitive command>
public class CommandNode extends Node {
    private Node node;
    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);
        }
    }
    public String toString() {
        return node.toString();
    }
}
RepeatCommandNode.java

package com.test.dp.Interpreter.Sample;

// <repeat command> ::= repeat <number> <command list>
public class RepeatCommandNode extends Node {
    private int number;
    private Node commandListNode;
    public void parse(Context context) throws ParseException {
        context.skipToken("repeat");
        number = context.currentNumber();
        context.nextToken();
        commandListNode = new CommandListNode();
        commandListNode.parse(context);
    }
    public String toString() {
        return "[repeat " + number + " " + commandListNode + "]";
    }
}
PrimitiveCommandNode.java

package com.test.dp.Interpreter.Sample;

// <primitive command> ::= go | right | left
public class PrimitiveCommandNode extends Node {
    private String name;
    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");
        }
    }
    public String toString() {
        return name;
    }
}
Context.java

package com.test.dp.Interpreter.Sample;

import java.util.*;

//表示语法解析上下文的类
public class Context {
    private StringTokenizer tokenizer;
    private String currentToken;
    public Context(String text) {
        tokenizer = new StringTokenizer(text);
        nextToken();
    }
    public String nextToken() {
        if (tokenizer.hasMoreTokens()) {
            currentToken = tokenizer.nextToken();
        } else {
            currentToken = null;
        }
        return currentToken;
    }
    public String currentToken() {
        return currentToken;
    }
    public void skipToken(String token) throws ParseException {
        if (!token.equals(currentToken)) {
            throw new ParseException("Warning: " + token + " is expected, but " + currentToken + " is found.");
        }
        nextToken();
    }
    public int currentNumber() throws ParseException {
        int number = 0;
        try {
            number = Integer.parseInt(currentToken);
        } catch (NumberFormatException e) {
            throw new ParseException("Warning: " + e);
        }
        return number;
    }
}
ParseException.java

package com.test.dp.Interpreter.Sample;

//表示语法解析中可能回发生异常的类
public class ParseException extends Exception {
    public ParseException(String msg) {
        super(msg);
    }
}
Main.java

package com.test.dp.Interpreter.Sample;

import java.util.*;
import java.io.*;

public class Main {
    public static void main(String[] args) {
        try {
            BufferedReader reader = new BufferedReader(new FileReader("D:/workspace/design-pattern/src/com/test/dp/Interpreter/Sample/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();
        }
    }
}
program.txt

program end
program go end
program go right go right go right go right end
program repeat 4 go right end end
program repeat 4 repeat 3 go right go left end right end end

执行结果:

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

总结:

应用实例:编译器、运算表达式计算。

优点:1、可扩展性比较好,灵活。2、增加了新的解释表达式的方式。3、易于实现简单文法。

缺点:1、可利用场景比较少。2、对于复杂的文法比较难维护。3、解释器模式会引起类膨胀。4、解释器模式采用递归调用方法。

使用场景:1、可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。2、一些重复出现的问题可以用一种简单的语言来进行表达。3、一个简单语法需要解释的场景。

注意事项:可利用场景比较少,JAVA 中如果碰到可以用 expression4J 代替。


设计模式(行为型)之解释器模式(Interpreter Pattern)

访问者模式是一种较为复杂的行为型设计模式,它包含访问者和被访问元素两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。访问者模式使得用户可以在不修改现有系...
  • yanbober
  • yanbober
  • 2015年05月06日 17:11
  • 3464

JAVA设计模式十五--Interpreter(解释器模式)

Interpreter模式,即解释器模式。   解释器模式属于行为模式,Gof是这样定义的:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解     释语言中的句子...
  • hfmbook
  • hfmbook
  • 2012年06月25日 08:49
  • 3890

设计模式(c++)笔记之二十三(Interpreter模式)

一、描述:       概念:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 最简单的例子是表达式运算。       I...
  • my183100521
  • my183100521
  • 2013年10月25日 14:34
  • 2099

GOF 23 设计模式之 解释器模式(Interpreter)与访问者模式(Visitor)

解释器模式介绍 是一种不常用的设计模式 用于描述如何构成一个简单的语言解释器,主要用于使用面相对象语言开发的编译器和解释器设计 当我们需要开发一种新的语言时,可以考虑使用解释器模式 尽量不要使用解释器...
  • coderbean
  • coderbean
  • 2015年10月04日 14:23
  • 540

【JS设计模式】解释器模式代码示例

1、定义 Interpreter模式也叫解释器模式,是由GoF提出的23种设计模式中的一种。Interpreter是行为模式之一,它是一种特殊的设计模式,它建立一个解释器,对于特定的计算机程序...
  • itpinpai
  • itpinpai
  • 2016年06月13日 14:08
  • 2628

设计模式 - Interpreter Pattern(解释器模式)

设计模式 - Interpreter Pattern(解释器模式)  设计模式 - Interpreter Pattern(解释器模式)作者:webabcd介绍给定一个语言, 定义它的文法的一种表示,...
  • daonidedie
  • daonidedie
  • 2007年12月26日 21:44
  • 846

设计模式【解释器模式Interpreter Pattern】

解释器模式 解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 S...
  • qiaoquan3
  • qiaoquan3
  • 2017年10月19日 16:23
  • 50

设计模式实现(二十三)--- 解释器模式(interpreter)

解释器模式(interpreter),给定一个语言,定义它的
  • u012829687
  • u012829687
  • 2014年08月14日 11:10
  • 193

JAVA--解释器模式(Interpreter)--设计模式二十三

1,概述:            (1)解释器模式是我们暂时的最后一讲,一般主要应用在OOP开发中的编译器的开发中, 所以适用面比较窄       Context类是一个上下文环...
  • qq_26891045
  • qq_26891045
  • 2016年04月26日 10:26
  • 596

大话设计模式27----解释器模式

大话设计模式 1 解释器模式(interpreter)结构图 2 对解释器模式的一些解释 概念:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这...
  • qianqin_2014
  • qianqin_2014
  • 2016年07月26日 21:58
  • 343
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:设计模式(二十三)-解释器模式(Interpreter Pattern)——语法规则也是类
举报原因:
原因补充:

(最多只允许输入30个字)