package openmods.calc.parsing; import com.google.common.base.Preconditions; import openmods.calc.IExecutable; import openmods.calc.SymbolCall; import openmods.utils.OptionalInt; public class SimplePostfixCompilerState<E> implements IPostfixCompilerState<E> { final IExecutableListBuilder<E> builder; public SimplePostfixCompilerState(IExecutableListBuilder<E> builder) { this.builder = builder; } @Override public Result acceptToken(Token token) { if (token.type == TokenType.OPERATOR) builder.appendOperator(token.value); else if (token.type == TokenType.SYMBOL) builder.appendSymbolCall(token.value, SymbolCall.DEFAULT_ARG_COUNT, SymbolCall.DEFAULT_RET_COUNT); else if (token.type == TokenType.SYMBOL_WITH_ARGS) parseSymbolWithArgs(token.value, builder); else if (token.type.isValue()) builder.appendValue(token); else return Result.REJECTED; return Result.ACCEPTED; } private static <E> void parseSymbolWithArgs(String value, IExecutableListBuilder<E> output) { final int argsStart = value.lastIndexOf('$'); Preconditions.checkArgument(argsStart >= 0, "No args in token '%s'", value); final String id = value.substring(0, argsStart); OptionalInt argCount = OptionalInt.absent(); OptionalInt retCount = OptionalInt.absent(); try { final String args = value.substring(argsStart + 1, value.length()); final int argsSeparator = args.indexOf(','); if (argsSeparator >= 0) { { final String argCountStr = args.substring(0, argsSeparator); if (!argCountStr.isEmpty()) argCount = OptionalInt.of(Integer.parseInt(argCountStr)); } { final String retCountStr = args.substring(argsSeparator + 1, args.length()); if (!retCountStr.isEmpty()) retCount = OptionalInt.of(Integer.parseInt(retCountStr)); } } else { argCount = OptionalInt.of(Integer.parseInt(args)); } } catch (Exception e) { throw new IllegalArgumentException("Can't parse args on token '" + value + "'", e); } output.appendSymbolCall(id, argCount, retCount); } @Override public Result acceptExecutable(IExecutable<E> executable) { builder.appendExecutable(executable); return Result.ACCEPTED; } @Override public IExecutable<E> exit() { return builder.build(); } }