/** * @author A0000000X */ import java.util.NoSuchElementException; import java.util.List; import java.util.ArrayList; abstract class Reader { protected final List inputs; protected Reader(List inputs) { this.inputs = inputs; } protected Reader() { this.inputs = null; } private static final Reader EOF = new EOF(); public abstract T read(); public abstract Reader consume(); public abstract boolean hasNext(); public abstract Reader map(Immutator f); public abstract Reader flatMap(Immutator, ? super T> f); @SafeVarargs public static Reader of(T... inputs) { List currInputs = new ArrayList(); for (int i=0; i(currInputs); } public static Reader of() { @SuppressWarnings("unchecked") Reader res = (Reader) EOF; return res; } private static class NonEmpty extends Reader { protected NonEmpty(List inputs) { super(inputs); } @Override public T read() { return this.inputs.get(0); } @Override public boolean hasNext() { return true; } @Override public Reader consume() { if (this.inputs.size() == 1) { return Reader.of(); } List currInputs = new ArrayList(this.inputs); currInputs.remove(0); return new NonEmpty<>(currInputs); } @Override public Reader map(Immutator f) { List currInputs = new ArrayList(); for (int i=0; i(currInputs); } @Override public Reader flatMap(Immutator, ? super T> f) { Reader tmp = f.invoke(this.inputs.get(0)); List currInputs = new ArrayList(); for (int i=0; i(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 { @Override public Object read() { throw new NoSuchElementException(); } @Override public Reader consume() { throw new NoSuchElementException(); } @Override public boolean hasNext() { return false; } @Override public Reader map(Immutator f) { return Reader.of(); } @Override public Reader flatMap(Immutator, ? 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; } } }