All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.petitparser.parser.primitive.CharacterRange Maven / Gradle / Ivy

There is a newer version: 2.4.0
Show newest version
package org.petitparser.parser.primitive;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * Internal class to build an optimized {@link CharacterPredicate} from single
 * characters or ranges of characters.
 */
class CharacterRange {

  static final Comparator CHARACTER_RANGE_COMPARATOR =
      Comparator.comparing((CharacterRange range) -> range.start)
          .thenComparing((CharacterRange range) -> range.stop);

  static CharacterPredicate toCharacterPredicate(List ranges) {

    // 1. sort the ranges
    List sortedRanges = new ArrayList<>(ranges);
    sortedRanges.sort(CHARACTER_RANGE_COMPARATOR);

    // 2. merge adjacent or overlapping ranges
    List mergedRanges = new ArrayList<>();
    for (CharacterRange thisRange : sortedRanges) {
      if (mergedRanges.isEmpty()) {
        mergedRanges.add(thisRange);
      } else {
        CharacterRange lastRange = mergedRanges.get(mergedRanges.size() - 1);
        if (lastRange.stop + 1 >= thisRange.start) {
          CharacterRange characterRange =
              new CharacterRange(lastRange.start, thisRange.stop);
          mergedRanges.set(mergedRanges.size() - 1, characterRange);
        } else {
          mergedRanges.add(thisRange);
        }
      }
    }

    // 3. build the best resulting predicates
    if (mergedRanges.isEmpty()) {
      return CharacterPredicate.none();
    } else if (mergedRanges.size() == 1) {
      CharacterRange characterRange = mergedRanges.get(0);
      return characterRange.start == characterRange.stop ?
          CharacterPredicate.of(characterRange.start) :
          CharacterPredicate.range(characterRange.start, characterRange.stop);
    } else {
      char[] starts = new char[mergedRanges.size()];
      char[] stops = new char[mergedRanges.size()];
      for (int i = 0; i < mergedRanges.size(); i++) {
        starts[i] = mergedRanges.get(i).start;
        stops[i] = mergedRanges.get(i).stop;
      }
      return CharacterPredicate.ranges(starts, stops);
    }
  }

  private final char start;
  private final char stop;

  CharacterRange(char start, char stop) {
    this.start = start;
    this.stop = stop;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy