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); }
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}] "); } }
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(); } } }