//-----------------------------------------------------------
        private Type Visit(Identifier node, Table table)
        {
            GlobalSymbolTable gstable = table as GlobalSymbolTable;
            LocalSymbolTable  lstable = table as LocalSymbolTable;

            var symbolName = node.AnchorToken.Lexeme;

            if (table is GlobalSymbolTable)
            {
                if (gstable.Contains(symbolName))
                {
                    return(gstable[symbolName].TheType);
                }
                throw new SemanticError("Undeclared variable: " + symbolName, node.AnchorToken);
            }
            else if (table is LocalSymbolTable)
            {
                if (lstable.Contains(symbolName))
                {
                    return(lstable[symbolName].LocalType);
                }
                if (GSTable.Contains(symbolName))
                {
                    return(GSTable[symbolName].TheType);
                }
                throw new SemanticError("Undeclared variable: " + symbolName, node.AnchorToken);
            }
            else
            {
                throw new TypeAccessException("Expecting either a GlobalSymbolTable or a LocalSymboltable");
            }
        }
        //-----------------------------------------------------------
        private Type Visit(AssignmentStatement node, Table table)
        {
            Type leftExpressionType  = Visit((dynamic)node[0], table);
            Type rightExpressionType = Visit((dynamic)node[1], table);

            if (leftExpressionType != rightExpressionType)
            {
                if (!((leftExpressionType == Type.LIST_OF_BOOLEAN || leftExpressionType == Type.LIST_OF_INTEGER || leftExpressionType == Type.LIST_OF_STRING) && rightExpressionType == Type.LIST_OF_ANYTHING))
                {
                    throw new SemanticError("Expecting type " + leftExpressionType + " instead of " + rightExpressionType + " in assignment statement", node.AnchorToken);
                }
            }

            if (node[0] is Identifier)
            {
                GlobalSymbolTable gstable = table as GlobalSymbolTable;
                LocalSymbolTable  lstable = table as LocalSymbolTable;

                var symbolName = node[0].AnchorToken.Lexeme;
                if (table is GlobalSymbolTable)
                {
                    if (gstable[symbolName].IsConstant)
                    {
                        throw new SemanticError("Cannot perform assignment to constant " + symbolName, node[0].AnchorToken);
                    }
                }
                else if (table is LocalSymbolTable)
                {
                    if (lstable.Contains(symbolName))
                    {
                        if (lstable[symbolName].Kind == Clasification.CONST)
                        {
                            throw new SemanticError("Cannot perform assignment to constant " + symbolName, node[0].AnchorToken);
                        }
                    }
                    else
                    {
                        if (GSTable.Contains(symbolName) && GSTable[symbolName].IsConstant)
                        {
                            throw new SemanticError("Cannot perform assignment to constant " + symbolName, node[0].AnchorToken);
                        }
                    }
                }
                else
                {
                    throw new TypeAccessException("Expecting either a GlobalSymbolTable or a LocalSymboltable");
                }
            }
            else if (node[0] is ListIndexExpression)
            {
            }
            else
            {
                throw new TypeAccessException("Expecting either a Idenetifier or a ListIndexExpression " + node[0]);
            }

            return(Type.VOID);
        }
        //-----------------------------------------------------------
        private Type Visit(VariableDeclaration node, Table table)
        {
            GlobalSymbolTable gstable = table as GlobalSymbolTable;
            LocalSymbolTable  lstable = table as LocalSymbolTable;

            Type declarationType = Visit((dynamic)node[1], table);

            foreach (var n in node[0])
            {
                var symbolName = n.AnchorToken.Lexeme;
                if (table is GlobalSymbolTable)
                {
                    if (GSTable.Contains(symbolName))
                    {
                        throw new SemanticError("Duplicated symbol: " + symbolName, n.AnchorToken);
                    }
                }
                else if (table is LocalSymbolTable)
                {
                    if (lstable.Contains(symbolName))
                    {
                        throw new SemanticError("Duplicated symbol: " + symbolName, n.AnchorToken);
                    }
                }
                else
                {
                    throw new TypeAccessException("Expecting either a GlobalSymbolTable or a LocalSymboltable");
                }

                if (table is GlobalSymbolTable)
                {
                    gstable[symbolName] = new GlobalSymbol(declarationType);
                }
                else if (table is LocalSymbolTable)
                {
                    lstable[symbolName] = new LocalSymbol(declarationType);
                }
                else
                {
                    throw new TypeAccessException("Expecting either a GlobalSymbolTable or a LocalSymboltable");
                }
            }

            return(Type.VOID);
        }
        //-----------------------------------------------------------
        private Type Visit(ConstantDeclaration node, Table table)
        {
            GlobalSymbolTable gstable = table as GlobalSymbolTable;
            LocalSymbolTable  lstable = table as LocalSymbolTable;

            var symbolName = node.AnchorToken.Lexeme;

            if (table is GlobalSymbolTable)
            {
                if (GSTable.Contains(symbolName))
                {
                    throw new SemanticError("Duplicated symbol: " + symbolName, node[0].AnchorToken);
                }
            }
            else if (table is LocalSymbolTable)
            {
                if (lstable.Contains(symbolName))
                {
                    throw new SemanticError("Duplicated symbol: " + symbolName, node[0].AnchorToken);
                }
            }
            else
            {
                throw new TypeAccessException("Expecting either a GlobalSymbolTable or a LocalSymboltable");
            }

            Type nodeType = Visit((dynamic)node[0], table);

            if (node[0] is Lst)
            {
                if (node[0].Count() == 0)
                {
                    throw new SemanticError("Constant lists cannot be empty: " + symbolName, node.AnchorToken);
                }

                dynamic lst;
                if (nodeType == Type.LIST_OF_BOOLEAN)
                {
                    lst = new Boolean[node[0].Count()];
                }
                else if (nodeType == Type.LIST_OF_INTEGER)
                {
                    lst = new Int32[node[0].Count()];
                }
                else if (nodeType == Type.LIST_OF_STRING)
                {
                    lst = new String[node[0].Count()];
                }
                else
                {
                    throw new TypeAccessException("Expecting one of the following node types: LIST_OF_BOOLEAN, LIST_OF_INTEGER, LIST_OF_STRING");
                }

                int i = 0;
                foreach (var n in node[0])
                {
                    lst[i++] = n.ExtractValue();
                }
                if (table is GlobalSymbolTable)
                {
                    gstable[symbolName] = new GlobalSymbol(nodeType, lst);
                }
                else if (table is LocalSymbolTable)
                {
                    lstable[symbolName] = new LocalSymbol(nodeType, lst);
                }
                else
                {
                    throw new TypeAccessException("Expecting either a GlobalSymbolTable or a LocalSymboltable");
                }
            }
            else
            {
                if (table is GlobalSymbolTable)
                {
                    gstable[symbolName] = new GlobalSymbol(nodeType, node[0].ExtractValue());
                }
                else if (table is LocalSymbolTable)
                {
                    lstable[symbolName] = new LocalSymbol(nodeType, node[0].ExtractValue());
                }
                else
                {
                    throw new TypeAccessException("Expecting either a GlobalSymbolTable or a LocalSymboltable");
                }
            }

            return(Type.VOID);
        }