// Path: Code/src/main/java/otld/otld/intermediate/exceptions/FunctionAlreadyDeclared.java
// public class FunctionAlreadyDeclared extends ElementException {
// }
// 
// Path: Code/src/main/java/otld/otld/intermediate/exceptions/TypeMismatch.java
// public class TypeMismatch extends ElementException {
// }
// 
// Path: Code/src/main/java/otld/otld/intermediate/exceptions/VariableAlreadyDeclared.java
// public class VariableAlreadyDeclared extends ElementException {
// }


import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeProperty;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.antlr.v4.runtime.tree.TerminalNode;
import otld.otld.grammar.otldBaseListener;
import otld.otld.grammar.otldLexer;
import otld.otld.grammar.otldParser;
import otld.otld.intermediate.*;
import otld.otld.intermediate.exceptions.FunctionAlreadyDeclared;
import otld.otld.intermediate.exceptions.TypeMismatch;
import otld.otld.intermediate.exceptions.VariableAlreadyDeclared;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
            }
        } else {
            errors.add(new Error(ctx.ID().getSymbol().getLine(),
                    ctx.ID().getSymbol().getCharPositionInLine(),
                    ErrorMsg.RESERVEDNAME.getMessage()));
        }
    }

    @Override
    public void enterFactory(otldParser.FactoryContext ctx) {
        ArrayList<Type> types = new ArrayList<>(ctx.CARGO().size());
        for (TerminalNode n : ctx.CARGO()) {
            Type type = getType(n.getText());

            if (type != null) {
                types.add(type);
            } else {
                errors.add(new Error(ctx.CARGO().get(ctx.CARGO().indexOf(n)).getSymbol().getLine(),
                        ctx.CARGO().get(ctx.CARGO().indexOf(n)).getSymbol().getCharPositionInLine(),
                        ErrorMsg.TYPENOTDEFINED.getMessage()));
            }
        }

        try {
            Type[] typeArr = new Type[types.size()];
            Function function = new Function(ctx.ID().getText(), types.toArray(typeArr));
            city.addFunction(function);
            functions.put(ctx.deffactory(), function);
            //Set the lastFunction to this so code that is part of the factory body can access it's platforms
            lastFunction = function;
// Path: Code/src/main/java/otld/otld/intermediate/exceptions/FunctionAlreadyDeclared.java
// public class FunctionAlreadyDeclared extends ElementException {
// }
// 
// Path: Code/src/main/java/otld/otld/intermediate/exceptions/TypeMismatch.java
// public class TypeMismatch extends ElementException {
// }
// 
// Path: Code/src/main/java/otld/otld/intermediate/exceptions/VariableAlreadyDeclared.java
// public class VariableAlreadyDeclared extends ElementException {
// }


// Path: Code/src/main/java/otld/otld/parsing/OTLDListener.java
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeProperty;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.antlr.v4.runtime.tree.TerminalNode;
import otld.otld.grammar.otldBaseListener;
import otld.otld.grammar.otldLexer;
import otld.otld.grammar.otldParser;
import otld.otld.intermediate.*;
import otld.otld.intermediate.exceptions.FunctionAlreadyDeclared;
import otld.otld.intermediate.exceptions.TypeMismatch;
import otld.otld.intermediate.exceptions.VariableAlreadyDeclared;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

            }
        } else {
            errors.add(new Error(ctx.ID().getSymbol().getLine(),
                    ctx.ID().getSymbol().getCharPositionInLine(),
                    ErrorMsg.RESERVEDNAME.getMessage()));
        }
    }

    @Override
    public void enterFactory(otldParser.FactoryContext ctx) {
        ArrayList<Type> types = new ArrayList<>(ctx.CARGO().size());
        for (TerminalNode n : ctx.CARGO()) {
            Type type = getType(n.getText());

            if (type != null) {
                types.add(type);
            } else {
                errors.add(new Error(ctx.CARGO().get(ctx.CARGO().indexOf(n)).getSymbol().getLine(),
                        ctx.CARGO().get(ctx.CARGO().indexOf(n)).getSymbol().getCharPositionInLine(),
                        ErrorMsg.TYPENOTDEFINED.getMessage()));
            }
        }

        try {
            Type[] typeArr = new Type[types.size()];
            Function function = new Function(ctx.ID().getText(), types.toArray(typeArr));
            city.addFunction(function);
            functions.put(ctx.deffactory(), function);
            //Set the lastFunction to this so code that is part of the factory body can access it's platforms
            lastFunction = function;
        } catch (FunctionAlreadyDeclared functionAlreadyDeclared) {