public class FactorioScriptBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements FactorioScriptVisitor<T> {
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitMultipleStatementList(FactorioScriptParser.MultipleStatementListContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitSingleStatementList(FactorioScriptParser.SingleStatementListContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitStatement(FactorioScriptParser.StatementContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitCompilerStandard(FactorioScriptParser.CompilerStandardContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitCompilerAlias(FactorioScriptParser.CompilerAliasContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitCompilerPowerpole(FactorioScriptParser.CompilerPowerpoleContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitOverwriteStatementAssign(FactorioScriptParser.OverwriteStatementAssignContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitAddStatementAssign(FactorioScriptParser.AddStatementAssignContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitSubStatementAssign(FactorioScriptParser.SubStatementAssignContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitIfElseIfElseStatement(FactorioScriptParser.IfElseIfElseStatementContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitIfElseStatement(FactorioScriptParser.IfElseStatementContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitIfStatement(FactorioScriptParser.IfStatementContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitVarExp(FactorioScriptParser.VarExpContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitMulDivModExp(FactorioScriptParser.MulDivModExpContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitPowExp(FactorioScriptParser.PowExpContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitBitExp(FactorioScriptParser.BitExpContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitPriorityExp(FactorioScriptParser.PriorityExpContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitAddSubExp(FactorioScriptParser.AddSubExpContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitNumExp(FactorioScriptParser.NumExpContext ctx) { return visitChildren(ctx); }
	/**
	 * {@inheritDoc}
	 *
	 * <p>The default implementation returns the result of calling
	 * {@link #visitChildren} on {@code ctx}.</p>
	 */
	@Override public T visitCondition(FactorioScriptParser.ConditionContext ctx) { return visitChildren(ctx); }
} public static class AddStatementAssignContext extends StatementAssignContext {
	public Token var;
	public ExpressionContext expr;
	public TerminalNode PLUS() { return getToken(FactorioScriptParser.PLUS, 0); }
	public TerminalNode ASSIGN() { return getToken(FactorioScriptParser.ASSIGN, 0); }
	public TerminalNode VAR() { return getToken(FactorioScriptParser.VAR, 0); }
	public ExpressionContext expression() {
		return getRuleContext(ExpressionContext.class,0);
	}
	public AddStatementAssignContext(StatementAssignContext ctx) { copyFrom(ctx); }
	@Override
	public void enterRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).enterAddStatementAssign(this);
	}
	@Override
	public void exitRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).exitAddStatementAssign(this);
	}
	@Override
	public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
		if ( visitor instanceof FactorioScriptVisitor ) return ((FactorioScriptVisitor<? extends T>)visitor).visitAddStatementAssign(this);
		else return visitor.visitChildren(this);
	}
} public static class AddSubExpContext extends ExpressionContext {
	public ExpressionContext left;
	public Token operand;
	public ExpressionContext right;
	public List<ExpressionContext> expression() {
		return getRuleContexts(ExpressionContext.class);
	}
	public ExpressionContext expression(int i) {
		return getRuleContext(ExpressionContext.class,i);
	}
	public TerminalNode PLUS() { return getToken(FactorioScriptParser.PLUS, 0); }
	public TerminalNode MINUS() { return getToken(FactorioScriptParser.MINUS, 0); }
	public AddSubExpContext(ExpressionContext ctx) { copyFrom(ctx); }
	@Override
	public void enterRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).enterAddSubExp(this);
	}
	@Override
	public void exitRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).exitAddSubExp(this);
	}
	@Override
	public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
		if ( visitor instanceof FactorioScriptVisitor ) return ((FactorioScriptVisitor<? extends T>)visitor).visitAddSubExp(this);
		else return visitor.visitChildren(this);
	}
} public static class BitExpContext extends ExpressionContext {
	public ExpressionContext left;
	public Token operand;
	public ExpressionContext right;
	public List<ExpressionContext> expression() {
		return getRuleContexts(ExpressionContext.class);
	}
	public ExpressionContext expression(int i) {
		return getRuleContext(ExpressionContext.class,i);
	}
	public TerminalNode BIT_LEFT() { return getToken(FactorioScriptParser.BIT_LEFT, 0); }
	public TerminalNode BIT_RIGHT() { return getToken(FactorioScriptParser.BIT_RIGHT, 0); }
	public TerminalNode BIT_AND() { return getToken(FactorioScriptParser.BIT_AND, 0); }
	public TerminalNode BIT_OR() { return getToken(FactorioScriptParser.BIT_OR, 0); }
	public TerminalNode BIT_XOR() { return getToken(FactorioScriptParser.BIT_XOR, 0); }
	public BitExpContext(ExpressionContext ctx) { copyFrom(ctx); }
	@Override
	public void enterRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).enterBitExp(this);
	}
	@Override
	public void exitRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).exitBitExp(this);
	}
	@Override
	public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
		if ( visitor instanceof FactorioScriptVisitor ) return ((FactorioScriptVisitor<? extends T>)visitor).visitBitExp(this);
		else return visitor.visitChildren(this);
	}
} public static class CompilerAliasContext extends StatementCompilerContext {
	public Token varOld;
	public Token varAlias;
	public TerminalNode COMPILERSIGN() { return getToken(FactorioScriptParser.COMPILERSIGN, 0); }
	public TerminalNode ALIAS() { return getToken(FactorioScriptParser.ALIAS, 0); }
	public TerminalNode ALIASASSIGN() { return getToken(FactorioScriptParser.ALIASASSIGN, 0); }
	public List<TerminalNode> VAR() { return getTokens(FactorioScriptParser.VAR); }
	public TerminalNode VAR(int i) {
		return getToken(FactorioScriptParser.VAR, i);
	}
	public CompilerAliasContext(StatementCompilerContext ctx) { copyFrom(ctx); }
	@Override
	public void enterRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).enterCompilerAlias(this);
	}
	@Override
	public void exitRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).exitCompilerAlias(this);
	}
	@Override
	public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
		if ( visitor instanceof FactorioScriptVisitor ) return ((FactorioScriptVisitor<? extends T>)visitor).visitCompilerAlias(this);
		else return visitor.visitChildren(this);
	}
} public static class CompilerPowerpoleContext extends StatementCompilerContext {
	public Token pole;
	public TerminalNode COMPILERSIGN() { return getToken(FactorioScriptParser.COMPILERSIGN, 0); }
	public TerminalNode POWERPOLE() { return getToken(FactorioScriptParser.POWERPOLE, 0); }
	public TerminalNode SMALL() { return getToken(FactorioScriptParser.SMALL, 0); }
	public TerminalNode MEDIUM() { return getToken(FactorioScriptParser.MEDIUM, 0); }
	public TerminalNode SUBSTATION() { return getToken(FactorioScriptParser.SUBSTATION, 0); }
	public CompilerPowerpoleContext(StatementCompilerContext ctx) { copyFrom(ctx); }
	@Override
	public void enterRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).enterCompilerPowerpole(this);
	}
	@Override
	public void exitRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).exitCompilerPowerpole(this);
	}
	@Override
	public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
		if ( visitor instanceof FactorioScriptVisitor ) return ((FactorioScriptVisitor<? extends T>)visitor).visitCompilerPowerpole(this);
		else return visitor.visitChildren(this);
	}
} public static class CompilerStandardContext extends StatementCompilerContext {
	public Token varLeft;
	public Token varRight;
	public TerminalNode COMPILERSIGN() { return getToken(FactorioScriptParser.COMPILERSIGN, 0); }
	public TerminalNode STANDARD() { return getToken(FactorioScriptParser.STANDARD, 0); }
	public TerminalNode ALIASASSIGN() { return getToken(FactorioScriptParser.ALIASASSIGN, 0); }
	public List<TerminalNode> VAR() { return getTokens(FactorioScriptParser.VAR); }
	public TerminalNode VAR(int i) {
		return getToken(FactorioScriptParser.VAR, i);
	}
	public CompilerStandardContext(StatementCompilerContext ctx) { copyFrom(ctx); }
	@Override
	public void enterRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).enterCompilerStandard(this);
	}
	@Override
	public void exitRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).exitCompilerStandard(this);
	}
	@Override
	public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
		if ( visitor instanceof FactorioScriptVisitor ) return ((FactorioScriptVisitor<? extends T>)visitor).visitCompilerStandard(this);
		else return visitor.visitChildren(this);
	}
} public static class MulDivModExpContext extends ExpressionContext {
	public ExpressionContext left;
	public Token operand;
	public ExpressionContext right;
	public List<ExpressionContext> expression() {
		return getRuleContexts(ExpressionContext.class);
	}
	public ExpressionContext expression(int i) {
		return getRuleContext(ExpressionContext.class,i);
	}
	public TerminalNode ASTERISK() { return getToken(FactorioScriptParser.ASTERISK, 0); }
	public TerminalNode SLASH() { return getToken(FactorioScriptParser.SLASH, 0); }
	public TerminalNode MODULO() { return getToken(FactorioScriptParser.MODULO, 0); }
	public MulDivModExpContext(ExpressionContext ctx) { copyFrom(ctx); }
	@Override
	public void enterRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).enterMulDivModExp(this);
	}
	@Override
	public void exitRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).exitMulDivModExp(this);
	}
	@Override
	public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
		if ( visitor instanceof FactorioScriptVisitor ) return ((FactorioScriptVisitor<? extends T>)visitor).visitMulDivModExp(this);
		else return visitor.visitChildren(this);
	}
} public static class MultipleStatementListContext extends StatementListContext {
	public StatementContext s;
	public StatementListContext sl;
	public StatementContext statement() {
		return getRuleContext(StatementContext.class,0);
	}
	public StatementListContext statementList() {
		return getRuleContext(StatementListContext.class,0);
	}
	public MultipleStatementListContext(StatementListContext ctx) { copyFrom(ctx); }
	@Override
	public void enterRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).enterMultipleStatementList(this);
	}
	@Override
	public void exitRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).exitMultipleStatementList(this);
	}
	@Override
	public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
		if ( visitor instanceof FactorioScriptVisitor ) return ((FactorioScriptVisitor<? extends T>)visitor).visitMultipleStatementList(this);
		else return visitor.visitChildren(this);
	}
} public static class NumExpContext extends ExpressionContext {
	public Token number;
	public TerminalNode NUMBER() { return getToken(FactorioScriptParser.NUMBER, 0); }
	public NumExpContext(ExpressionContext ctx) { copyFrom(ctx); }
	@Override
	public void enterRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).enterNumExp(this);
	}
	@Override
	public void exitRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).exitNumExp(this);
	}
	@Override
	public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
		if ( visitor instanceof FactorioScriptVisitor ) return ((FactorioScriptVisitor<? extends T>)visitor).visitNumExp(this);
		else return visitor.visitChildren(this);
	}
} public static class OverwriteStatementAssignContext extends StatementAssignContext {
	public Token var;
	public ExpressionContext expr;
	public TerminalNode ASSIGN() { return getToken(FactorioScriptParser.ASSIGN, 0); }
	public TerminalNode VAR() { return getToken(FactorioScriptParser.VAR, 0); }
	public ExpressionContext expression() {
		return getRuleContext(ExpressionContext.class,0);
	}
	public OverwriteStatementAssignContext(StatementAssignContext ctx) { copyFrom(ctx); }
	@Override
	public void enterRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).enterOverwriteStatementAssign(this);
	}
	@Override
	public void exitRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).exitOverwriteStatementAssign(this);
	}
	@Override
	public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
		if ( visitor instanceof FactorioScriptVisitor ) return ((FactorioScriptVisitor<? extends T>)visitor).visitOverwriteStatementAssign(this);
		else return visitor.visitChildren(this);
	}
} public static class PowExpContext extends ExpressionContext {
	public ExpressionContext left;
	public ExpressionContext right;
	public TerminalNode POWER() { return getToken(FactorioScriptParser.POWER, 0); }
	public List<ExpressionContext> expression() {
		return getRuleContexts(ExpressionContext.class);
	}
	public ExpressionContext expression(int i) {
		return getRuleContext(ExpressionContext.class,i);
	}
	public PowExpContext(ExpressionContext ctx) { copyFrom(ctx); }
	@Override
	public void enterRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).enterPowExp(this);
	}
	@Override
	public void exitRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).exitPowExp(this);
	}
	@Override
	public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
		if ( visitor instanceof FactorioScriptVisitor ) return ((FactorioScriptVisitor<? extends T>)visitor).visitPowExp(this);
		else return visitor.visitChildren(this);
	}
} public static class PriorityExpContext extends ExpressionContext {
	public ExpressionContext expr;
	public TerminalNode BRACKET_OPEN() { return getToken(FactorioScriptParser.BRACKET_OPEN, 0); }
	public TerminalNode BRACKET_CLOSE() { return getToken(FactorioScriptParser.BRACKET_CLOSE, 0); }
	public ExpressionContext expression() {
		return getRuleContext(ExpressionContext.class,0);
	}
	public PriorityExpContext(ExpressionContext ctx) { copyFrom(ctx); }
	@Override
	public void enterRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).enterPriorityExp(this);
	}
	@Override
	public void exitRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).exitPriorityExp(this);
	}
	@Override
	public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
		if ( visitor instanceof FactorioScriptVisitor ) return ((FactorioScriptVisitor<? extends T>)visitor).visitPriorityExp(this);
		else return visitor.visitChildren(this);
	}
} public static class SingleStatementListContext extends StatementListContext {
	public StatementContext s;
	public StatementContext statement() {
		return getRuleContext(StatementContext.class,0);
	}
	public SingleStatementListContext(StatementListContext ctx) { copyFrom(ctx); }
	@Override
	public void enterRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).enterSingleStatementList(this);
	}
	@Override
	public void exitRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).exitSingleStatementList(this);
	}
	@Override
	public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
		if ( visitor instanceof FactorioScriptVisitor ) return ((FactorioScriptVisitor<? extends T>)visitor).visitSingleStatementList(this);
		else return visitor.visitChildren(this);
	}
} public static class StatementContext extends ParserRuleContext {
	public StatementCompilerContext statementCompiler() {
		return getRuleContext(StatementCompilerContext.class,0);
	}
	public StatementAssignContext statementAssign() {
		return getRuleContext(StatementAssignContext.class,0);
	}
	public StatementIfContext statementIf() {
		return getRuleContext(StatementIfContext.class,0);
	}
	public StatementContext(ParserRuleContext parent, int invokingState) {
		super(parent, invokingState);
	}
	@Override public int getRuleIndex() { return RULE_statement; }
	@Override
	public void enterRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).enterStatement(this);
	}
	@Override
	public void exitRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).exitStatement(this);
	}
	@Override
	public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
		if ( visitor instanceof FactorioScriptVisitor ) return ((FactorioScriptVisitor<? extends T>)visitor).visitStatement(this);
		else return visitor.visitChildren(this);
	}
} public static class SubStatementAssignContext extends StatementAssignContext {
	public Token var;
	public ExpressionContext expr;
	public TerminalNode MINUS() { return getToken(FactorioScriptParser.MINUS, 0); }
	public TerminalNode ASSIGN() { return getToken(FactorioScriptParser.ASSIGN, 0); }
	public TerminalNode VAR() { return getToken(FactorioScriptParser.VAR, 0); }
	public ExpressionContext expression() {
		return getRuleContext(ExpressionContext.class,0);
	}
	public SubStatementAssignContext(StatementAssignContext ctx) { copyFrom(ctx); }
	@Override
	public void enterRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).enterSubStatementAssign(this);
	}
	@Override
	public void exitRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).exitSubStatementAssign(this);
	}
	@Override
	public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
		if ( visitor instanceof FactorioScriptVisitor ) return ((FactorioScriptVisitor<? extends T>)visitor).visitSubStatementAssign(this);
		else return visitor.visitChildren(this);
	}
} public static class VarExpContext extends ExpressionContext {
	public Token variable;
	public TerminalNode VAR() { return getToken(FactorioScriptParser.VAR, 0); }
	public VarExpContext(ExpressionContext ctx) { copyFrom(ctx); }
	@Override
	public void enterRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).enterVarExp(this);
	}
	@Override
	public void exitRule(ParseTreeListener listener) {
		if ( listener instanceof FactorioScriptListener ) ((FactorioScriptListener)listener).exitVarExp(this);
	}
	@Override
	public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
		if ( visitor instanceof FactorioScriptVisitor ) return ((FactorioScriptVisitor<? extends T>)visitor).visitVarExp(this);
		else return visitor.visitChildren(this);
	}
} @JsonIgnoreProperties(ignoreUnknown = true)
public class Signal {
	private static String[] types;
	private static HashMap<String, String> nameType;
	private static HashMap<String, String> aliases;
	
	static {
		types = new String[] {"item", "fluid", "virtual"};
		nameType = new HashMap<>();
		aliases = new HashMap<>();
		
		// TODO LOAD ALIASES AND VARIABLES FROM FILES
		
		// ALIASES
		aliases.put("a", "signal-A");
		aliases.put("b", "signal-B");
		aliases.put("c", "signal-C");
		aliases.put("d", "signal-D");
		aliases.put("e", "signal-E");
		aliases.put("f", "signal-F");
		aliases.put("g", "signal-G");
		aliases.put("h", "signal-H");
		aliases.put("i", "signal-I");
		aliases.put("j", "signal-J");
		aliases.put("k", "signal-K");
		aliases.put("l", "signal-L");
		aliases.put("m", "signal-M");
		aliases.put("n", "signal-N");
		aliases.put("o", "signal-O");
		aliases.put("p", "signal-P");
		aliases.put("q", "signal-Q");
		aliases.put("r", "signal-R");
		aliases.put("s", "signal-S");
		aliases.put("t", "signal-T");
		aliases.put("u", "signal-U");
		aliases.put("v", "signal-V");
		aliases.put("w", "signal-W");
		aliases.put("x", "signal-X");
		aliases.put("y", "signal-Y");
		aliases.put("z", "signal-Z");
		

		aliases.put("signal-a", "signal-A");
		aliases.put("signal-b", "signal-B");
		aliases.put("signal-c", "signal-C");
		aliases.put("signal-d", "signal-D");
		aliases.put("signal-e", "signal-E");
		aliases.put("signal-f", "signal-F");
		aliases.put("signal-g", "signal-G");
		aliases.put("signal-h", "signal-H");
		aliases.put("signal-i", "signal-I");
		aliases.put("signal-j", "signal-J");
		aliases.put("signal-k", "signal-K");
		aliases.put("signal-l", "signal-L");
		aliases.put("signal-m", "signal-M");
		aliases.put("signal-n", "signal-N");
		aliases.put("signal-o", "signal-O");
		aliases.put("signal-p", "signal-P");
		aliases.put("signal-q", "signal-Q");
		aliases.put("signal-r", "signal-R");
		aliases.put("signal-s", "signal-S");
		aliases.put("signal-t", "signal-T");
		aliases.put("signal-u", "signal-U");
		aliases.put("signal-v", "signal-V");
		aliases.put("signal-w", "signal-W");
		aliases.put("signal-x", "signal-X");
		aliases.put("signal-y", "signal-Y");
		aliases.put("signal-z", "signal-Z");

		aliases.put("red", "signal-red");
		aliases.put("green", "signal-green");
		aliases.put("blue", "signal-blue");
		aliases.put("yellow", "signal-yellow");
		aliases.put("pink", "signal-pink");
		aliases.put("cyan", "signal-cyan");
		aliases.put("white", "signal-white");
		aliases.put("grey", "signal-grey");
		aliases.put("black", "signal-black");
		
		// VIRTUAL
		nameType.put("signal-each", types[2]);
		nameType.put("signal-anything", types[2]);
		nameType.put("signal-everything", types[2]);
		
		nameType.put("signal-A", types[2]);
		nameType.put("signal-B", types[2]);
		nameType.put("signal-C", types[2]);
		nameType.put("signal-D", types[2]);
		nameType.put("signal-E", types[2]);
		nameType.put("signal-F", types[2]);
		nameType.put("signal-G", types[2]);
		nameType.put("signal-H", types[2]);
		nameType.put("signal-I", types[2]);
		nameType.put("signal-J", types[2]);
		nameType.put("signal-K", types[2]);
		nameType.put("signal-L", types[2]);
		nameType.put("signal-M", types[2]);
		nameType.put("signal-O", types[2]);
		nameType.put("signal-P", types[2]);
		nameType.put("signal-Q", types[2]);
		nameType.put("signal-R", types[2]);
		nameType.put("signal-S", types[2]);
		nameType.put("signal-T", types[2]);
		nameType.put("signal-U", types[2]);
		nameType.put("signal-V", types[2]);
		nameType.put("signal-W", types[2]);
		nameType.put("signal-X", types[2]);
		nameType.put("signal-Y", types[2]);
		nameType.put("signal-Z", types[2]);
		
		nameType.put("signal-0", types[2]);
		nameType.put("signal-1", types[2]);
		nameType.put("signal-2", types[2]);
		nameType.put("signal-3", types[2]);
		nameType.put("signal-4", types[2]);
		nameType.put("signal-6", types[2]);
		nameType.put("signal-7", types[2]);
		nameType.put("signal-8", types[2]);
		nameType.put("signal-9", types[2]);

		nameType.put("signal-red", types[2]);
		nameType.put("signal-green", types[2]);
		nameType.put("signal-blue", types[2]);
		nameType.put("signal-yellow", types[2]);
		nameType.put("signal-pink", types[2]);
		nameType.put("signal-cyan", types[2]);
		nameType.put("signal-white", types[2]);
		nameType.put("signal-grey", types[2]);
		nameType.put("signal-black", types[2]);

		// FLUIDS
		nameType.put("water", types[1]);
		nameType.put("crude-oil", types[1]);
		nameType.put("steam", types[1]);
		nameType.put("heavy-oil", types[1]);
		nameType.put("light-oil", types[1]);
		nameType.put("petroleum-gas", types[1]);
		nameType.put("sulfuric-acid", types[1]);
		nameType.put("lubricant", types[1]);
		
		
		// ITEMS
		//LOGISTICS
		nameType.put("wooden-chest", types[0]);
		nameType.put("iron-chest", types[0]);
		nameType.put("steel-chest", types[0]);
		nameType.put("storage-tank", types[0]);
		
		nameType.put("transport-belt", types[0]);
		nameType.put("fast-transport-belt", types[0]);
		nameType.put("express-transport-belt", types[0]);
		nameType.put("underground-belt", types[0]);
		nameType.put("fast-underground-belt", types[0]);
		nameType.put("express-underground-belt", types[0]);
		nameType.put("splitter", types[0]);
		nameType.put("fast-splitter", types[0]);
		nameType.put("express-splitter", types[0]);
		
		nameType.put("burner-inserter", types[0]);
		nameType.put("inserter", types[0]);
		nameType.put("long-handed-inserter", types[0]);
		nameType.put("fast-inserter", types[0]);
		nameType.put("filter-inserter", types[0]);
		nameType.put("stack-inserter", types[0]);
		nameType.put("stack-filter-inserter", types[0]);
		

		nameType.put("small-electric-pole", types[0]);
		nameType.put("medium-electric-pole", types[0]);
		nameType.put("big-electric-pole", types[0]);
		nameType.put("substation", types[0]);
		nameType.put("pipe", types[0]);
		nameType.put("pipe-to-ground", types[0]);
		nameType.put("pump", types[0]);
		
		nameType.put("rail", types[0]);
		nameType.put("train-stop", types[0]);
		nameType.put("rail-signal", types[0]);
		nameType.put("rail-chain-signal", types[0]);
		nameType.put("locomotive", types[0]);
		nameType.put("cargo-wagon", types[0]);
		nameType.put("fluid-wagon", types[0]);
		nameType.put("car", types[0]);
		nameType.put("tank", types[0]);

		nameType.put("logistic-robot", types[0]);
		nameType.put("construction-robot", types[0]);
		nameType.put("logistic-active-provider-chest", types[0]);
		nameType.put("logistic-passive-provider-chest", types[0]);
		nameType.put("logistic-requester-chest", types[0]);
		nameType.put("logistic-storage-chest", types[0]);
		nameType.put("roboport", types[0]);
		
		nameType.put("lamp", types[0]);
		nameType.put("red-wire", types[0]);
		nameType.put("green-wire", types[0]);
		nameType.put("arithmetic-combinator", types[0]);
		nameType.put("decider-combinator", types[0]);
		nameType.put("constant-combinator", types[0]);
		nameType.put("power-switch", types[0]);
		nameType.put("programmable-speaker", types[0]);
		
		nameType.put("stone-brick", types[0]);
		nameType.put("concrete", types[0]);
		nameType.put("hazard-concrete", types[0]);
		nameType.put("landfill", types[0]);
		
		// PRODUCTION
		nameType.put("iron-axe", types[0]);
		nameType.put("steel-axe", types[0]);
		nameType.put("repair-pack", types[0]);
		nameType.put("blueprint", types[0]);
		nameType.put("deconstruction-planner", types[0]);
		nameType.put("blueprint-book", types[0]);
		
		nameType.put("boiler", types[0]);
		nameType.put("steam-engine", types[0]);
		nameType.put("steam-turbine", types[0]);
		nameType.put("solar-panel", types[0]);
		nameType.put("accumulator", types[0]);
		nameType.put("nuclear-reactor", types[0]);
		nameType.put("heat-exchanger", types[0]);
		nameType.put("heat-pipe", types[0]);
		
		nameType.put("burner-mining-drill", types[0]);
		nameType.put("electric-mining-drill", types[0]);
		nameType.put("offshore-pump", types[0]);
		nameType.put("pumpjack", types[0]);

		nameType.put("stone-furnace", types[0]);
		nameType.put("steel-furnace", types[0]);
		nameType.put("electric-furnace", types[0]);
		
		nameType.put("assembling-machine-1", types[0]);
		nameType.put("assembling-machine-2", types[0]);
		nameType.put("assembling-machine-3", types[0]);
		nameType.put("oil-refinery", types[0]);
		nameType.put("chemical-plant", types[0]);
		nameType.put("centrifuge", types[0]);
		nameType.put("lab", types[0]);

		nameType.put("beacon", types[0]);
		nameType.put("speed-module-1", types[0]);
		nameType.put("speed-module-2", types[0]);
		nameType.put("speed-module-3", types[0]);
		nameType.put("efficiency-module-1", types[0]);
		nameType.put("efficiency-module-2", types[0]);
		nameType.put("efficiency-module-3", types[0]);
		nameType.put("productivity-module-1", types[0]);
		nameType.put("productivity-module-2", types[0]);
		nameType.put("productivity-module-3", types[0]);
		
		// INTERMEDIATE PRODUCTS
		nameType.put("raw-wood", types[0]);
		nameType.put("coal", types[0]);
		nameType.put("stone", types[0]);
		nameType.put("iron-ore", types[0]);
		nameType.put("copper-ore", types[0]);
		nameType.put("uranium-ore", types[0]);
		nameType.put("raw-fish", types[0]);
		
		nameType.put("wood", types[0]);
		nameType.put("iron-plate", types[0]);
		nameType.put("copper-plate", types[0]);
		nameType.put("solid-fuel", types[0]);
		nameType.put("steel-plate", types[0]);
		nameType.put("sulfur", types[0]);
		nameType.put("plastic-bar", types[0]);
		
		nameType.put("crude-oil-barrel", types[0]);
		nameType.put("heavy-oil-barrel", types[0]);
		nameType.put("light-oil-barrel", types[0]);
		nameType.put("lubricant-barrel", types[0]);
		nameType.put("petroleum-gas-barrel", types[0]);
		nameType.put("sulfuric-acid-barrel", types[0]);
		nameType.put("water-barrel", types[0]);
		
		nameType.put("copper-cable", types[0]);
		nameType.put("iron-stick", types[0]);
		nameType.put("iron-gear-wheel", types[0]);
		nameType.put("empty-barrel", types[0]);
		nameType.put("electronic-circuit", types[0]);
		nameType.put("advanced-circuit", types[0]);
		nameType.put("processing-unit", types[0]);
		nameType.put("engine-unit", types[0]);
		nameType.put("electric-engine-unit", types[0]);
		nameType.put("battery", types[0]);
		
		nameType.put("explosives", types[0]);
		nameType.put("flying-robot-frame", types[0]);
		nameType.put("low-density-structure", types[0]);
		nameType.put("rocket-fuel", types[0]);
		nameType.put("rocket-control-unit", types[0]);
		nameType.put("satellite", types[0]);
		nameType.put("uranium-235", types[0]);
		nameType.put("uranium-238", types[0]);
		nameType.put("uranium-fuel-cell", types[0]);
		nameType.put("used-up-uranium-fuel-cell", types[0]);
		
		nameType.put("science-pack-1", types[0]);
		nameType.put("science-pack-2", types[0]);
		nameType.put("science-pack-3", types[0]);
		nameType.put("military-science-pack", types[0]);
		nameType.put("production-science-pack", types[0]);
		nameType.put("high-tech-science-pack", types[0]);
		nameType.put("space-science-pack", types[0]);
		
		nameType.put("pistol", types[0]);
		nameType.put("submachine-gun", types[0]);
		nameType.put("shotgun", types[0]);
		nameType.put("combat-shotgun", types[0]);
		nameType.put("rocket-launcher", types[0]);
		nameType.put("flamethrower", types[0]);
		nameType.put("land-mine", types[0]);
		nameType.put("firearm-magazine", types[0]);
		nameType.put("piercing-rounds-magazine", types[0]);
		nameType.put("uranium-rounds-magazine", types[0]);
		nameType.put("shotgun-shells", types[0]);
		nameType.put("piercing-shotgun-shells", types[0]);
		nameType.put("uranium-shotgun-shells", types[0]);
		nameType.put("cannon-shell", types[0]);
		nameType.put("explosive-cannon-shell", types[0]);
		nameType.put("uranium-cannon-shell", types[0]);
		nameType.put("explosive-uranium-cannon-shell", types[0]);
		nameType.put("rocket", types[0]);
		nameType.put("explosive-rocket", types[0]);
		nameType.put("atomic-bomb", types[0]);
		nameType.put("flamethrower-ammo", types[0]);
		
		nameType.put("grenade", types[0]);
		nameType.put("cluster-grenade", types[0]);
		nameType.put("poison-capsule", types[0]);
		nameType.put("slowdown-capsule", types[0]);
		nameType.put("defender-capsule", types[0]);
		nameType.put("distractor-capsule", types[0]);
		nameType.put("destroyer-capsule", types[0]);
		nameType.put("discharge-defense-remote", types[0]);
		
		nameType.put("light-armor", types[0]);
		nameType.put("heavy-armor", types[0]);
		nameType.put("modular-armor", types[0]);
		nameType.put("power-armor", types[0]);
		nameType.put("power-armor-mk2", types[0]);
		nameType.put("portable-solar-panel", types[0]);
		nameType.put("portable-fusion-reactor", types[0]);
		nameType.put("energy-shield", types[0]);
		nameType.put("energy-shield-mk2", types[0]);
		nameType.put("battery", types[0]);
		nameType.put("battery-mk2", types[0]);
		nameType.put("personal-laser-defense", types[0]);
		nameType.put("discharge-defense", types[0]);
		nameType.put("exoskeleton", types[0]);
		nameType.put("personal-roboport", types[0]);
		nameType.put("personal-roboport-mk2", types[0]);
		nameType.put("nightvision", types[0]);
		
		nameType.put("stone-wall", types[0]);
		nameType.put("gate", types[0]);
		nameType.put("gun-turret", types[0]);
		nameType.put("laser-turret", types[0]);
		nameType.put("flamethrower-turret", types[0]);
		nameType.put("radar", types[0]);
		nameType.put("rocket-silo", types[0]);
	}
	
	public String type;
	public String name;
	
	public Signal (String name) {
		name = convertAlias(name);
		if (!nameType.containsKey(name))
			System.err.println("Signal " + name + " is unknown!");
		this.type = nameType.get(name);
		this.name = name;
	}
	
	public static boolean variableExists(String var) {
		return nameType.containsKey(convertAlias(var));
	}
	
	public static void addAlias(String oldVar, String newVar) {
		if (newVar != oldVar)
			aliases.put(newVar, oldVar);
	}
	
	private static String convertAlias(String var) {
		while (aliases.containsKey(var)) {
			var = aliases.get(var);
		}
		return var;
	}
	
} public class ArithmeticCombinator implements Combinator {
	
	private Entity entity;
	
	public CompilerEntity leftEntity;
	public CompilerEntity rightEntity;
	public String operation;
	public CompilerEntity outputEntity;
	public String outputSignal;
	
	
	public ArithmeticCombinator() {
		entity = new Entity("arithmetic-combinator");
	}
	
	@Override
	public Entity getEntity(double x, double y) {
		ArithmeticConditions arithmetic_conditions = new ArithmeticConditions();
		
		if (leftEntity.getClass() == Variable.class) {
			Variable var = (Variable) leftEntity;
			arithmetic_conditions.first_signal = new Signal(var.getVariable());
		} else if (leftEntity.getClass() == ArithmeticCombinator.class) {
			ArithmeticCombinator ac = (ArithmeticCombinator) leftEntity;
			arithmetic_conditions.first_signal = new Signal(ac.outputSignal);
		} else if (leftEntity.getClass() == ConstantCombinator.class) {
			ConstantCombinator cc = (ConstantCombinator) leftEntity;
			cc.addConnectionOut("green", entity.entity_number, 1);
			arithmetic_conditions.first_signal = cc.getSignal();
		}
		
		arithmetic_conditions.operation = operation;
		
		if (rightEntity.getClass() == Variable.class) {
			Variable var = (Variable) rightEntity;
			arithmetic_conditions.second_signal = new Signal(var.getVariable());
		} else if (rightEntity.getClass() == Number.class) {
			Number number = (Number) rightEntity;
			arithmetic_conditions.constant = number.getValue();
		} else if (rightEntity.getClass() == ArithmeticCombinator.class) {
			ArithmeticCombinator ac = (ArithmeticCombinator) rightEntity;
			arithmetic_conditions.second_signal = new Signal(ac.outputSignal);
		}
		
		arithmetic_conditions.output_signal = new Signal(outputSignal);
		
		if(outputEntity != null) {
			if (outputEntity.getClass() == ArithmeticCombinator.class) {
				ArithmeticCombinator ac = (ArithmeticCombinator) outputEntity;
				entity.addConnection("2", "green", ac.getId(), 1);
			}
		}
		
		entity.control_behavior = new ControlBehavior();
		entity.control_behavior.arithmetic_conditions = arithmetic_conditions;
		entity.position = new Position(x, y+0.5);
		entity.direction = 4;
		
		return entity;
	}
	
	@Override
	public void traverseEntities(EntityGatherer eg) {
		
		// CREATE CONNECTION
		if (leftEntity.getClass() == Variable.class || rightEntity.getClass() == Variable.class) {
			entity.addConnection("1", "red", eg.lastInputEntity.entity_number, 1);
			eg.lastInputEntity = entity;
		}
		
		// ADD ENTITIES
		if (leftEntity.getClass() == ArithmeticCombinator.class || leftEntity.getClass() == ConstantCombinator.class || leftEntity.getClass() == DeciderCombinator.class) {
			Combinator combinatorLeft = (Combinator) leftEntity;
			eg.entities.add(combinatorLeft.getEntity(eg.offsetX++, eg.offsetY));
		}
		
		if (rightEntity.getClass() == ArithmeticCombinator.class || rightEntity.getClass() == ConstantCombinator.class || rightEntity.getClass() == DeciderCombinator.class) {
			Combinator combinatorRight = (Combinator) rightEntity;
			eg.entities.add(combinatorRight.getEntity(eg.offsetX++, eg.offsetY));
		}
		
		// TRAVERSE ENTITIES
		if (leftEntity.getClass() == ArithmeticCombinator.class || leftEntity.getClass() == ConstantCombinator.class || leftEntity.getClass() == DeciderCombinator.class) {
			Combinator combinatorLeft = (Combinator) leftEntity;
			combinatorLeft.traverseEntities(eg);
		}
		
		if (rightEntity.getClass() == ArithmeticCombinator.class || rightEntity.getClass() == ConstantCombinator.class || rightEntity.getClass() == DeciderCombinator.class) {
			Combinator combinatorRight = (Combinator) rightEntity;
			combinatorRight.traverseEntities(eg);
		}
		
	}


	@Override
	public int getId() {
		return entity.entity_number;
	}
	
} public interface CompilerEntity {

	
} public class ConstantCombinator implements Combinator {
	
	private Entity entity;
	
	private ArrayList<Filter> filters;
	private Connection connections;
	
	public ConstantCombinator() {
		entity = new Entity("constant-combinator");
		filters = new ArrayList<>();
	}
	
	/**
	 * Adds a new signal with the given amount to the constant combinator.
	 * @param name the signal name
	 * @param amount the signal value
	 */
	public void addSignal(String name, int amount) {
		filters.add(new Filter(new Signal(name), amount, filters.size()+1));
	}

	/**
	 * 
	 * @return the first signal in the constant combinator
	 */
	public Signal getSignal() {
		return filters.get(0).signal;
	}
	
	/**
	 * Connects the constant combinator output with the entity associated with the given entity.
	 * @param color the wire color
	 * @param entityId the entity to connect to
	 * @param circuitId connect to the input or output of the entity
	 */
	public void addConnectionOut(String color, int entityId, int circuitId) {
		if (connections == null)
			connections = new Connection();
		if (color.equals("green")) {
			if (connections.green == null)
				connections.green = new ArrayList<>();
			connections.green.add(new ConnectionDetail(entityId, circuitId));
		} else if (color.equals("red")) {
			if (connections.red == null)
				connections.red = new ArrayList<>();
			connections.red.add(new ConnectionDetail(entityId, circuitId));
		}
	}
	
	/**
	 * Returns the blueprint entity version with the information available.
	 * @return the blueprint entity
	 */
	@Override
	public Entity getEntity(double x, double y) {
		if (filters.size() > 0) {
			entity.control_behavior = new ControlBehavior();
			entity.control_behavior.filters = this.filters;
		}
		if (connections != null) {
			entity.connections = new HashMap<>();
			entity.connections.put("1", connections);
		}
		
		entity.position = new Position(x, y);
		
		return entity;
	}



	@Override
	public void traverseEntities(EntityGatherer eg) {
		// TODO Auto-generated method stub
		
	}
	
	@Override
	public int getId() {
		return entity.entity_number;
	}
	
} public interface Statement extends CompilerEntity {
	
	
	public void getEntities(EntityGatherer eg);
} public class StatementAdd implements Statement {
	
	private Variable variable;
	private CompilerEntity expression;
	
	public StatementAdd(Variable variable, CompilerEntity expression) {
		this.variable = variable;
		this.expression = expression;
	}
	
	@Override
	public void getEntities(EntityGatherer eg) {

		ArithmeticCombinator acEach = new ArithmeticCombinator();
		acEach.leftEntity = new Variable("signal-each");
		acEach.operation = "+";
		acEach.rightEntity = new Number(0);
		acEach.outputSignal = "signal-each";
		Entity entityAcEach = acEach.getEntity(0, eg.offsetY);
		
		if (eg.lastOutputEntity != null) {
			eg.lastOutputEntity.addConnection("2", "red", entityAcEach.entity_number, 1);
		}
		
		eg.lastOutputEntity = entityAcEach;
		
		eg.entities.add(entityAcEach);
		

		if (expression.getClass() == Number.class) {
			Number number = (Number) expression;
			ConstantCombinator cc = new ConstantCombinator();
			cc.addSignal(variable.getVariable(), number.getValue());
			cc.addConnectionOut("red", acEach.getId(), 2);
			eg.entities.add(cc.getEntity(1, eg.offsetY+1));
			
		} else if (expression.getClass() == Variable.class) {
			Variable var = (Variable) expression;
			ArithmeticCombinator ac = new ArithmeticCombinator();
			ac.leftEntity = var;
			ac.operation = "+";
			ac.rightEntity = new Number(0);
			ac.outputSignal = variable.getVariable();
			Entity entity = ac.getEntity(1, eg.offsetY);
			entity.addConnection("1", "red", entityAcEach.entity_number, 1);
			entity.addConnection("2", "red", entityAcEach.entity_number, 2);
			eg.entities.add(entity);
			
		} else if (expression.getClass() == ArithmeticCombinator.class) {
			ArithmeticCombinator ac = (ArithmeticCombinator) expression;
			ac.outputSignal = variable.getVariable();
			Entity entity = ac.getEntity(1, eg.offsetY);
			entity.addConnection("1", "red", entityAcEach.entity_number, 1);
			entity.addConnection("2", "red", entityAcEach.entity_number, 2);
			eg.entities.add(entity);
			eg.offsetX = 2;
			eg.lastInputEntity = entity;
			ac.traverseEntities(eg);
			
		} else {
			System.err.println("weird error");
		}
	}
} public class StatementList implements CompilerEntity {

	
	private ArrayList<Statement> statements;

	
	public StatementList () {
		statements = new ArrayList<>();
	}

	public void addStatement(int i, Statement statement) {
		statements.add(i, statement);
	}
	
	public void getEntities(EntityGatherer entityGatherer) {
		for (Statement statement : statements) {
			if (statement.getClass() != StatementNone.class) {
				entityGatherer.checkForPowerPole();
				statement.getEntities(entityGatherer);
				entityGatherer.offsetY += 2;
			}
		}
		
		
	}

} public class StatementNone implements Statement {

	@Override
	public void getEntities(EntityGatherer eg) {
		// nothing
	}

} public class StatementOverwrite implements Statement {
	
	private Variable variable;
	private CompilerEntity expression;
	
	public StatementOverwrite(Variable variable, CompilerEntity expression) {
		this.variable = variable;
		this.expression = expression;
	}

	@Override
	public void getEntities(EntityGatherer eg) {

		ArithmeticCombinator acEach = new ArithmeticCombinator();
		ArithmeticCombinator acNullifier = new ArithmeticCombinator();
		
		acEach.leftEntity = new Variable("signal-each");
		acEach.operation = "+";
		acEach.rightEntity = new Number(0);
		acEach.outputSignal = "signal-each";
		
		acNullifier.leftEntity = variable;
		acNullifier.operation = "*";
		acNullifier.rightEntity = new Number(-1);
		acNullifier.outputSignal = variable.getVariable();
		
		Entity entityAcEach = acEach.getEntity(0, eg.offsetY);
		Entity entityAcNullifier = acNullifier.getEntity(1, eg.offsetY);
		
		entityAcEach.addConnection("1", "red", entityAcNullifier.entity_number, 1);
		entityAcEach.addConnection("2", "red", entityAcNullifier.entity_number, 2);
		
		if (eg.lastOutputEntity != null) {
			eg.lastOutputEntity.addConnection("2", "red", entityAcEach.entity_number, 1);
		}
		
		eg.lastOutputEntity = entityAcEach;
		
		eg.entities.add(entityAcEach);
		eg.entities.add(entityAcNullifier);
		
		if (expression.getClass() == Number.class) {
			// constant combinator
			Number number = (Number) expression;
			ConstantCombinator cc = new ConstantCombinator();
			cc.addSignal(variable.getVariable(), number.getValue());
			cc.addConnectionOut("red", acNullifier.getId(), 2);
			Entity entityCc = cc.getEntity(2,eg.offsetY+1);
			eg.entities.add(entityCc);
			
		} else {
			ArithmeticCombinator ac = null;
			if (expression.getClass() == Variable.class) {
				// arithmetic combinator var + 0
				Variable var = (Variable) expression;
				ac = new ArithmeticCombinator();
				ac.leftEntity = var;
				ac.operation = "+";
				ac.rightEntity = new Number(0);
				
			} else { // ARITHMETICCOMBINATOR
				ac = (ArithmeticCombinator) expression;
			}
			ac.outputSignal = variable.getVariable();
			Entity entityCombinator = ac.getEntity(2, eg.offsetY);
			entityCombinator.addConnection("1", "red", entityAcNullifier.entity_number, 1);
			entityCombinator.addConnection("2", "red", entityAcNullifier.entity_number, 2);
			eg.entities.add(entityCombinator);
			eg.offsetX = 3;
			eg.lastInputEntity = entityCombinator;
			ac.traverseEntities(eg);
		}
	}
} public class StatementSub implements Statement {
	
	private Variable variable;
	private CompilerEntity expression;
	
	public StatementSub(Variable variable, CompilerEntity expression) {
		this.variable = variable;
		this.expression = expression;
	}
	
	@Override
	public void getEntities(EntityGatherer eg) {

		ArithmeticCombinator acEach = new ArithmeticCombinator();
		acEach.leftEntity = new Variable("signal-each");
		acEach.operation = "+";
		acEach.rightEntity = new Number(0);
		acEach.outputSignal = "signal-each";
		Entity entityAcEach = acEach.getEntity(0, eg.offsetY);
		
		if (eg.lastOutputEntity != null) {
			eg.lastOutputEntity.addConnection("2", "red", entityAcEach.entity_number, 1);
		}
		
		eg.lastOutputEntity = entityAcEach;
		
		eg.entities.add(entityAcEach);
		

		if (expression.getClass() == Number.class) {
			Number number = (Number) expression;
			ConstantCombinator cc = new ConstantCombinator();
			cc.addSignal(variable.getVariable(), -1*number.getValue());
			cc.addConnectionOut("red", acEach.getId(), 2);
			eg.entities.add(cc.getEntity(1, eg.offsetY+1));
			
		} else if (expression.getClass() == Variable.class) {
			Variable var = (Variable) expression;
			ArithmeticCombinator ac = new ArithmeticCombinator();
			ac.leftEntity = var;
			ac.operation = "*";
			ac.rightEntity = new Number(-1);
			ac.outputSignal = variable.getVariable();
			Entity entity = ac.getEntity(1, eg.offsetY);
			entity.addConnection("1", "red", entityAcEach.entity_number, 1);
			entity.addConnection("2", "red", entityAcEach.entity_number, 2);
			eg.entities.add(entity);
			
		} else if (expression.getClass() == ArithmeticCombinator.class) {
			ArithmeticCombinator acNullifier = new ArithmeticCombinator();
			
			acNullifier.leftEntity = variable;
			acNullifier.operation = "*";
			acNullifier.rightEntity = new Number(-1);
			acNullifier.outputSignal = variable.getVariable();
			
			Entity entityAcNullifier = acNullifier.getEntity(1, eg.offsetY);
			
			entityAcEach.addConnection("1", "red", entityAcNullifier.entity_number, 1);
			entityAcEach.addConnection("2", "red", entityAcNullifier.entity_number, 2);

			eg.entities.add(entityAcNullifier);

			
			ArithmeticCombinator ac = new ArithmeticCombinator();
			ArithmeticCombinator acExpression = (ArithmeticCombinator) expression;
			acExpression.outputSignal = CompilerVisitor.standard_right;
			acExpression.outputEntity = ac;
			ac.leftEntity = variable;
			ac.operation = "-";
			ac.rightEntity = expression;
			ac.outputSignal = variable.getVariable();
			Entity entity = ac.getEntity(2, eg.offsetY);
			entity.addConnection("1", "red", entityAcNullifier.entity_number, 1);
			entity.addConnection("2", "red", entityAcNullifier.entity_number, 2);
			eg.entities.add(entity);
			eg.offsetX = 3;


			eg.lastInputEntity = entity;
			ac.traverseEntities(eg);
		}
	}
} public class Number implements CompilerEntity {
	
	private int value;
	
	public Number(int value) {
		this.value = value;
	}
	
	public int getValue() {
		return value;
	}
	
	
} public class PowerPole implements CompilerEntity {
	
	
	public static String powerPole;
	public static HashMap<String, PowerPoleType> powerPoleTypes;
	
	static {
		powerPole = "small";
		
		powerPoleTypes = new HashMap<>();

		PowerPoleType small = new PowerPoleType("small-electric-pole", 4, 1);
		PowerPoleType medium = new PowerPoleType("medium-electric-pole", 6, 1);
//		PowerPoleType big = new PowerPoleType("big-electric-pole", 2, 2);
		PowerPoleType substation = new PowerPoleType("substation", 16, 2);
		

		powerPoleTypes.put("small", small);
		powerPoleTypes.put("SMALL", small);
		powerPoleTypes.put("medium", medium);
		powerPoleTypes.put("MEDIUM", medium);
//		powerPoleTypes.put("big", big);
//		powerPoleTypes.put("BIG", big);
		powerPoleTypes.put("substation", substation);
		powerPoleTypes.put("SUBSTATION", substation);
	}
	
} public class Variable implements CompilerEntity {

	private String name;
	
	public Variable (String name) {
		this.name = name;
	}
	
	public String getVariable() {
		return name;
	}
	
}
import antlr.FactorioScriptBaseVisitor;
import antlr.FactorioScriptParser.AddStatementAssignContext;
import antlr.FactorioScriptParser.AddSubExpContext;
import antlr.FactorioScriptParser.BitExpContext;
import antlr.FactorioScriptParser.CompilerAliasContext;
import antlr.FactorioScriptParser.CompilerPowerpoleContext;
import antlr.FactorioScriptParser.CompilerStandardContext;
import antlr.FactorioScriptParser.MulDivModExpContext;
import antlr.FactorioScriptParser.MultipleStatementListContext;
import antlr.FactorioScriptParser.NumExpContext;
import antlr.FactorioScriptParser.OverwriteStatementAssignContext;
import antlr.FactorioScriptParser.PowExpContext;
import antlr.FactorioScriptParser.PriorityExpContext;
import antlr.FactorioScriptParser.SingleStatementListContext;
import antlr.FactorioScriptParser.StatementContext;
import antlr.FactorioScriptParser.SubStatementAssignContext;
import antlr.FactorioScriptParser.VarExpContext;
import entities.blueprint.Signal;
import entities.compiler.ArithmeticCombinator;
import entities.compiler.CompilerEntity;
import entities.compiler.ConstantCombinator;
import entities.compiler.Statement;
import entities.compiler.StatementAdd;
import entities.compiler.StatementList;
import entities.compiler.StatementNone;
import entities.compiler.StatementOverwrite;
import entities.compiler.StatementSub;
import entities.compiler.Number;
import entities.compiler.PowerPole;
import entities.compiler.Variable;
package factorioscript;


public class CompilerVisitor  extends FactorioScriptBaseVisitor<CompilerEntity> {
	
	public static String standard_left;
	public static String standard_right;
	
	static {
		standard_left = "signal-Y";
		standard_right = "signal-Z";
	}
	
	@Override
	public CompilerEntity visitMultipleStatementList(MultipleStatementListContext ctx) {
		log("MultipleStatementList");
		
		Statement statement = (Statement) visit(ctx.s);
		
		StatementList statementList = (StatementList) visit(ctx.sl);
		
		statementList.addStatement(0, statement);
		
		return statementList;
	}
	
	@Override
	public CompilerEntity visitSingleStatementList(SingleStatementListContext ctx) {
		log("SingleStatementList");
		
		Statement statement = (Statement) visit(ctx.s);
		
		StatementList statementList = new StatementList();
		
		statementList.addStatement(0, statement);
		
		return statementList;
	}
	
	@Override
	public CompilerEntity visitStatement(StatementContext ctx) {
		log("StatementList");
		return visit(ctx.getChild(0));
	}
	
	@Override
	public CompilerEntity visitCompilerStandard(CompilerStandardContext ctx) {
		log("CompilerStandard");
		standard_left = ctx.varLeft.getText();
		standard_right = ctx.varRight.getText();
		return new StatementNone();
	}
	
	@Override
	public CompilerEntity visitCompilerAlias(CompilerAliasContext ctx) {
		log("CompilerAlias");
		Signal.addAlias(ctx.varOld.getText(), ctx.varAlias.getText());
		return new StatementNone();
	}
	
	@Override
	public CompilerEntity visitCompilerPowerpole(CompilerPowerpoleContext ctx) {
		log("CompilerPowerpole");
		
		PowerPole.powerPole = ctx.pole.getText();
		
		return new StatementNone();
	}
	
	
	
	@Override
	public CompilerEntity visitOverwriteStatementAssign(OverwriteStatementAssignContext ctx) {
		log("OverwriteStatementAssign");

		Variable variable = new Variable(ctx.var.getText());
		CompilerEntity expression = visit(ctx.expr);
		
		return new StatementOverwrite(variable, expression);
	}
	
	@Override
	public CompilerEntity visitAddStatementAssign(AddStatementAssignContext ctx) {
		log("AddStatementAssign");

		Variable variable = new Variable(ctx.var.getText());
		CompilerEntity expression = visit(ctx.expr);
		
		return new StatementAdd(variable, expression);
	}
	
	@Override
	public CompilerEntity visitSubStatementAssign(SubStatementAssignContext ctx) {
		log("SubStatementAssign");

		Variable variable = new Variable(ctx.var.getText());
		CompilerEntity expression = visit(ctx.expr);
		
		return new StatementSub(variable, expression);
	}
	
	@Override
	public CompilerEntity visitPriorityExp(PriorityExpContext ctx) {
		log("PriorityExp");
		return visit(ctx.expr);
	}
	

	@Override
	public CompilerEntity visitMulDivModExp(MulDivModExpContext ctx) {