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

fastparse.CharPredicates.scala Maven / Gradle / Ivy

The newest version!
package scala.meta.internal.fastparse

import scala.meta.internal.fastparse.utils.MacroUtils

/**
  * Fast, pre-computed character predicates for charactes from 0 to 65535
  *
  * Useful because FastParse does it's parsing character by character, so
  * although this doesn't have the full range of the java
  * `Character.getType(c: Int)` functions, it still is good enough for
  * a wide range of use cases
  */
object CharPredicates{
  lazy val isPrintableChar = MacroUtils.preCompute{c =>
    val block = java.lang.Character.UnicodeBlock.of(c)
    !java.lang.Character.isISOControl(c) &&
    !java.lang.Character.isSurrogate(c) &&
    block != null &&
    block != java.lang.Character.UnicodeBlock.SPECIALS
  }
  // a character's type only seems to go from 0 to 30; hence we
  // can store each in 5 bits. Here we make use of the existing
  // 1-bit-per-char preComputed bitmaps we already had, and simply
  // join them back in charTypeLookup in order to get an array of
  // character types from 0 to 65535
  //
  // All this is done lazily at runtime, so if you don't use it
  // you don't pay any cost. On Scala.js, this all gets
  // dead-code-eliminated if it isn't used, so you don't pay any code-size cost

  lazy val bit1 = MacroUtils.preCompute{c => (c.getType & 1) != 0}
  lazy val bit2 = MacroUtils.preCompute{c => (c.getType & 2) != 0}
  lazy val bit3 = MacroUtils.preCompute{c => (c.getType & 4) != 0}
  lazy val bit4 = MacroUtils.preCompute{c => (c.getType & 8) != 0}
  lazy val bit5 = MacroUtils.preCompute{c => (c.getType & 16) != 0}

  def boolToInt(b: Boolean, n: Int) = if (b) 1 << n else 0

  lazy val charTypeLookup: IndexedSeq[Int] = Array.tabulate(Char.MaxValue+1){ i0 =>
    val i = i0.toChar
    boolToInt(bit1(i), 0) |
    boolToInt(bit2(i), 1) |
    boolToInt(bit3(i), 2) |
    boolToInt(bit4(i), 3) |
    boolToInt(bit5(i), 4)
  }



  def isMathSymbol(c: Char) = charTypeLookup(c) == Character.MATH_SYMBOL
  def isOtherSymbol(c: Char) = charTypeLookup(c) == Character.OTHER_SYMBOL
  def isLetter(c: Char) = {
    ((((1 << Character.UPPERCASE_LETTER) |
      (1 << Character.LOWERCASE_LETTER) |
      (1 << Character.TITLECASE_LETTER) |
      (1 << Character.MODIFIER_LETTER) |
      (1 << Character.OTHER_LETTER)) >> charTypeLookup(c)) & 1) != 0
  }

  def isDigit(c: Char) = charTypeLookup(c) == Character.DECIMAL_DIGIT_NUMBER
  def isLower(c: Char) = charTypeLookup(c) == Character.LOWERCASE_LETTER
  def isUpper(c: Char) = charTypeLookup(c) == Character.UPPERCASE_LETTER
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy