package openmods.calc.parsing;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.PeekingIterator;
import java.util.List;
import java.util.Map;
import openmods.calc.Compilers;
import openmods.calc.Compilers.ICompiler;
import openmods.calc.Environment;
import openmods.calc.ExecutableList;
import openmods.calc.ExprType;
import openmods.calc.Frame;
import openmods.calc.ICompilerMapFactory;
import openmods.calc.IExecutable;
import openmods.calc.OperatorDictionary;
import openmods.calc.Value;
import openmods.calc.parsing.DefaultPostfixCompiler.IStateProvider;
public class BasicCompilerMapFactory<E> implements ICompilerMapFactory<E, ExprType> {
public static final String BRACKET_CONSTANT_EVALUATE = "[";
public static final String MODIFIER_SYMBOL_GET = "@";
public static final String SYMBOL_PREFIX = "prefix";
public static final String SYMBOL_INFIX = "infix";
private static class WrappedCompiler<E> implements ICompiler<E> {
private final Tokenizer tokenizer;
private final ITokenStreamCompiler<E> compiler;
private WrappedCompiler(Tokenizer tokenizer, ITokenStreamCompiler<E> compiler) {
this.tokenizer = tokenizer;
this.compiler = compiler;
}
@Override
public IExecutable<E> compile(String input) {
final PeekingIterator<Token> tokens = tokenizer.tokenize(input);
final IExecutable<E> result = compiler.compile(tokens);
if (tokens.hasNext())
throw new IllegalStateException("Unconsumed tokens: " + Lists.newArrayList(tokens));
return result;
}
}
public static class ParserSwitchTransition<E> implements ISymbolCallStateTransition<E> {
private ICompilerState<E> switchState;
public ParserSwitchTransition(ICompilerState<E> switchState) {
this.switchState = switchState;
}
@Override
public ICompilerState<E> getState() {
return switchState;
}
@Override
public IExprNode<E> createRootNode(List<IExprNode<E>> children) {
Preconditions.checkState(children.size() == 1, "Expected one node, got %s", children);
return new DummyNode<E>(children.get(0));
}
}
@Override
public Compilers<E, ExprType> create(E nullValue, IValueParser<E> valueParser, OperatorDictionary<E> operators, Environment<E> environment) {
final Tokenizer prefixTokenizer = new Tokenizer();
final Tokenizer infixTokenizer = new Tokenizer();
final Tokenizer postfixTokenizer = new Tokenizer();
for (String operator : operators.allOperators()) {
prefixTokenizer.addOperator(operator);
infixTokenizer.addOperator(operator);
postfixTokenizer.addOperator(operator);
}
setupPrefixTokenizer(prefixTokenizer);
setupInfixTokenizer(infixTokenizer);
setupPostfixTokenizer(postfixTokenizer);
final IExprNodeFactory<E> exprNodeFactory = createExprNodeFactory(valueParser);
final MappedCompilerState<E> prefixCompilerState = createPrefixCompilerState(operators, exprNodeFactory);
final MappedCompilerState<E> infixCompilerState = createInfixCompilerState(operators, exprNodeFactory);
prefixCompilerState.addStateTransition(SYMBOL_INFIX, new ParserSwitchTransition<E>(infixCompilerState));
prefixCompilerState.addStateTransition(SYMBOL_PREFIX, new ParserSwitchTransition<E>(prefixCompilerState));
infixCompilerState.addStateTransition(SYMBOL_INFIX, new ParserSwitchTransition<E>(infixCompilerState));
infixCompilerState.addStateTransition(SYMBOL_PREFIX, new ParserSwitchTransition<E>(prefixCompilerState));
configureCompilerStateCommon(prefixCompilerState, environment);
configureCompilerStateCommon(infixCompilerState, environment);
final Map<ExprType, ICompiler<E>> compilers = Maps.newHashMap();
compilers.put(ExprType.PREFIX, new WrappedCompiler<E>(prefixTokenizer, createPrefixParser(prefixCompilerState)));
compilers.put(ExprType.INFIX, new WrappedCompiler<E>(infixTokenizer, createInfixParser(infixCompilerState)));
compilers.put(ExprType.POSTFIX, new WrappedCompiler<E>(postfixTokenizer, createPostfixParser(valueParser, operators, environment)));
return new Compilers<E, ExprType>(compilers);
}
protected void setupPrefixTokenizer(Tokenizer tokenizer) {}
protected MappedCompilerState<E> createCompilerState(final IAstParser<E> parser) {
return new MappedCompilerState<E>(parser);
}
protected MappedCompilerState<E> createPrefixCompilerState(OperatorDictionary<E> operators, IExprNodeFactory<E> exprNodeFactory) {
final IAstParser<E> prefixParser = new PrefixParser<E>(operators, exprNodeFactory);
return createCompilerState(prefixParser);
}
protected ITokenStreamCompiler<E> createPrefixParser(ICompilerState<E> compilerState) {
return new AstCompiler<E>(compilerState);
}
protected void setupInfixTokenizer(Tokenizer tokenizer) {}
protected MappedCompilerState<E> createInfixCompilerState(OperatorDictionary<E> operators, IExprNodeFactory<E> exprNodeFactory) {
final IAstParser<E> infixParser = new InfixParser<E>(operators, exprNodeFactory);
return createCompilerState(infixParser);
}
protected ITokenStreamCompiler<E> createInfixParser(ICompilerState<E> compilerState) {
return new AstCompiler<E>(compilerState);
}
protected void setupPostfixTokenizer(Tokenizer tokenizer) {
tokenizer.addModifier(MODIFIER_SYMBOL_GET);
}
protected ITokenStreamCompiler<E> createPostfixParser(IValueParser<E> valueParser, OperatorDictionary<E> operators, final Environment<E> env) {
final DefaultPostfixCompiler<E> compiler = new DefaultPostfixCompiler<E>(valueParser, operators);
return addSymbolGetState(addConstantEvaluatorState(valueParser, operators, env, compiler));
}
public static <E> DefaultPostfixCompiler<E> addConstantEvaluatorState(IValueParser<E> valueParser, OperatorDictionary<E> operators, Environment<E> env, DefaultPostfixCompiler<E> compiler) {
return compiler.addBracketStateProvider(BRACKET_CONSTANT_EVALUATE, createConstantEvaluatorStateProvider(valueParser, operators, env, BRACKET_CONSTANT_EVALUATE));
}
public static <E> IStateProvider<E> createConstantEvaluatorStateProvider(final IValueParser<E> valueParser, final OperatorDictionary<E> operators, final Environment<E> env, final String openingBracket) {
return new IStateProvider<E>() {
@Override
public IPostfixCompilerState<E> createState() {
final IExecutableListBuilder<E> listBuilder = new DefaultExecutableListBuilder<E>(valueParser, operators);
class ConstantEvaluatorState extends BracketPostfixCompilerStateBase<E> {
ConstantEvaluatorState() {
super(listBuilder, openingBracket);
}
@Override
protected IExecutable<E> processCompiledBracket(final IExecutable<E> compiledExpr) {
final Frame<E> resultFrame = env.executeIsolated(compiledExpr);
final List<IExecutable<E>> computedValues = Lists.newArrayList();
for (E value : resultFrame.stack())
computedValues.add(Value.create(value));
return ExecutableList.wrap(computedValues);
}
}
return new ConstantEvaluatorState();
}
};
}
public static <E> DefaultPostfixCompiler<E> addSymbolGetState(DefaultPostfixCompiler<E> compiler) {
return compiler.addModifierStateProvider(MODIFIER_SYMBOL_GET, new IStateProvider<E>() {
@Override
public IPostfixCompilerState<E> createState() {
return new SymbolGetPostfixCompilerState<E>();
}
});
}
protected DefaultExprNodeFactory<E> createExprNodeFactory(IValueParser<E> valueParser) {
return new DefaultExprNodeFactory<E>(valueParser);
}
protected void configureCompilerStateCommon(MappedCompilerState<E> compilerState, Environment<E> environment) {}
}