nus/cs2030s/labs/MockPE2/Reader.java

146 lines
3.4 KiB
Java

/**
* @author A0000000X
*/
import java.util.NoSuchElementException;
import java.util.List;
import java.util.ArrayList;
abstract class Reader<T> {
protected final List<T> inputs;
protected Reader(List<T> inputs) {
this.inputs = inputs;
}
protected Reader() {
this.inputs = null;
}
private static final Reader<?> EOF = new EOF();
public abstract T read();
public abstract Reader<T> consume();
public abstract boolean hasNext();
public abstract <R> Reader<R> map(Immutator<? extends R, ? super T> f);
public abstract Reader<T> flatMap(Immutator<? extends Reader<? extends T>, ? super T> f);
@SafeVarargs
public static <T> Reader<T> of(T... inputs) {
List<T> currInputs = new ArrayList<T>();
for (int i=0; i<inputs.length; i++) {
currInputs.add(inputs[i]);
}
return new NonEmpty<>(currInputs);
}
public static <T> Reader<T> of() {
@SuppressWarnings("unchecked")
Reader<T> res = (Reader<T>) EOF;
return res;
}
private static class NonEmpty<T> extends Reader<T> {
protected NonEmpty(List<T> inputs) {
super(inputs);
}
@Override
public T read() {
return this.inputs.get(0);
}
@Override
public boolean hasNext() {
return true;
}
@Override
public Reader<T> consume() {
if (this.inputs.size() == 1) {
return Reader.<T>of();
}
List<T> currInputs = new ArrayList<T>(this.inputs);
currInputs.remove(0);
return new NonEmpty<>(currInputs);
}
@Override
public <R> Reader<R> map(Immutator<? extends R, ? super T> f) {
List<R> currInputs = new ArrayList<R>();
for (int i=0; i<this.inputs.size(); i++) {
currInputs.add(f.invoke(this.inputs.get(i)));
}
return new NonEmpty<>(currInputs);
}
@Override
public Reader<T> flatMap(Immutator<? extends Reader<? extends T>, ? super T> f) {
Reader<? extends T> tmp = f.invoke(this.inputs.get(0));
List<T> currInputs = new ArrayList<T>();
for (int i=0; i<tmp.inputs.size(); i++) {
currInputs.add(tmp.inputs.get(i));
}
for (int i=1; i<this.inputs.size(); i++) {
currInputs.add(this.inputs.get(i));
}
return new NonEmpty<>(currInputs);
}
@Override
public String toString() {
return "Reader";
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof NonEmpty<?>)) {
return false;
}
return true;
}
}
private static class EOF extends Reader<Object> {
@Override
public Object read() {
throw new NoSuchElementException();
}
@Override
public Reader<Object> consume() {
throw new NoSuchElementException();
}
@Override
public boolean hasNext() {
return false;
}
@Override
public <R> Reader<R> map(Immutator<? extends R, Object> f) {
return Reader.of();
}
@Override
public Reader<Object> flatMap(Immutator<? extends Reader<? extends Object>, ? super Object> f) {
return Reader.of();
}
@Override
public String toString() {
return "EOF";
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof EOF)) {
return false;
}
return true;
}
}
}