package openmods.calc.parsing;
import com.google.common.collect.Lists;
import java.util.List;
import openmods.calc.ExecutableList;
import openmods.calc.IExecutable;
import openmods.calc.NoopExecutable;
import openmods.calc.Operator;
import openmods.calc.OperatorDictionary;
import openmods.calc.SymbolCall;
import openmods.calc.SymbolGet;
import openmods.calc.Value;
import openmods.utils.OptionalInt;
public class DefaultExecutableListBuilder<E> implements IExecutableListBuilder<E> {
private final IValueParser<E> valueParser;
private final OperatorDictionary<E> operators;
private final List<IExecutable<E>> buffer = Lists.newArrayList();
public DefaultExecutableListBuilder(IValueParser<E> valueParser, OperatorDictionary<E> operators) {
this.valueParser = valueParser;
this.operators = operators;
}
protected void addToBuffer(IExecutable<E> executable) {
buffer.add(executable);
}
@Override
public void appendValue(E value) {
addToBuffer(Value.create(value));
}
@Override
public void appendValue(Token token) {
try {
final E parsedValue = valueParser.parseToken(token);
appendValue(parsedValue);
} catch (Throwable t) {
throw new InvalidTokenException(token, t);
}
}
private Operator<E> getAnyOperator(String id) {
Operator<E> op = operators.getBinaryOperator(id);
if (op != null) return op;
op = operators.getUnaryOperator(id);
if (op != null) return op;
throw new IllegalArgumentException("Invalid operator: " + id);
}
@Override
public void appendOperator(String id) {
addToBuffer(getAnyOperator(id));
}
@Override
public void appendSymbolGet(String id) {
addToBuffer(new SymbolGet<E>(id));
}
@Override
public void appendSymbolCall(String id, OptionalInt argCount, OptionalInt returnCount) {
addToBuffer(new SymbolCall<E>(id, argCount, returnCount));
}
@Override
public void appendExecutable(IExecutable<E> executable) {
if (executable instanceof NoopExecutable) {
// well, no-op
} else if (executable instanceof ExecutableList) {
List<IExecutable<E>> flattenedList = Lists.newArrayList();
((ExecutableList<E>)executable).deepFlatten(flattenedList);
for (IExecutable<E> e : flattenedList)
addToBuffer(e);
} else {
addToBuffer(executable);
}
}
@Override
public IExecutable<E> build() {
return ExecutableList.wrap(buffer);
}
}