public VariableToken(ref string s, ExpressionData parent)
        {
            Match m = VARIABLE_REGEX.Match(s.Substring(1));

            if (m.Success)
            {
                s         = s.Substring(m.Index + m.Length + 1);
                Variable  = m.Captures[0].Value;
                Namespace = "";
            }
            else
            {
                m = new Regex("\\[(?<namespace>\\w+)::(?<variable>\\w+)\\]").Match(s.Substring(1));
                if (m.Success)
                {
                    Variable  = m.Groups[2].Value;
                    Namespace = m.Groups[1].Value;
                    s         = s.Substring(m.Index + m.Length + 1);
                }
                else
                {
                    SourceWriter.Help(null, "Unable to parse variable '" + s + "'");
                }
            }
        }
        public static string LookupSsisTypeSqlName(string ssistype, string length, int precision, int scale)
        {
            // Skip Data Transformation Underscore
            if (ssistype.StartsWith("DT_"))
            {
                ssistype = ssistype.Substring(3);
            }
            ssistype = ssistype.ToLower();

            // Okay, let's check real stuff
            if (ssistype == "i2")
            {
                return("smallint");
            }
            else if (ssistype == "i4")
            {
                return("int");
            }
            else if (ssistype == "i8")
            {
                return("bigint");
            }
            else if (ssistype == "str")
            {
                return(String.Format("varchar({0})", length == null ? "max" : length));
            }
            else if (ssistype == "wstr")
            {
                return(String.Format("nvarchar({0})", length == null ? "max" : length));
            }
            else if (ssistype == "dbtimestamp")
            {
                return("datetime");
            }
            else if (ssistype == "r4")
            {
                return("real");
            }
            else if (ssistype == "r8")
            {
                return("float");

                // Currency
            }
            else if (ssistype == "cy")
            {
                return("money");
            }
            else if (ssistype == "numeric")
            {
                return(String.Format("decimal({0},{1})", precision, scale));
            }
            else
            {
                SourceWriter.Help(null, "I don't yet understand the SSIS type named " + ssistype);
            }
            return(null);
        }
        public static void EmitScriptProject(SsisObject o, string indent)
        {
            // Find the script object child
            var script = o.GetChildByType("DTS:ObjectData").GetChildByType("ScriptProject");

            // Create a folder for this script
            string project_folder = Path.Combine(AppFolder, o.GetFolderName());

            Directory.CreateDirectory(project_folder);

            // Extract all the individual script files in this script
            foreach (SsisObject child in script.Children)
            {
                string fn  = project_folder + child.Attributes["Name"];
                string dir = Path.GetDirectoryName(fn);
                Directory.CreateDirectory(dir);

                if (child.DtsObjectType == "BinaryItem")
                {
                    byte[] contents = System.Convert.FromBase64String(child.ContentValue);
                    File.WriteAllBytes(fn, contents);
                }
                else if (child.DtsObjectType == "ProjectItem")
                {
                    File.WriteAllText(fn, child.ContentValue);
                }

                // Handle DLL files specially - they are binary!  Oh yeah base64 encoded
                if (fn.EndsWith(".dll"))
                {
                    DllFiles.Add(fn);

                    // Note this as a potential problem
                    SourceWriter.Help(o, "The Visual Basic project " + child.Attributes["Name"] + " was embedded in the DTSX project.  Visual Basic code cannot be automatically converted.");

                    // Show the user that this is how the script should be executed, if they want to fix it
                    SourceWriter.WriteLine(@"{0}//{1}.ScriptMain sm = new {1}.ScriptMain();", indent, Path.GetFileNameWithoutExtension(fn).Replace("scripttask", "ScriptTask"));
                    SourceWriter.WriteLine(@"{0}//sm.Main();", indent);

                    // Is this a project file?
                }
                else if (fn.EndsWith(".vbproj") || fn.EndsWith(".csproj"))
                {
                    ProjectFiles.Add(fn);
                }
                else
                {
                    AllFiles.Add(fn);
                }
            }
        }
        public ConversionToken(ref string s, ExpressionData parent)
        {
            Match m = CONVERT_REGEX.Match(s);

            if (m.Success)
            {
                s              = s.Substring(m.Index + m.Length);
                TypeRef        = ColumnVariable.LookupSsisTypeName(m.Groups[1].Value);
                TokenToConvert = parent.ConsumeToken(ref s);
            }
            else
            {
                SourceWriter.Help(null, "Unable to parse conversion token " + s);
            }
        }
        public static string LookupSsisTypeName(string p)
        {
            // Skip Data Transformation Underscore
            if (p.StartsWith("DT_"))
            {
                p = p.Substring(3);
            }
            p = p.ToLower();

            // Okay, let's check real stuff
            if (p == "i2")
            {
                return("System.Int16");
            }
            else if (p == "i4")
            {
                return("System.Int32");
            }
            else if (p == "i8")
            {
                return("System.Int64");
            }
            else if (p == "str" || p == "wstr")
            {
                return("System.String");
            }
            else if (p == "dbtimestamp")
            {
                return("System.DateTime");
            }
            else if (p == "r4" || p == "r8")
            {
                return("double");

                // Currency & numerics both become decimals
            }
            else if (p == "cy" || p == "numeric")
            {
                return("System.Decimal");
            }
            else
            {
                SourceWriter.Help(null, "I don't yet understand the SSIS type named " + p);
            }
            return(null);
        }
        public LineageToken(ref string s, ExpressionData parent)
        {
            Match m = LINEAGE_REGEX.Match(s);

            if (m.Success)
            {
                var li = (from LineageObject l in parent.Lineage where l.LineageId == m.Groups[1].Value select l).FirstOrDefault();
                if (li != null)
                {
                    s          = s.Substring(m.Index + m.Length);
                    LineageRef = li;
                }
                else
                {
                    SourceWriter.Help(null, "Unable to find lineage reference #" + s);
                }
            }
        }
        /// <summary>
        /// Get the connection string name when given a GUID
        /// </summary>
        /// <param name="conn_guid_str"></param>
        /// <returns></returns>
        public static string GetConnectionStringPrefix(string conn_guid_str)
        {
            SsisObject connobj = SsisObject.GetObjectByGuid(Guid.Parse(conn_guid_str));

            if (connobj == null)
            {
                return("Sql");
            }
            string objecttype = connobj.Properties["CreationName"];

            if (objecttype.StartsWith("OLEDB"))
            {
                return("OleDb");
            }
            else if (objecttype.StartsWith("ADO.NET:System.Data.SqlClient.SqlConnection"))
            {
                return("Sql");
            }
            else
            {
                SourceWriter.Help(null, "I don't understand the database connection type " + objecttype);
            }
            return("");
        }
        public ProgramVariable(SsisObject o, bool as_global)
        {
            // Figure out what type of a variable we are
            DtsType      = o.GetChildByType("DTS:VariableValue").Attributes["DTS:DataType"];
            CSharpType   = null;
            DefaultValue = o.GetChildByType("DTS:VariableValue").ContentValue;
            Comment      = o.Description;
            Namespace    = o.Properties["Namespace"];
            IsGlobal     = as_global;
            VariableName = o.DtsObjectName;

            // Here are the DTS type codes I know
            if (DtsType == "3")
            {
                CSharpType = "int";
            }
            else if (DtsType == "8")
            {
                CSharpType = "string";
                if (!String.IsNullOrEmpty(DefaultValue))
                {
                    DefaultValue = "\"" + DefaultValue.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
                }
            }
            else if (DtsType == "13")
            {
                CSharpType   = "DataTable";
                DefaultValue = "new DataTable()";
            }
            else if (DtsType == "2")
            {
                CSharpType = "short";
            }
            else if (DtsType == "11")
            {
                CSharpType = "bool";
                if (DefaultValue == "1")
                {
                    DefaultValue = "true";
                }
                else
                {
                    DefaultValue = "false";
                }
            }
            else if (DtsType == "20")
            {
                CSharpType = "long";
            }
            else if (DtsType == "7")
            {
                CSharpType = "DateTime";
                if (!String.IsNullOrEmpty(DefaultValue))
                {
                    DefaultValue = "DateTime.Parse(\"" + DefaultValue + "\")";
                }
            }
            else
            {
                SourceWriter.Help(o, "I don't understand DTS type " + DtsType);
            }
        }
        public Token ConsumeToken(ref string s)
        {
            // Get the first character
            char c = s[0];

            // Is it whitespace?  Just consume this character and move on
            if (c == ' ' || c == '\r' || c == '\n' || c == '\t')
            {
                s = s.Substring(1);
                return(null);

                // Is this a lineage column reference?
            }
            else if (c == '#')
            {
                return(new LineageToken(ref s, this));

                // Is this a global variable reference?
            }
            else if (c == '@')
            {
                return(new VariableToken(ref s, this));

                // Is this a type conversion?  If so, we need one more token
            }
            else if (c == '(')
            {
                return(new ConversionToken(ref s, this));

                // Is this a math operation?
            }
            else if (c == '+' || c == '-' || c == '*' || c == '/')
            {
                s = s.Substring(1);
                return(new OperationToken()
                {
                    Op = c.ToString()
                });

                // Check for solo negation or not-equals
            }
            else if (c == '!')
            {
                if (s[1] == '=')
                {
                    s = s.Substring(2);
                    return(new OperationToken()
                    {
                        Op = "!="
                    });
                }
                s = s.Substring(1);
                return(new OperationToken()
                {
                    Op = "!"
                });

                // This could be either assignment or equality
            }
            else if (c == '=')
            {
                if (s[1] == '=')
                {
                    s = s.Substring(2);
                    return(new OperationToken()
                    {
                        Op = "=="
                    });
                }
                s = s.Substring(1);
                return(new OperationToken()
                {
                    Op = "="
                });

                // Is this a string constant?
            }
            else if (c == '"')
            {
                Match m = STRING_REGEX.Match(s);
                if (m.Success)
                {
                    s = s.Substring(m.Index + m.Length);
                    return(new ConstantToken()
                    {
                        Value = m.Captures[0].Value, TypeRef = "System.String"
                    });
                }

                // Is this a numeric constant?
            }
            else if (c >= '0' && c <= '9')
            {
                Match m = NUMBER_REGEX.Match(s);
                if (m.Success)
                {
                    s = s.Substring(m.Index + m.Length);
                    return(new ConstantToken()
                    {
                        Value = m.Captures[0].Value, TypeRef = "System.Int32"
                    });
                }

                // Is this boolean true or false?
            }
            else if (s.StartsWith("true", StringComparison.CurrentCultureIgnoreCase))
            {
                s = s.Substring(4);
                return(new ConstantToken()
                {
                    Value = "true", TypeRef = "System.Boolean"
                });
            }
            else if (s.StartsWith("false", StringComparison.CurrentCultureIgnoreCase))
            {
                s = s.Substring(5);
                return(new ConstantToken()
                {
                    Value = "false", TypeRef = "System.Boolean"
                });
            }

            // Did we fail to process this token?  Fail out
            SourceWriter.Help(null, "Unable to parse expression '" + _expression + "'");
            s = "";
            return(null);
        }