Interpreter パターン

「Interpreter」という英単語は、「通訳」を意味します。

このパターンは、なんらかの文法規則をもった文書(プログラム言語)を解析し、その結果得られた手順(命令)に基づき処理を実行していくというパターンです。


役割り

1. AbstractExpression(抽象的な表現)
「TerminalExpression」・「NonterminalExpression」に共通のインタフェースを定義します。
2. TerminalExpression(終端となる表現)
終端を表現するクラスです。階層関係の末端(構造木の葉)を表します。
3. NonterminalExpression(非終端となる表現)
非終端を表現するクラスです。階層関係のノード(構造木の節)を表します。
4. Context(文脈・状況判断)
「Expression」(インタプリタ)が構文解析を行うための情報を提供します。
5. Client(利用者)
「Interpreter」パターンを適用したクラスを利用し処理します。

▲PageTop

クラス図

Interpreterパターンのクラス図

Interpreterパターン クラス図

▲PageTop

サンプル

ソースコード

1. AbstractExpression.java

public abstract class AbstractExpression {
    public abstract int Interpret(Context context);
}

2. TerminalExpression.java

public class TerminalExpression extends AbstractExpression{
    private String saveToken;
    public int Interpret(Context context) {
        String token = context.getToken();
        saveToken = token;
        context.nextToken();
        return Integer.parseInt(token);
    }
    public String toString(){
        return saveToken;
    }
}

3. NonterminalExpression.java

import java.util.List;
import java.util.ArrayList;

public class NonterminalExpression extends AbstractExpression {
    private int resultValue;
    private String startTagPlus = "<+>";
    private String endTagPlus   = "</+>";
    private List<AbstractExpression> list = new ArrayList<AbstractExpression>();
    public int Interpret(Context context) {
        AbstractExpression childExpressions;
        context.nextToken();
        String token = "";
        while (!context.isEnd()) {
            token = context.getToken();
            if (startTagPlus.equals(token)) {
                childExpressions = new NonterminalExpression();
            } else if (endTagPlus.equals(token)) {
                context.nextToken();
                break;
            } else {
                childExpressions = new TerminalExpression();
            }
            resultValue += childExpressions.Interpret(context);
            list.add(childExpressions);
        }
        return resultValue;
    }
    public String toString(){
        return "+" + list.toString();
    }
}

4. Context.java

import java.util.StringTokenizer;

public class Context {
    private StringTokenizer tokens;
    private String currentToken;
    public Context(String source) {
        tokens = new StringTokenizer(source);
        nextToken();
    }
    public String getToken(){
        return currentToken;
    }
    public void nextToken(){
        String token = null;
        if (!isEnd()){
            token = tokens.nextToken();
        }
        currentToken = token;
    }
    public boolean isEnd(){
        return !tokens.hasMoreElements();
    }
}

5. Client.java

public class Client {
    public static void main(String[] args) {
        String sourse = "<+> 10 <+> 1 4 8 5 1 <+> 1 7 </+> 1 </+> 10 1 </+>";
        Context context = new Context(sourse);
        AbstractExpression expression = new NonterminalExpression();
        System.out.println(expression.Interpret(context));
        System.out.println(expression.toString());
    }
}

実行結果

C:\sample\desin_pattern\interpreter>javac Client.java [Enter]

C:\sample\desin_pattern\interpreter>java Client [Enter]
49
+[10, +[1, 4, 8, 5, 1, +[1, 7], 1], 10, 1]
        

▲PageTop