Пример #1
0
 static Optional <CharRange> TryMerge_Accumulate_Merge2Range(CharRange left, CharRange right)
 {
     if (/* left.Start <= right.Start && */ right.Start <= left.End)
     {
         if (left.End <= right.End || (right.End - left.End) == 1)
         {
             return(new Optional <CharRange>(CharRange.Between(left.Start, right.End)));
         }
         return(new Optional <CharRange>(left));
     }
     return(new Optional <CharRange>());
 }
Пример #2
0
        static Stack <CharRange> TryMerge_Accumulate(Stack <CharRange> stack, CharRange range)
        {
            if (stack.Count == 0)
            {
                stack.Push(range);
                return(stack);
            }
            var res = TryMerge_Accumulate_Merge2Range(stack.Peek(), range);

            if (res.Present)
            {
                stack.Pop();
                stack.Push(res.Value);
            }
            else
            {
                stack.Push(range);
            }
            return(stack);
        }
Пример #3
0
        public static CharRange[] AnyOf(IEnumerable <char> cs)
        {
            if (cs == null)
            {
                throw new ArgumentNullException(nameof(cs));
            }
            var leftSeq = cs.Distinct().OrderBy(a => a).ToArray();

            if (leftSeq.Length == 0)
            {
                return(new CharRange[0]);
            }
            if (leftSeq.Length == 1)
            {
                return new CharRange[] { CharRange.Exactly(leftSeq[0]) }
            }
            ;

            // シーケンスの先頭の文字を重複させたシーケンスを作成
            var rightSeq = new char[] { leftSeq[0] }.Concat(leftSeq);

            // 元のシーケンスと新しいシーケンスをZIPして匿名型のシーケンスを作成。
            // Content:文字クラスを構成する文字、Prev:それらの文字の1つ前の文字。
            var zip = leftSeq.Zip(rightSeq, (left, right) => new {
                Content     = left,
                PrevContent = right
            });

            // コード差分とコード自体を内容とする匿名型のシーケンスに変換。
            var increments = zip.Select(chx => new {
                Increment = chx.Content - chx.PrevContent,
                Content   = chx.Content
            });

            // 文字の範囲を構成するメンバを一時的に格納するバッファ
            var charsBuff = new List <char>();
            // 文字の範囲を表すオブジェクトを一時的に格納するバッファ
            var rangesBuff = new List <CharRange>();

            // コード差分とコード自体を内容とする匿名型のシーケンスをループ処理
            foreach (var pair in increments)
            {
                // コード差分が1より大きい=文字の範囲の分断が生じる
                if (pair.Increment > 1)
                {
                    // 範囲メンバを格納しているバッファの内容をもとに範囲オブジェクトを生成
                    // 範囲オブジェクト用のバッファに追加
                    rangesBuff.Add(CharRange.Between(charsBuff.First(), charsBuff.Last()));
                    // 範囲メンバを格納しているバッファはクリア
                    charsBuff.Clear();
                }
                // 文字を文字範囲メンバ用のバッファに追加
                charsBuff.Add(pair.Content);
            }

            // ループを抜けたあと範囲化の済んでいないメンバがいないかチェック
            if (charsBuff.Count > 0)
            {
                // 残っていたメンバの情報から範囲オブジェクトを作成しバッファに追加
                rangesBuff.Add(CharRange.Between(charsBuff.First(), charsBuff.Last()));
            }

            // 範囲オブジェクトのシーケンスを呼び出し元に返す
            return(rangesBuff.ToArray());
        }
Пример #4
0
 public static CharRange[] TryAppend(CharRange r, char ch)
 {
     return(r.Contains(ch) ? new[] { r } : TryMerge(r, CharRange.Exactly(ch)));
 }
 public override CharClass Plus(char ch)
 {
     return(new CharRangeCharClass(CharRangeUtility.TryMerge(_charRanges.Concat(new[] { CharRange.Exactly(ch) }))));
 }