serene-simple/src/main/java/serene/simple/Reader.java

69 lines
2.0 KiB
Java

package serene.simple;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PushbackReader;
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<Node> nodes = new ArrayList<Node>();
skipWhitespaces(inputStream);
char c = inputStream.read();
while ((byte) c != -1) {
inputStream.unread(c);
nodes.add(readNode(inputStream));
skipWhitespaces(inputStream);
c = (char) inputStream.read();
}
}
private static Node readList(PushbackReader inputStream) throws IOException {
char opening = (char) inputStream.read();
assert opening == '(' : "Lists must start with a '('";
List<Node> nodes = new ArrayList<Node>();
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(ListNode.list(nodes));
}
}