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 + "]"; } }