package serene.simple; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PushbackReader; import java.util.ArrayList; import java.util.List; public class Reader { public static Node readNode(PushbackReader inputStream) throws IOException { char c = (char) inputStream.read(); inputStream.unread(c); if (c == '(') { return readList(inputStream); } else if (Character.isDigit(c)) { return readNumber(inputStream); } else if (c == ')') { throw new IllegalArgumentException("Unmatch paranthesis."); } else { return readSymbol(inputStream); } } public static ListNode read(InputStream inputStream) throws IOException { return read(new PushbackReader(new InputStreamReader(inputStream))); } public static ListNode read(PushbackReader inputStream) throws IOException { List nodes = new ArrayList(); skipWhiteSpaces(inputStream); char c = (char) inputStream.read(); while ((byte) c != -1) { inputStream.unread(c); nodes.add(readNode(inputStream)); skipWhiteSpaces(inputStream); c = (char) inputStream.read(); } return ListNode.list(nodes); } private static Node readList(PushbackReader inputStream) throws IOException { char opening = (char) inputStream.read(); assert opening == '(' : "Lists must start with a '('"; List nodes = new ArrayList(); do { skipWhiteSpaces(inputStream); char c = (char) inputStream.read(); if (c == ')') { break; } else if ((byte) c == -1) { throw new EOFException("EOF reached before closing of list"); } else { inputStream.unread(c); nodes.add(readNode(inputStream)); } } while(true); return SpecialForm.check(ListNode.list(nodes)); } private static Node readSymbol(PushbackReader inputStream) throws IOException { String str = ""; while (true) { int ch = inputStream.read(); if(isWhiteSpace(ch)) { inputStream.unread(ch); break; }; str = str + (char) ch; } return new SymbolNode(str); } private static Node readNumber(PushbackReader inputStream) throws IOException { String number = ""; while (true) { int ch = inputStream.read(); if(isWhiteSpace(ch)) { inputStream.unread(ch); break; }; number = number + (char) ch; } return new NumberNode(Long.parseLong(number, 10)); } private static void skipWhiteSpaces(PushbackReader inputStream) throws IOException { int ch = inputStream.read(); while (isWhiteSpace(ch)) { ch = inputStream.read(); } inputStream.unread(ch); } private static boolean isWhiteSpace(int ch) { return (ch == ' ' || ch == '\t' || ch == '\f' || ch == '\r' || ch == '\n'); } }