TerminalNameNode CreateTerminalNameNode(RegularNameNode parent, uint stringIndex)
        {
            var node = new TerminalNameNode();

            node.Parent    = parent;
            node.Character = 0;
            node.TailIndex = stringIndex;
            nodeCache.Add(node);
            parent.Children.Add(0, node);
            return(node);
        }
Example #2
0
 void ProcessTerminalNode(TerminalNameNode terminalNode, RegularNameNode currNode, uint slot)
 {
     terminalNode.Index       = slot;
     terminalNode.ParentIndex = currNode.Index;
     currNode.ValueOffset     = terminalNode.Index;
     ExtendRangeMap(terminalNode.Index);
     usedRangeMap[(int)terminalNode.Index] = true;
     UpdateMinFreeSlot();
     // Just in case
     if (terminalNode.Index + 1 > maxFreeSlot)
     {
         maxFreeSlot = terminalNode.Index + 1;
     }
     if (OutputDebug)
     {
         Console.Write($"[{slot}] ");
     }
 }
Example #3
0
        void ProcessNode(RegularNameNode currNode)
        {
            cachedRange.Clear();

            if (OutputDebug)
            {
                writer.Write($"{currNode.Index} {(char)currNode.Character} ");
            }

            TerminalNameNode terminalNode = currNode.Children.Select(x => x.Value)
                                            .FirstOrDefault(x => x is TerminalNameNode) as TerminalNameNode;
            bool terminalNodeProcessed = false;

            var children = currNode.Children.Select(x => x.Value).Where(x => x is RegularNameNode)
                           .Cast <RegularNameNode>().OrderBy(x => x.Character).ToArray();

            if (children.Length > 0)
            {
                uint minChildIndex = Math.Max(minFreeSlot, children[0].Character + 1u);
                uint minChildValue = children[0].Character;
                foreach (var child in children)
                {
                    cachedRange.Add(child.Character - minChildValue);
                }
                bool needExtending;
                minChildIndex = FindFreeRange(minChildIndex, cachedRange, out needExtending, false);

                if (terminalNode != null)
                {
                    // Check if we can place a terminal node before our current index
                    int potentialTerminalIndex = (int)minChildIndex - (int)minChildValue;
                    if (potentialTerminalIndex < 0 || usedRangeMap[potentialTerminalIndex])
                    {
                        try
                        {
                            // Occupied, try basing children on terminating node
                            // This throws if it won't work
                            FindFreeRange(minFreeSlot + minChildValue, cachedRange, out needExtending, true);
                            ProcessTerminalNode(terminalNode, currNode, minFreeSlot);
                            minChildIndex = terminalNode.Index + minChildValue;
                        }
                        catch (Exception)
                        {
                            // Just stick it at the end
                            ProcessTerminalNode(terminalNode, currNode, maxFreeSlot);
                            minChildIndex = terminalNode.Index + minChildValue;
                            // Validate
                            FindFreeRange(minChildIndex, cachedRange, out needExtending, true);
                        }
                    }
                    else
                    {
                        // Put terminating node down below
                        ProcessTerminalNode(terminalNode, currNode, (uint)potentialTerminalIndex);
                    }
                    terminalNodeProcessed = true;
                }


                if (needExtending)
                {
                    ExtendRangeMap(minChildIndex + cachedRange[cachedRange.Count - 1]);
                }

                for (int i = 0; i < children.Length; ++i)
                {
                    var child = children[i];
                    child.Index       = minChildIndex + cachedRange[i];
                    child.ParentIndex = currNode.Index;
                    usedRangeMap[(int)child.Index] = true;
                }

                uint lastChildIndexFree = children[children.Length - 1].Index + 1;
                if (lastChildIndexFree > maxFreeSlot)
                {
                    maxFreeSlot = lastChildIndexFree;
                }

                if (OutputDebug)
                {
                    if (children.Length == 1)
                    {
                        writer.Write($"<{children[0].Index}>");
                    }
                    else
                    {
                        writer.Write($"<{children[0].Index} {children[children.Length - 1].Index}>");
                    }
                }

                if (terminalNode == null)
                {
                    currNode.ValueOffset = children[0].Index - children[0].Character;
                }
                UpdateMinFreeSlot();

                if (OutputDebug)
                {
                    writer.WriteLine();
                    ++writer.Indent;
                }

                foreach (var child in children)
                {
                    ProcessNode(child);
                }

                if (OutputDebug)
                {
                    --writer.Indent;
                }
            }

            if (terminalNode != null && !terminalNodeProcessed)
            {
                ProcessTerminalNode(terminalNode, currNode, minFreeSlot);
                if (OutputDebug)
                {
                    writer.WriteLine();
                }
            }
        }