Interpreterパターン

むずかしいいい。このパターンはつかわないかな。。
とり会えず一周したことになる。
この経験をどう活かすかにかかっている。再度読み返しが必要だろう。そういえばC言語も復習しないとダメだ。

% find . -name "*.java" -print0 |xargs -0 cat                                []
import java.util.ArrayList;

// <command list> ::= <command>* end
public class CommandListNode extends Node {
	private ArrayList<Node> list = new ArrayList<>();

	@Override
	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);
			}
		}
	}

	@Override
	public String toString() {
		return list.toString();
	}

}
// <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);
		}
	}

	@Override
	public String toString() {
		return node.toString();
	}
}
import java.util.StringTokenizer;

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;
	}

}
import java.io.BufferedReader;
import java.io.FileReader;

public class Main {

	public static void main(String[] args) {
		try {
			BufferedReader reader = new BufferedReader(new FileReader(
					"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);
			}
			reader.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
public abstract class Node {
	public abstract void parse(Context context) throws ParseException;
}
public class ParseException extends Exception {
	private static final long serialVersionUID = 1L;

	public ParseException(String msg) {
		super(msg);
	}
}
//<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");
		}
	}

	@Override
	public String toString() {
		return name;
	}
}
// <program> ::= program <command list>
public class ProgramNode extends Node {
	private Node commandListNode;

	@Override
	public void parse(Context context) throws ParseException {
		context.skipToken("program");
		commandListNode = new CommandListNode();
		commandListNode.parse(context);
	}

	@Override
	public String toString() {
		return "[program " + commandListNode + "]";
	}
}
// <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);
	}

	@Override
	public String toString() {
		return "[repeat " + number + " " + commandListNode + "]";
	}
}