private static GrammarNode <T> GetInnerNode(GrammarNode <T> grammarNode, ref RepetitionRange range, Boolean isLazy) { if (grammarNode is Repetition <T> repetition && repetition.IsLazy == isLazy) { /* expr{α}{β} ≡ expr{α·β} */ if (repetition.Range.IsSingleElement && range.IsSingleElement) { var reps = repetition.Range.Minimum * range.Minimum; range = new RepetitionRange(reps, reps); return(repetition.InnerNode); } /* expr{a, b}{c, d} ≡ expr{a·c, b·d} IF b·c ≥ a·(c + 1) - 1 * Basically checks if each occurrence of the range [n·a, n·b] where n ∈ [c, d] * overlaps with each other. * If it does, we then just get the range of [a·c, b·d] (the union of all * occurrences of the range on the previous sentence) instead of nesting the repetitions. */ if (repetition.Range.IsFinite && range.IsFinite && repetition.Range.Maximum * range.Minimum >= repetition.Range.Minimum * (range.Minimum + 1) - 1) { range = new RepetitionRange( SaturatingMath.Multiply(repetition.Range.Minimum, range.Minimum), SaturatingMath.Multiply(repetition.Range.Maximum !.Value, range.Maximum !.Value)); return(repetition.InnerNode); } } return(grammarNode); }
/// <summary> /// Creates a new repetition node /// </summary> /// <param name="grammarNode"></param> /// <param name="range"></param> /// <param name="isLazy"></param> public Repetition(GrammarNode <T> grammarNode, RepetitionRange range, Boolean isLazy) : base(GetInnerNode(grammarNode, ref range, isLazy)) { this.Range = range; this.IsLazy = isLazy; }