public string Lookup(VB6SubTree subTree)
        {
            if (subTree == null)
            {
                throw new ArgumentNullException(nameof(subTree));
            }

            //var t = GetNodeHash(subTree.GetRoot());
            var t = subTree.GetRoot();

            if (generatedPatterns.ContainsKey(t))
            {
                return(generatedPatterns[t]);
            }
            return(null);
        }
        public static List <ASTSequenceItem> Create(ASTPatternGenerator apg, ParseTree rootNode)
        {
            if (apg == null)
            {
                throw new ArgumentNullException(nameof(apg));
            }

            VB6NodeTree            nodeTree     = new VB6NodeTree(rootNode);
            List <ASTSequenceItem> returnedList = new List <ASTSequenceItem> {
            };

            foreach (var node in nodeTree.GetAllNodes())
            {
                var subtree = new VB6SubTree(nodeTree, node);

                int    depth        = 0;
                string childIndices = "";
                string typePath     = "";

                var paths = nodeTree.GetPath(node).ToList();
                if (paths.Count == 0)
                {
                    continue;
                }

                foreach (IndexedPath path in paths)
                {
                    childIndices += path.ChildIndex + "/";
                    typePath     += path.NodeTypeName + "/";
                    depth++;
                }

                var asi = new ASTSequenceItem {
                    setpos    = returnedList.Count,
                    depth     = depth,
                    childPath = childIndices,
                    token     = paths.Last().Token,
                    typeName  = paths.First().NodeTypeName,
                    pattern   = apg.Lookup(subtree),
                    node      = node
                };
                returnedList.Add(asi);
            }
            return(returnedList);
        }
        public static string GetNodeTreeHashString(VB6SubTree nodeTree)
        {
            if (nodeTree == null)
            {
                throw new ArgumentNullException(nameof(nodeTree));
            }

            var typeNames = new List <string>();
            var count     = 0;

            foreach (var node in nodeTree.GetAllNodes())
            {
                typeNames.Add(VbToCsharpPattern.LookupNodeType(node));
                count++;
                if (count > 20)
                {
                    break;
                }
            }
            return(String.Join("/", typeNames));
        }
        public void GetPatterns(VB6NodeTree nodeTree)
        {
            if (nodeTree == null)
            {
                throw new ArgumentNullException(nameof(nodeTree));
            }

            // Iterate over all nodes and add them to node hash based on their concatenated type strings
            foreach (var node in nodeTree.GetAllNodes())
            {
                var subtree = new VB6SubTree(nodeTree, node);

                //var nodeTreeHashString = GetNodeTreeHashString(subtree);
                var nodeHash = GetNodeHash(node);

                if (!nodeHashDict.ContainsKey(nodeHash))
                {
                    nodeHashDict[nodeHash] = new Dictionary <string, List <VB6SubTree> >();
                }
                var tokens = String.Join(" ", GetTokens(node));
                if (!nodeHashDict[nodeHash].ContainsKey(tokens))
                {
                    nodeHashDict[nodeHash][tokens] = new List <VB6SubTree>();
                }
                nodeHashDict[nodeHash][tokens].Add(subtree);
            }

            foreach (var key in nodeHashDict.Keys)
            {
                foreach (var key2 in nodeHashDict[key].Keys)
                {
                    var s = new List <string>();
                    foreach (var subtree in nodeHashDict[key][key2])
                    {
                        var node   = subtree.GetRoot();
                        var tokens = String.Join(" ", GetTokens(node));
                        s.Add(tokens);
                    }
                    var s2 = String.Join(", ", s);
                    DebugClass.LogError("NodeTreeHashString: " + key + " " + key2 + ": " + nodeHashDict[key][key2].Count + ": " + s2);
                }
            }

            // TODO: Is it possible to auto-generate this dictionary?
            // No stress, it's small, but would be nice for other languages.
            var replaceable = new Dictionary <string, bool>();

            replaceable["AmbiguousIdentifierContext"] = true;
            replaceable["CertainIdentifierContext"]   = true;
            replaceable["LiteralContext"]             = true;
            replaceable["FieldLengthContext"]         = true;

            // Iterate over all nodes and replace each token/text in pattern with pattern letter,
            // if there are two or more variations of this token under this node type name
            const string letters = "ABCDEFGHIJKLMNOPQRSTUVXYZ";

            foreach (var node in nodeTree.GetAllNodes())
            {
                var subtree     = new VB6SubTree(nodeTree, node);
                int letterIndex = 0;
                var text        = node.getText();
                var pattern     = text;

                foreach (var child in subtree.GetAllNodes())
                {
                    if (replaceable.ContainsKey(VbToCsharpPattern.LookupNodeType(child)))
                    {
                        //DebugClass.LogError("REPLACING: " + VbToCsharpPattern.LookupNodeType(child));
                        var tokens = GetTokens(child);
                        foreach (var token in tokens)
                        {
                            if (letterIndex < letters.Length)
                            {
                                var oldPattern = pattern;
                                pattern = pattern.Replace(token, letters[letterIndex].ToString(System.Globalization.CultureInfo.InvariantCulture));
                                if (pattern != oldPattern)
                                {
                                    letterIndex++;
                                }
                                //DebugClass.LogError("REPLACING: " + token);
                            }

                            if (letterIndex >= letters.Length)
                            {
                                break;
                            }
                        }
                        if (letterIndex >= letters.Length)
                        {
                            break;
                        }
                    }
                }
                if (pattern.Length >= 100)
                {
                    pattern = "PATTERN TOO LONG";
                }
                generatedPatterns[node] = pattern;
            }
        }
        public static void GetCode(VB6NodeTree nodeTree)
        {
            const string genFolder = @"F:\emh-dev\VB6ToCSharpCompiler\VB6ToCSharpCompiler\VB6NodeTranslatorLogging";

            Dictionary <string, Dictionary <ImmutableList <string>, List <VB6SubTree> > > nodeTypeDict = new Dictionary <string, Dictionary <ImmutableList <string>, List <VB6SubTree> > >();

            if (nodeTree == null)
            {
                throw new ArgumentNullException(nameof(nodeTree));
            }

            // Iterate over all nodes and add them to node hash based on their concatenated type strings
            var assignments = new List <string>();

            foreach (var node in nodeTree.GetAllNodes())
            {
                var subtree = new VB6SubTree(nodeTree, node);

                //var nodeTreeHashString = GetNodeTreeHashString(subtree);
                var nodeHash = GetNodeHash(node);

                if (!nodeTypeDict.ContainsKey(nodeHash))
                {
                    nodeTypeDict[nodeHash] = new Dictionary <ImmutableList <string>, List <VB6SubTree> >();
                }

                var children = ImmutableList.Create <string>();
                foreach (var child in nodeTree.GetChildren(node))
                {
                    var tokens = String.Join(" ", GetTokens(child));
                    //if (!string.IsNullOrEmpty(tokens))
                    //{
                    //    children = children.Add("\"" + tokens + "\"");
                    //} else
                    //{

                    //}
                    children = children.Add(GetNodeHash(child));
                }

                if (!nodeTypeDict[nodeHash].ContainsKey(children))
                {
                    nodeTypeDict[nodeHash][children] = new List <VB6SubTree>();
                }
                nodeTypeDict[nodeHash][children].Add(subtree);
            }

            var hasContexts = new Dictionary <string, bool>();

            foreach (ContextNodeType contextNodeType in (ContextNodeType[])Enum.GetValues(typeof(ContextNodeType)))
            {
                var typeName  = contextNodeType.ToString("F");
                var fileName  = typeName + ".cs";
                var outString = GetCls(typeName);
                hasContexts[typeName] = true;
                System.IO.File.WriteAllText(Path.Combine(genFolder, fileName), outString);

                typeName =
                    typeName[0]
                    .ToString(System.Globalization.CultureInfo.InvariantCulture)
                    .ToUpper(System.Globalization.CultureInfo.InvariantCulture) + typeName.Substring(1);
                var assignment =
                    "dict[ContextNodeType.$TYPE] = new VB6NodeTranslatorLogging.$TYPE(nodeTree, dict);\r\n"
                    .Replace("$TYPE", typeName).Replace("$TYPE", typeName);
                assignments.Add(assignment);
            }

            var mainClass = @"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VB6ToCSharpCompiler
{
    public static class VB6NodeTranslatorLoader
    {
        public static IEnumerable<string> Translate(VB6NodeTree nodeTree) {
            if (nodeTree == null)
            {
                throw new ArgumentNullException(nameof(nodeTree));
            }

            var dict = new Dictionary<ContextNodeType, VB6NodeTranslator>();
            
            // dict[ContextNodeType.AmbiguousIdentifierContext] = new VB6NodeTranslatorLogging.AmbiguousIdentifierContext(nodeTree, dict);
            $ASSIGNMENTS
            
            if (!Enum.TryParse(nodeTree.GetRoot().GetType().Name, out ContextNodeType contextNodeType))
            {
                throw new ArgumentException(""contextNodeType"");
            }
            return dict[contextNodeType].Translate(nodeTree.GetChildren(nodeTree.GetRoot()));
        }
    }
}
";

            mainClass = mainClass.Replace("$ASSIGNMENTS", String.Join("", assignments));
            System.IO.File.WriteAllText(Path.Combine(genFolder, "../VB6NodeTranslatorLoader.cs"), mainClass);

            //foreach (var key in nodeTypeDict.Keys)
            //{
            //    var typeName = key;
            //    if (!hasContexts.ContainsKey(typeName))
            //    {
            //        DebugClass.LogError(typeName + ",");
            //        hasContexts[typeName] = true;
            //    }
            //    var fileName = typeName + ".cs";
            //    var outString = GetCls(typeName);
            //    System.IO.File.WriteAllText(Path.Combine(genFolder, fileName), outString);
            //}
        }