Interpreter パターン (文法規則をクラスで表現したものを用い構文解析し, その結果に基づき処理を実行していく機能を提供する)
[Interpreter] = 通訳
このパターンは, なんらかの文法規則をもった文書 (プログラム言語) を解析し, その結果得られた手順 (命令) に基づき処理を実行していくというパターン.
役割
- AbstractExpression (抽象的な表現):
[TerminalExpression] と [NonterminalExpression] に共通のインタフェース
定義する.
- TerminalExpression (終端となる表現):
終端を表現するクラス. 階層関係の末端 (構造木の葉) を表す.
- NonterminalExpression (非終端となる表現):
非終端を表現するクラス. 階層関係のノード (構造木の節) を表す.
- Context (文脈, 状況判断):
[Expression] (インタプリタ) が構文解析を行うための情報を提供する.
- Client (利用者):
[Interpreter] パターンを適用したクラスを利用し処理する.
クラス図
Interpreter パターンの図
ソースコード
- AbstractExpression.java
| public abstract class AbstractExpression{
public abstract int Interpret(Context context);
}
|
- TerminalExpression.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | 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;
}
}
|
- NonterminalExpression.java
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 | 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();
}
}
|
- Context.java
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 | 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(); // 標準の .nextToken() を呼び出す
}
currentToken = token;
}
public boolean isEnd(){
return !tokens.hasMoreElements();
}
}
|
- Client.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | public class Client{
public static void main(String[] args){
/*
注意: 数字だけなので, 文字列になったら, エラーとなる.
*/
String source = "<%> 1 <%> 2 3 4 5 6 <%> 7 8 </%> 9 </%> 10 11 </%>";
Context context = new Context(source);
AbstractExpression expression = new NonterminalExpression();
System.out.println( expression.Interpret(context) );
System.out.println( expression.toString() );
}
}
|
上記のプログラムの実行結果:
[wtopia Interpreter]$ java Client
66
+[1, +[2, 3, 4, 5, 6, +[7, 8], 9], 10, 11]