/// <summary> /// Folds a negated set node. /// </summary> /// <param name="negatedSet"></param> /// <param name="argument">The argument to be passed to the visitor method.</param> /// <returns> /// <list type="number"> /// <item>The original node if it's to be kept</item> /// <item>A different node to replace the original node with</item> /// <item>Null if the node is to be removed</item> /// </list> /// </returns> protected override GrammarNode <Char>?VisitNegatedSet(NegatedSet negatedSet, TArgument argument) => negatedSet;
protected override String?VisitNegatedSet(NegatedSet negatedSet, Unit argument) => null;
/// <summary> /// Visits a negated set node. /// </summary> /// <param name="negatedSet"></param> /// <param name="argument">The argument data passed by the caller.</param> /// <returns>The result of visiting this node.</returns> protected abstract TReturn VisitNegatedSet(NegatedSet negatedSet, TArgument argument);
protected override GrammarNode <Char>?VisitNegatedSet(NegatedSet negatedSet, OptimizeArgs argument) { var characters = negatedSet.Characters.ToList(); var ranges = negatedSet.Ranges.ToList(); var categories = negatedSet.UnicodeCategories.ToList(); // We don't want inner sets to be optimized since we'll flatten them. OptimizeArgs childrenArgument = argument.WithIsParentASet(true); List <GrammarNode <Char> > nodes = negatedSet.Nodes.Select(node => this.Visit(node, childrenArgument)) .Where(node => node is not null) .ToList() !; var nodeIdx = 0; while (true) { loopStart: if (nodeIdx >= nodes.Count) { break; } GrammarNode <Char> node = nodes[nodeIdx] !; switch (node.Kind) { case GrammarNodeKind.CharacterTerminal: { var characterTerminal = (CharacterTerminal)node; nodes.RemoveAt(nodeIdx); characters.Add(characterTerminal.Value); goto loopStart; } case GrammarNodeKind.CharacterRange: { var characterRange = (CharacterRange)node; nodes.RemoveAt(nodeIdx); ranges.Add(characterRange.Range); goto loopStart; } case GrammarNodeKind.CharacterUnicodeCategoryTerminal: { var unicodeCategoryTerminal = (UnicodeCategoryTerminal)node; nodes.RemoveAt(nodeIdx); categories.Add(unicodeCategoryTerminal.Category); goto loopStart; } case GrammarNodeKind.CharacterSet: { var subSet = (Set)node; nodes.RemoveAt(nodeIdx); characters.AddRange(subSet.Characters); ranges.AddRange(subSet.Ranges); categories.AddRange(subSet.UnicodeCategories); nodes.AddRange(subSet.Nodes); goto loopStart; } } nodeIdx++; } characters.Sort(); OptimizationAlgorithms.ExpandRanges(characters, ranges, true); OptimizationAlgorithms.RangifyCharacters(characters, ranges, true); OptimizationAlgorithms.MergeRanges(ranges); ImmutableArray <Char> flattenedRanges = CharUtils.FlattenRanges(ranges); var categoriesFlagSet = CharUtils.CreateCategoryFlagSet(categories); OptimizationAlgorithms.RemoveMatchedCharacters(characters, flattenedRanges, categoriesFlagSet); // Characters are still sorted at this point CharacterBitVector?characterBitVector = null; if (characters.Any()) { var charactersDistance = characters[characters.Count - 1] - characters[0]; if (charactersDistance is > 1 and <= 256) { characterBitVector = new CharacterBitVector(characters); } } return(new OptimizedNegatedSet( characters.ToImmutableHashSet(), flattenedRanges, categoriesFlagSet, nodes.ToImmutableArray(), characterBitVector)); }
/// <summary> /// Initializes a new set element. /// </summary> /// <param name="negatedSet"></param> public SetElement(NegatedSet negatedSet) : this((GrammarNode <Char>)negatedSet) { }