Make Regex engine freezing friendly. (#1742)

This commit is contained in:
Nikolay Igotti
2018-07-02 16:18:43 +03:00
committed by GitHub
parent dfac13a7a7
commit 0146e50688
3 changed files with 341 additions and 259 deletions
@@ -33,6 +33,10 @@
package kotlin.text.regex package kotlin.text.regex
import kotlin.collections.associate
import konan.worker.freeze
/** /**
* Unicode category (i.e. Ll, Lu). * Unicode category (i.e. Ll, Lu).
*/ */
@@ -44,7 +48,9 @@ internal open class UnicodeCategory(protected val category: Int) : AbstractCharC
* Unicode category scope (i.e IsL, IsM, ...) * Unicode category scope (i.e IsL, IsM, ...)
*/ */
internal class UnicodeCategoryScope(category: Int) : UnicodeCategory(category) { internal class UnicodeCategoryScope(category: Int) : UnicodeCategory(category) {
override fun contains(ch: Int): Boolean = alt xor (category shr ch.toChar().category.value and 1 != 0) override fun contains(ch: Int): Boolean {
return alt xor (((category shr ch.toChar().category.value) and 1) != 0)
}
} }
/** /**
@@ -52,7 +58,6 @@ internal class UnicodeCategoryScope(category: Int) : UnicodeCategory(category) {
* Note: this class represent a token, not node, so being constructed by lexer. * Note: this class represent a token, not node, so being constructed by lexer.
*/ */
internal abstract class AbstractCharClass : SpecialToken() { internal abstract class AbstractCharClass : SpecialToken() {
/** /**
* Show if the class has alternative meaning: * Show if the class has alternative meaning:
* if the class contains character 'a' and alt == true then the class will contains all characters except 'a'. * if the class contains character 'a' and alt == true then the class will contains all characters except 'a'.
@@ -92,39 +97,53 @@ internal abstract class AbstractCharClass : SpecialToken() {
open val instance: AbstractCharClass open val instance: AbstractCharClass
get() = this get() = this
val surrogates: AbstractCharClass by lazy {
val result = object : AbstractCharClass() {
override fun contains(ch: Int): Boolean {
val index = ch - Char.MIN_SURROGATE.toInt()
return if (index >= 0 && index < AbstractCharClass.SURROGATE_CARDINALITY) private val surrogates_ = konan.worker.AtomicReference<AbstractCharClass>()
this.altSurrogates xor this@AbstractCharClass.lowHighSurrogates.get(index) val surrogates: AbstractCharClass
else get() {
false surrogates_.get()?.let {
return it
} }
} val result = object : AbstractCharClass() {
result.setNegative(this.altSurrogates) override fun contains(ch: Int): Boolean {
return@lazy result val index = ch - Char.MIN_SURROGATE.toInt()
}
return if (index >= 0 && index < AbstractCharClass.SURROGATE_CARDINALITY)
val withoutSurrogates: AbstractCharClass by lazy { this.altSurrogates xor this@AbstractCharClass.lowHighSurrogates.get(index)
val result = object : AbstractCharClass() { else
override fun contains(ch: Int): Boolean { false
val index = ch - Char.MIN_SURROGATE.toInt() }
val containslHS = if (index >= 0 && index < AbstractCharClass.SURROGATE_CARDINALITY)
this.altSurrogates xor this@AbstractCharClass.lowHighSurrogates.get(index)
else
false
return this@AbstractCharClass.contains(ch) && !containslHS
} }
result.setNegative(this.altSurrogates)
surrogates_.compareAndSwap(null, result.freeze())
return surrogates_.get()!!
} }
result.setNegative(isNegative())
result.mayContainSupplCodepoints = mayContainSupplCodepoints
return@lazy result private val withoutSurrogates_ = konan.worker.AtomicReference<AbstractCharClass>()
} val withoutSurrogates: AbstractCharClass
get() {
withoutSurrogates_.get()?.let {
return it
}
val result = object : AbstractCharClass() {
override fun contains(ch: Int): Boolean {
val index = ch - Char.MIN_SURROGATE.toInt()
val containslHS = if (index >= 0 && index < AbstractCharClass.SURROGATE_CARDINALITY)
this.altSurrogates xor this@AbstractCharClass.lowHighSurrogates.get(index)
else
false
return this@AbstractCharClass.contains(ch) && !containslHS
}
}
result.setNegative(isNegative())
result.mayContainSupplCodepoints = mayContainSupplCodepoints
withoutSurrogates_ .compareAndSwap(null, result.freeze())
return withoutSurrogates_.get()!!
}
/** /**
* Sets this CharClass to negative form, i.e. if they will add some characters and after that set this * Sets this CharClass to negative form, i.e. if they will add some characters and after that set this
@@ -149,68 +168,114 @@ internal abstract class AbstractCharClass : SpecialToken() {
} }
internal abstract class CachedCharClass { internal abstract class CachedCharClass {
private val posValue: AbstractCharClass by lazy { computeValue() } lateinit private var posValue: AbstractCharClass
private val negValue: AbstractCharClass by lazy { computeValue().setNegative(true) }
lateinit private var negValue: AbstractCharClass
// Somewhat ugly init sequence, as computeValue() may depend on fields, initialized in subclass ctor.
protected fun initValues() {
posValue = computeValue()
negValue = computeValue().setNegative(true)
}
fun getValue(negative: Boolean): AbstractCharClass = if (!negative) posValue else negValue fun getValue(negative: Boolean): AbstractCharClass = if (!negative) posValue else negValue
protected abstract fun computeValue(): AbstractCharClass protected abstract fun computeValue(): AbstractCharClass
} }
internal class CachedDigit : CachedCharClass() { internal class CachedDigit : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass = CharClass().add('0', '9') override fun computeValue(): AbstractCharClass = CharClass().add('0', '9')
} }
internal class CachedNonDigit : CachedCharClass() { internal class CachedNonDigit : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass = override fun computeValue(): AbstractCharClass =
CharClass().add('0', '9').setNegative(true).apply { mayContainSupplCodepoints = true } CharClass().add('0', '9').setNegative(true).apply { mayContainSupplCodepoints = true }
} }
internal class CachedSpace : CachedCharClass() { internal class CachedSpace : CachedCharClass() {
init {
initValues()
}
/* 9-13 - \t\n\x0B\f\r; 32 - ' ' */ /* 9-13 - \t\n\x0B\f\r; 32 - ' ' */
override fun computeValue(): AbstractCharClass = CharClass().add(9, 13).add(32) override fun computeValue(): AbstractCharClass = CharClass().add(9, 13).add(32)
} }
internal class CachedNonSpace : CachedCharClass() { internal class CachedNonSpace : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass = override fun computeValue(): AbstractCharClass =
CachedSpace().getValue(negative = true).apply { mayContainSupplCodepoints = true } CachedSpace().getValue(negative = true).apply { mayContainSupplCodepoints = true }
} }
internal class CachedWord : CachedCharClass() { internal class CachedWord : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass = CharClass().add('a', 'z').add('A', 'Z').add('0', '9').add('_') override fun computeValue(): AbstractCharClass = CharClass().add('a', 'z').add('A', 'Z').add('0', '9').add('_')
} }
internal class CachedNonWord : CachedCharClass() { internal class CachedNonWord : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass = override fun computeValue(): AbstractCharClass =
CachedWord().getValue(negative = true).apply { mayContainSupplCodepoints = true } CachedWord().getValue(negative = true).apply { mayContainSupplCodepoints = true }
} }
internal class CachedLower : CachedCharClass() { internal class CachedLower : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass = CharClass().add('a', 'z') override fun computeValue(): AbstractCharClass = CharClass().add('a', 'z')
} }
internal class CachedUpper : CachedCharClass() { internal class CachedUpper : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass = CharClass().add('A', 'Z') override fun computeValue(): AbstractCharClass = CharClass().add('A', 'Z')
} }
internal class CachedASCII : CachedCharClass() { internal class CachedASCII : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass = CharClass().add(0x00, 0x7F) override fun computeValue(): AbstractCharClass = CharClass().add(0x00, 0x7F)
} }
internal class CachedAlpha : CachedCharClass() { internal class CachedAlpha : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass = CharClass().add('a', 'z').add('A', 'Z') override fun computeValue(): AbstractCharClass = CharClass().add('a', 'z').add('A', 'Z')
} }
internal class CachedAlnum : CachedCharClass() { internal class CachedAlnum : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass = override fun computeValue(): AbstractCharClass =
(CachedAlpha().getValue(negative = false) as CharClass).add('0', '9') (CachedAlpha().getValue(negative = false) as CharClass).add('0', '9')
} }
internal class CachedPunct : CachedCharClass() { internal class CachedPunct : CachedCharClass() {
init {
initValues()
}
/* Punctuation !"#$%&'()*+,-./:;<=>?@ [\]^_` {|}~ */ /* Punctuation !"#$%&'()*+,-./:;<=>?@ [\]^_` {|}~ */
override fun computeValue(): AbstractCharClass = CharClass().add(0x21, 0x40).add(0x5B, 0x60).add(0x7B, 0x7E) override fun computeValue(): AbstractCharClass = CharClass().add(0x21, 0x40).add(0x5B, 0x60).add(0x7B, 0x7E)
} }
internal class CachedGraph : CachedCharClass() { internal class CachedGraph : CachedCharClass() {
init {
initValues()
}
/* plus punctuation */ /* plus punctuation */
override fun computeValue(): AbstractCharClass = override fun computeValue(): AbstractCharClass =
(CachedAlnum().getValue(negative = false) as CharClass) (CachedAlnum().getValue(negative = false) as CharClass)
@@ -220,42 +285,60 @@ internal abstract class AbstractCharClass : SpecialToken() {
} }
internal class CachedPrint : CachedCharClass() { internal class CachedPrint : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass = override fun computeValue(): AbstractCharClass =
(CachedGraph().getValue(negative = true) as CharClass).add(0x20) (CachedGraph().getValue(negative = true) as CharClass).add(0x20)
} }
internal class CachedBlank : CachedCharClass() { internal class CachedBlank : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass = CharClass().add(' ').add('\t') override fun computeValue(): AbstractCharClass = CharClass().add(' ').add('\t')
} }
internal class CachedCntrl : CachedCharClass() { internal class CachedCntrl : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass = CharClass().add(0x00, 0x1F).add(0x7F) override fun computeValue(): AbstractCharClass = CharClass().add(0x00, 0x1F).add(0x7F)
} }
internal class CachedXDigit : CachedCharClass() { internal class CachedXDigit : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass = CharClass().add('0', '9').add('a', 'f').add('A', 'F') override fun computeValue(): AbstractCharClass = CharClass().add('0', '9').add('a', 'f').add('A', 'F')
} }
internal class CachedRange(var start: Int, var end: Int) : CachedCharClass() { internal class CachedRange(var start: Int, var end: Int) : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass = override fun computeValue(): AbstractCharClass =
object: AbstractCharClass() { object: AbstractCharClass() {
override fun contains(ch: Int): Boolean = alt xor (ch in start..end) override fun contains(ch: Int): Boolean = alt xor (ch in start..end)
}.apply { }.apply {
if (end >= Char.MIN_SUPPLEMENTARY_CODE_POINT) { if (end >= Char.MIN_SUPPLEMENTARY_CODE_POINT) {
mayContainSupplCodepoints = true mayContainSupplCodepoints = true
}
val minSurrogate = Char.MIN_SURROGATE.toInt()
val maxSurrogate = Char.MAX_SURROGATE.toInt()
// There is an intersection with surrogate characters.
if (end >= minSurrogate && start <= maxSurrogate && start <= end) {
val surrogatesStart = maxOf(start, minSurrogate) - minSurrogate
val surrogatesEnd = minOf(end, maxSurrogate) - minSurrogate
lowHighSurrogates.set(surrogatesStart..surrogatesEnd)
}
} }
val minSurrogate = Char.MIN_SURROGATE.toInt()
val maxSurrogate = Char.MAX_SURROGATE.toInt()
// There is an intersection with surrogate characters.
if (end >= minSurrogate && start <= maxSurrogate && start <= end) {
val surrogatesStart = maxOf(start, minSurrogate) - minSurrogate
val surrogatesEnd = minOf(end, maxSurrogate) - minSurrogate
lowHighSurrogates.set(surrogatesStart..surrogatesEnd)
}
}
} }
internal class CachedSpecialsBlock : CachedCharClass() { internal class CachedSpecialsBlock : CachedCharClass() {
init {
initValues()
}
public override fun computeValue(): AbstractCharClass = CharClass().add(0xFEFF, 0xFEFF).add(0xFFF0, 0xFFFD) public override fun computeValue(): AbstractCharClass = CharClass().add(0xFEFF, 0xFEFF).add(0xFFF0, 0xFFFD)
} }
@@ -263,7 +346,9 @@ internal abstract class AbstractCharClass : SpecialToken() {
val category: Int, val category: Int,
val mayContainSupplCodepoints: Boolean, val mayContainSupplCodepoints: Boolean,
val containsAllSurrogates: Boolean = false) : CachedCharClass() { val containsAllSurrogates: Boolean = false) : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass { override fun computeValue(): AbstractCharClass {
val result = UnicodeCategoryScope(category) val result = UnicodeCategoryScope(category)
if (containsAllSurrogates) { if (containsAllSurrogates) {
@@ -279,7 +364,9 @@ internal abstract class AbstractCharClass : SpecialToken() {
val category: Int, val category: Int,
val mayContainSupplCodepoints: Boolean, val mayContainSupplCodepoints: Boolean,
val containsAllSurrogates: Boolean = false) : CachedCharClass() { val containsAllSurrogates: Boolean = false) : CachedCharClass() {
init {
initValues()
}
override fun computeValue(): AbstractCharClass { override fun computeValue(): AbstractCharClass {
val result = UnicodeCategory(category) val result = UnicodeCategory(category)
if (containsAllSurrogates) { if (containsAllSurrogates) {
@@ -290,206 +377,205 @@ internal abstract class AbstractCharClass : SpecialToken() {
} }
} }
companion object { companion object {
//Char.MAX_SURROGATE - Char.MIN_SURROGATE + 1 //Char.MAX_SURROGATE - Char.MIN_SURROGATE + 1
const val SURROGATE_CARDINALITY = 2048 const val SURROGATE_CARDINALITY = 2048
private var classCache: MutableMap<String, CachedCharClass>? = null
/** /**
* Character classes. * Character classes.
* See http://www.unicode.org/reports/tr18/, http://www.unicode.org/Public/4.1.0/ucd/Blocks.txt * See http://www.unicode.org/reports/tr18/, http://www.unicode.org/Public/4.1.0/ucd/Blocks.txt
*/ */
// TODO: Make a faster implementation. enum class CharClasses(val regexName : String, val factory: () -> CachedCharClass) {
fun createClass(name: String) : CachedCharClass = LOWER("Lower", ::CachedLower),
when (name) { UPPER("Upper", ::CachedUpper),
"Lower" -> CachedLower() ASCII("ASCII", ::CachedASCII),
"Upper" -> CachedUpper() ALPHA("Alpha", ::CachedAlpha),
"ASCII" -> CachedASCII() DIGIT("Digit", ::CachedDigit),
"Alpha" -> CachedAlpha() ALNUM("Alnum", :: CachedAlnum),
"Digit" -> CachedDigit() PUNCT("Punct", ::CachedPunct),
"Alnum" -> CachedAlnum() GRAPH("Graph", ::CachedGraph),
"Punct" -> CachedPunct() PRINT("Print", ::CachedPrint),
"Graph" -> CachedGraph() BLANK("Blank", ::CachedBlank),
"Print" -> CachedPrint() CNTRL("Cntrl", ::CachedCntrl),
"Blank" -> CachedBlank() XDIGIT("XDigit", ::CachedXDigit),
"Cntrl" -> CachedCntrl() SPACE("Space", ::CachedSpace),
"XDigit" -> CachedXDigit() WORD("w", ::CachedWord),
"Space" -> CachedSpace() NON_WORD("W", ::CachedNonWord),
"w" -> CachedWord() SPACE_SHORT("s", ::CachedSpace),
"W" -> CachedNonWord() NON_SPACE("S", ::CachedNonSpace),
"s" -> CachedSpace() DIGIT_SHORT("d", ::CachedDigit),
"S" -> CachedNonSpace() NON_DIGIT("D", ::CachedNonDigit),
"d" -> CachedDigit() BASIC_LATIN("BasicLatin", { CachedRange(0x0000, 0x007F) }),
"D" -> CachedNonDigit() LATIN1_SUPPLEMENT("Latin-1Supplement", { CachedRange(0x0080, 0x00FF) }),
"BasicLatin" -> CachedRange(0x0000, 0x007F) LATIN_EXTENDED_A("LatinExtended-A", { CachedRange(0x0100, 0x017F) }),
"Latin-1Supplement" -> CachedRange(0x0080, 0x00FF) LATIN_EXTENDED_B("LatinExtended-B", { CachedRange(0x0180, 0x024F) }),
"LatinExtended-A" -> CachedRange(0x0100, 0x017F) IPA_EXTENSIONS("IPAExtensions", { CachedRange(0x0250, 0x02AF) }),
"LatinExtended-B" -> CachedRange(0x0180, 0x024F) SPACING_MODIFIER_LETTERS("SpacingModifierLetters", { CachedRange(0x02B0, 0x02FF) }),
"IPAExtensions" -> CachedRange(0x0250, 0x02AF) COMBINING_DIACRITICAL_MARKS("CombiningDiacriticalMarks", { CachedRange(0x0300, 0x036F) }),
"SpacingModifierLetters" -> CachedRange(0x02B0, 0x02FF) GREEK("Greek", { CachedRange(0x0370, 0x03FF) }),
"CombiningDiacriticalMarks" -> CachedRange(0x0300, 0x036F) CYRILLIC("Cyrillic", { CachedRange(0x0400, 0x04FF) }),
"Greek" -> CachedRange(0x0370, 0x03FF) CYRILLIC_SUPPLEMENT("CyrillicSupplement", { CachedRange(0x0500, 0x052F) }),
"Cyrillic" -> CachedRange(0x0400, 0x04FF) ARMENIAN("Armenian", { CachedRange(0x0530, 0x058F) }),
"CyrillicSupplement" -> CachedRange(0x0500, 0x052F) HEBREW("Hebrew", { CachedRange(0x0590, 0x05FF) }),
"Armenian" -> CachedRange(0x0530, 0x058F) ARABIC("Arabic", { CachedRange(0x0600, 0x06FF) }),
"Hebrew" -> CachedRange(0x0590, 0x05FF) SYRIAC("Syriac", { CachedRange(0x0700, 0x074F) }),
"Arabic" -> CachedRange(0x0600, 0x06FF) ARABICSUPPLEMENT("ArabicSupplement", { CachedRange(0x0750, 0x077F) }),
"Syriac" -> CachedRange(0x0700, 0x074F) THAANA("Thaana", { CachedRange(0x0780, 0x07BF) }),
"ArabicSupplement" -> CachedRange(0x0750, 0x077F) DEVANAGARI("Devanagari", { CachedRange(0x0900, 0x097F) }),
"Thaana" -> CachedRange(0x0780, 0x07BF) BENGALI("Bengali", { CachedRange(0x0980, 0x09FF) }),
"Devanagari" -> CachedRange(0x0900, 0x097F) GURMUKHI("Gurmukhi", { CachedRange(0x0A00, 0x0A7F) }),
"Bengali" -> CachedRange(0x0980, 0x09FF) GUJARATI("Gujarati", { CachedRange(0x0A80, 0x0AFF) }),
"Gurmukhi" -> CachedRange(0x0A00, 0x0A7F) ORIYA("Oriya", { CachedRange(0x0B00, 0x0B7F) }),
"Gujarati" -> CachedRange(0x0A80, 0x0AFF) TAMIL("Tamil", { CachedRange(0x0B80, 0x0BFF) }),
"Oriya" -> CachedRange(0x0B00, 0x0B7F) TELUGU("Telugu", { CachedRange(0x0C00, 0x0C7F) }),
"Tamil" -> CachedRange(0x0B80, 0x0BFF) KANNADA("Kannada", { CachedRange(0x0C80, 0x0CFF) }),
"Telugu" -> CachedRange(0x0C00, 0x0C7F) MALAYALAM("Malayalam", { CachedRange(0x0D00, 0x0D7F) }),
"Kannada" -> CachedRange(0x0C80, 0x0CFF) SINHALA("Sinhala", { CachedRange(0x0D80, 0x0DFF) }),
"Malayalam" -> CachedRange(0x0D00, 0x0D7F) THAI("Thai", { CachedRange(0x0E00, 0x0E7F) }),
"Sinhala" -> CachedRange(0x0D80, 0x0DFF) LAO("Lao", { CachedRange(0x0E80, 0x0EFF) }),
"Thai" -> CachedRange(0x0E00, 0x0E7F) TIBETAN("Tibetan", { CachedRange(0x0F00, 0x0FFF) }),
"Lao" -> CachedRange(0x0E80, 0x0EFF) MYANMAR("Myanmar", { CachedRange(0x1000, 0x109F) }),
"Tibetan" -> CachedRange(0x0F00, 0x0FFF) GEORGIAN("Georgian", { CachedRange(0x10A0, 0x10FF) }),
"Myanmar" -> CachedRange(0x1000, 0x109F) HANGULJAMO("HangulJamo", { CachedRange(0x1100, 0x11FF) }),
"Georgian" -> CachedRange(0x10A0, 0x10FF) ETHIOPIC("Ethiopic", { CachedRange(0x1200, 0x137F) }),
"HangulJamo" -> CachedRange(0x1100, 0x11FF) ETHIOPICSUPPLEMENT("EthiopicSupplement", { CachedRange(0x1380, 0x139F) }),
"Ethiopic" -> CachedRange(0x1200, 0x137F) CHEROKEE("Cherokee", { CachedRange(0x13A0, 0x13FF) }),
"EthiopicSupplement" -> CachedRange(0x1380, 0x139F) UNIFIEDCANADIANABORIGINALSYLLABICS("UnifiedCanadianAboriginalSyllabics", { CachedRange(0x1400, 0x167F) }),
"Cherokee" -> CachedRange(0x13A0, 0x13FF) OGHAM("Ogham", { CachedRange(0x1680, 0x169F) }),
"UnifiedCanadianAboriginalSyllabics" -> CachedRange(0x1400, 0x167F) RUNIC("Runic", { CachedRange(0x16A0, 0x16FF) }),
"Ogham" -> CachedRange(0x1680, 0x169F) TAGALOG("Tagalog", { CachedRange(0x1700, 0x171F) }),
"Runic" -> CachedRange(0x16A0, 0x16FF) HANUNOO("Hanunoo", { CachedRange(0x1720, 0x173F) }),
"Tagalog" -> CachedRange(0x1700, 0x171F) BUHID("Buhid", { CachedRange(0x1740, 0x175F) }),
"Hanunoo" -> CachedRange(0x1720, 0x173F) TAGBANWA("Tagbanwa", { CachedRange(0x1760, 0x177F) }),
"Buhid" -> CachedRange(0x1740, 0x175F) KHMER("Khmer", { CachedRange(0x1780, 0x17FF) }),
"Tagbanwa" -> CachedRange(0x1760, 0x177F) MONGOLIAN("Mongolian", { CachedRange(0x1800, 0x18AF) }),
"Khmer" -> CachedRange(0x1780, 0x17FF) LIMBU("Limbu", { CachedRange(0x1900, 0x194F) }),
"Mongolian" -> CachedRange(0x1800, 0x18AF) TAILE("TaiLe", { CachedRange(0x1950, 0x197F) }),
"Limbu" -> CachedRange(0x1900, 0x194F) NEWTAILUE("NewTaiLue", { CachedRange(0x1980, 0x19DF) }),
"TaiLe" -> CachedRange(0x1950, 0x197F) KHMERSYMBOLS("KhmerSymbols", { CachedRange(0x19E0, 0x19FF) }),
"NewTaiLue" -> CachedRange(0x1980, 0x19DF) BUGINESE("Buginese", { CachedRange(0x1A00, 0x1A1F) }),
"KhmerSymbols" -> CachedRange(0x19E0, 0x19FF) PHONETICEXTENSIONS("PhoneticExtensions", { CachedRange(0x1D00, 0x1D7F) }),
"Buginese" -> CachedRange(0x1A00, 0x1A1F) PHONETICEXTENSIONSSUPPLEMENT("PhoneticExtensionsSupplement", { CachedRange(0x1D80, 0x1DBF) }),
"PhoneticExtensions" -> CachedRange(0x1D00, 0x1D7F) COMBININGDIACRITICALMARKSSUPPLEMENT("CombiningDiacriticalMarksSupplement", { CachedRange(0x1DC0, 0x1DFF) }),
"PhoneticExtensionsSupplement" -> CachedRange(0x1D80, 0x1DBF) LATINEXTENDEDADDITIONAL("LatinExtendedAdditional", { CachedRange(0x1E00, 0x1EFF) }),
"CombiningDiacriticalMarksSupplement" -> CachedRange(0x1DC0, 0x1DFF) GREEKEXTENDED("GreekExtended", { CachedRange(0x1F00, 0x1FFF) }),
"LatinExtendedAdditional" -> CachedRange(0x1E00, 0x1EFF) GENERALPUNCTUATION("GeneralPunctuation", { CachedRange(0x2000, 0x206F) }),
"GreekExtended" -> CachedRange(0x1F00, 0x1FFF) SUPERSCRIPTSANDSUBSCRIPTS("SuperscriptsandSubscripts", { CachedRange(0x2070, 0x209F) }),
"GeneralPunctuation" -> CachedRange(0x2000, 0x206F) CURRENCYSYMBOLS("CurrencySymbols", { CachedRange(0x20A0, 0x20CF) }),
"SuperscriptsandSubscripts" -> CachedRange(0x2070, 0x209F) COMBININGMARKSFORSYMBOLS("CombiningMarksforSymbols", { CachedRange(0x20D0, 0x20FF) }),
"CurrencySymbols" -> CachedRange(0x20A0, 0x20CF) LETTERLIKESYMBOLS("LetterlikeSymbols", { CachedRange(0x2100, 0x214F) }),
"CombiningMarksforSymbols" -> CachedRange(0x20D0, 0x20FF) NUMBERFORMS("NumberForms", { CachedRange(0x2150, 0x218F) }),
"LetterlikeSymbols" -> CachedRange(0x2100, 0x214F) ARROWS("Arrows", { CachedRange(0x2190, 0x21FF) }),
"NumberForms" -> CachedRange(0x2150, 0x218F) MATHEMATICALOPERATORS("MathematicalOperators", { CachedRange(0x2200, 0x22FF) }),
"Arrows" -> CachedRange(0x2190, 0x21FF) MISCELLANEOUSTECHNICAL("MiscellaneousTechnical", { CachedRange(0x2300, 0x23FF) }),
"MathematicalOperators" -> CachedRange(0x2200, 0x22FF) CONTROLPICTURES("ControlPictures", { CachedRange(0x2400, 0x243F) }),
"MiscellaneousTechnical" -> CachedRange(0x2300, 0x23FF) OPTICALCHARACTERRECOGNITION("OpticalCharacterRecognition", { CachedRange(0x2440, 0x245F) }),
"ControlPictures" -> CachedRange(0x2400, 0x243F) ENCLOSEDALPHANUMERICS("EnclosedAlphanumerics", { CachedRange(0x2460, 0x24FF) }),
"OpticalCharacterRecognition" -> CachedRange(0x2440, 0x245F) BOXDRAWING("BoxDrawing", { CachedRange(0x2500, 0x257F) }),
"EnclosedAlphanumerics" -> CachedRange(0x2460, 0x24FF) BLOCKELEMENTS("BlockElements", { CachedRange(0x2580, 0x259F) }),
"BoxDrawing" -> CachedRange(0x2500, 0x257F) GEOMETRICSHAPES("GeometricShapes", { CachedRange(0x25A0, 0x25FF) }),
"BlockElements" -> CachedRange(0x2580, 0x259F) MISCELLANEOUSSYMBOLS("MiscellaneousSymbols", { CachedRange(0x2600, 0x26FF) }),
"GeometricShapes" -> CachedRange(0x25A0, 0x25FF) DINGBATS("Dingbats", { CachedRange(0x2700, 0x27BF) }),
"MiscellaneousSymbols" -> CachedRange(0x2600, 0x26FF) MISCELLANEOUSMATHEMATICALSYMBOLS_A("MiscellaneousMathematicalSymbols-A", { CachedRange(0x27C0, 0x27EF) }),
"Dingbats" -> CachedRange(0x2700, 0x27BF) SUPPLEMENTALARROWS_A("SupplementalArrows-A", { CachedRange(0x27F0, 0x27FF) }),
"MiscellaneousMathematicalSymbols-A" -> CachedRange(0x27C0, 0x27EF) BRAILLEPATTERNS("BraillePatterns", { CachedRange(0x2800, 0x28FF) }),
"SupplementalArrows-A" -> CachedRange(0x27F0, 0x27FF) SUPPLEMENTALARROWS_B("SupplementalArrows-B", { CachedRange(0x2900, 0x297F) }),
"BraillePatterns" -> CachedRange(0x2800, 0x28FF) MISCELLANEOUSMATHEMATICALSYMBOLS_B("MiscellaneousMathematicalSymbols-B", { CachedRange(0x2980, 0x29FF) }),
"SupplementalArrows-B" -> CachedRange(0x2900, 0x297F) SUPPLEMENTALMATHEMATICALOPERATORS("SupplementalMathematicalOperators", { CachedRange(0x2A00, 0x2AFF) }),
"MiscellaneousMathematicalSymbols-B" -> CachedRange(0x2980, 0x29FF) MISCELLANEOUSSYMBOLSANDARROWS("MiscellaneousSymbolsandArrows", { CachedRange(0x2B00, 0x2BFF) }),
"SupplementalMathematicalOperators" -> CachedRange(0x2A00, 0x2AFF) GLAGOLITIC("Glagolitic", { CachedRange(0x2C00, 0x2C5F) }),
"MiscellaneousSymbolsandArrows" -> CachedRange(0x2B00, 0x2BFF) COPTIC("Coptic", { CachedRange(0x2C80, 0x2CFF) }),
"Glagolitic" -> CachedRange(0x2C00, 0x2C5F) GEORGIANSUPPLEMENT("GeorgianSupplement", { CachedRange(0x2D00, 0x2D2F) }),
"Coptic" -> CachedRange(0x2C80, 0x2CFF) TIFINAGH("Tifinagh", { CachedRange(0x2D30, 0x2D7F) }),
"GeorgianSupplement" -> CachedRange(0x2D00, 0x2D2F) ETHIOPICEXTENDED("EthiopicExtended", { CachedRange(0x2D80, 0x2DDF) }),
"Tifinagh" -> CachedRange(0x2D30, 0x2D7F) SUPPLEMENTALPUNCTUATION("SupplementalPunctuation", { CachedRange(0x2E00, 0x2E7F) }),
"EthiopicExtended" -> CachedRange(0x2D80, 0x2DDF) CJKRADICALSSUPPLEMENT("CJKRadicalsSupplement", { CachedRange(0x2E80, 0x2EFF) }),
"SupplementalPunctuation" -> CachedRange(0x2E00, 0x2E7F) KANGXIRADICALS("KangxiRadicals", { CachedRange(0x2F00, 0x2FDF) }),
"CJKRadicalsSupplement" -> CachedRange(0x2E80, 0x2EFF) IDEOGRAPHICDESCRIPTIONCHARACTERS("IdeographicDescriptionCharacters", { CachedRange(0x2FF0, 0x2FFF) }),
"KangxiRadicals" -> CachedRange(0x2F00, 0x2FDF) CJKSYMBOLSANDPUNCTUATION("CJKSymbolsandPunctuation", { CachedRange(0x3000, 0x303F) }),
"IdeographicDescriptionCharacters" -> CachedRange(0x2FF0, 0x2FFF) HIRAGANA("Hiragana", { CachedRange(0x3040, 0x309F) }),
"CJKSymbolsandPunctuation" -> CachedRange(0x3000, 0x303F) KATAKANA("Katakana", { CachedRange(0x30A0, 0x30FF) }),
"Hiragana" -> CachedRange(0x3040, 0x309F) BOPOMOFO("Bopomofo", { CachedRange(0x3100, 0x312F) }),
"Katakana" -> CachedRange(0x30A0, 0x30FF) HANGULCOMPATIBILITYJAMO("HangulCompatibilityJamo", { CachedRange(0x3130, 0x318F) }),
"Bopomofo" -> CachedRange(0x3100, 0x312F) KANBUN("Kanbun", { CachedRange(0x3190, 0x319F) }),
"HangulCompatibilityJamo" -> CachedRange(0x3130, 0x318F) BOPOMOFOEXTENDED("BopomofoExtended", { CachedRange(0x31A0, 0x31BF) }),
"Kanbun" -> CachedRange(0x3190, 0x319F) CJKSTROKES("CJKStrokes", { CachedRange(0x31C0, 0x31EF) }),
"BopomofoExtended" -> CachedRange(0x31A0, 0x31BF) KATAKANAPHONETICEXTENSIONS("KatakanaPhoneticExtensions", { CachedRange(0x31F0, 0x31FF) }),
"CJKStrokes" -> CachedRange(0x31C0, 0x31EF) ENCLOSEDCJKLETTERSANDMONTHS("EnclosedCJKLettersandMonths", { CachedRange(0x3200, 0x32FF) }),
"KatakanaPhoneticExtensions" -> CachedRange(0x31F0, 0x31FF) CJKCOMPATIBILITY("CJKCompatibility", { CachedRange(0x3300, 0x33FF) }),
"EnclosedCJKLettersandMonths" -> CachedRange(0x3200, 0x32FF) CJKUNIFIEDIDEOGRAPHSEXTENSIONA("CJKUnifiedIdeographsExtensionA", { CachedRange(0x3400, 0x4DB5) }),
"CJKCompatibility" -> CachedRange(0x3300, 0x33FF) YIJINGHEXAGRAMSYMBOLS("YijingHexagramSymbols", { CachedRange(0x4DC0, 0x4DFF) }),
"CJKUnifiedIdeographsExtensionA" -> CachedRange(0x3400, 0x4DB5) CJKUNIFIEDIDEOGRAPHS("CJKUnifiedIdeographs", { CachedRange(0x4E00, 0x9FFF) }),
"YijingHexagramSymbols" -> CachedRange(0x4DC0, 0x4DFF) YISYLLABLES("YiSyllables", { CachedRange(0xA000, 0xA48F) }),
"CJKUnifiedIdeographs" -> CachedRange(0x4E00, 0x9FFF) YIRADICALS("YiRadicals", { CachedRange(0xA490, 0xA4CF) }),
"YiSyllables" -> CachedRange(0xA000, 0xA48F) MODIFIERTONELETTERS("ModifierToneLetters", { CachedRange(0xA700, 0xA71F) }),
"YiRadicals" -> CachedRange(0xA490, 0xA4CF) SYLOTINAGRI("SylotiNagri", { CachedRange(0xA800, 0xA82F) }),
"ModifierToneLetters" -> CachedRange(0xA700, 0xA71F) HANGULSYLLABLES("HangulSyllables", { CachedRange(0xAC00, 0xD7A3) }),
"SylotiNagri" -> CachedRange(0xA800, 0xA82F) HIGHSURROGATES("HighSurrogates", { CachedRange(0xD800, 0xDB7F) }),
"HangulSyllables" -> CachedRange(0xAC00, 0xD7A3) HIGHPRIVATEUSESURROGATES("HighPrivateUseSurrogates", { CachedRange(0xDB80, 0xDBFF) }),
"HighSurrogates" -> CachedRange(0xD800, 0xDB7F) LOWSURROGATES("LowSurrogates", { CachedRange(0xDC00, 0xDFFF) }),
"HighPrivateUseSurrogates" -> CachedRange(0xDB80, 0xDBFF) PRIVATEUSEAREA("PrivateUseArea", { CachedRange(0xE000, 0xF8FF) }),
"LowSurrogates" -> CachedRange(0xDC00, 0xDFFF) CJKCOMPATIBILITYIDEOGRAPHS("CJKCompatibilityIdeographs", { CachedRange(0xF900, 0xFAFF) }),
"PrivateUseArea" -> CachedRange(0xE000, 0xF8FF) ALPHABETICPRESENTATIONFORMS("AlphabeticPresentationForms", { CachedRange(0xFB00, 0xFB4F) }),
"CJKCompatibilityIdeographs" -> CachedRange(0xF900, 0xFAFF) ARABICPRESENTATIONFORMS_A("ArabicPresentationForms-A", { CachedRange(0xFB50, 0xFDFF) }),
"AlphabeticPresentationForms" -> CachedRange(0xFB00, 0xFB4F) VARIATIONSELECTORS("VariationSelectors", { CachedRange(0xFE00, 0xFE0F) }),
"ArabicPresentationForms-A" -> CachedRange(0xFB50, 0xFDFF) VERTICALFORMS("VerticalForms", { CachedRange(0xFE10, 0xFE1F) }),
"VariationSelectors" -> CachedRange(0xFE00, 0xFE0F) COMBININGHALFMARKS("CombiningHalfMarks", { CachedRange(0xFE20, 0xFE2F) }),
"VerticalForms" -> CachedRange(0xFE10, 0xFE1F) CJKCOMPATIBILITYFORMS("CJKCompatibilityForms", { CachedRange(0xFE30, 0xFE4F) }),
"CombiningHalfMarks" -> CachedRange(0xFE20, 0xFE2F) SMALLFORMVARIANTS("SmallFormVariants", { CachedRange(0xFE50, 0xFE6F) }),
"CJKCompatibilityForms" -> CachedRange(0xFE30, 0xFE4F) ARABICPRESENTATIONFORMS_B("ArabicPresentationForms-B", { CachedRange(0xFE70, 0xFEFF) }),
"SmallFormVariants" -> CachedRange(0xFE50, 0xFE6F) HALFWIDTHANDFULLWIDTHFORMS("HalfwidthandFullwidthForms", { CachedRange(0xFF00, 0xFFEF) }),
"ArabicPresentationForms-B" -> CachedRange(0xFE70, 0xFEFF) ALL("all", { CachedRange(0x00, 0x10FFFF) }),
"HalfwidthandFullwidthForms" -> CachedRange(0xFF00, 0xFFEF) SPECIALS("Specials", ::CachedSpecialsBlock),
"all" -> CachedRange(0x00, 0x10FFFF) CN("Cn", { CachedCategory(CharCategory.UNASSIGNED.value, true) }),
"Specials" -> CachedSpecialsBlock() ISL("IsL", { CachedCategoryScope(0x3E, true) }),
"Cn" -> CachedCategory(CharCategory.UNASSIGNED.value, true) LU("Lu", { CachedCategory(CharCategory.UPPERCASE_LETTER.value, true) }),
"IsL" -> CachedCategoryScope(0x3E, true) LL("Ll", { CachedCategory(CharCategory.LOWERCASE_LETTER.value, true) }),
"Lu" -> CachedCategory(CharCategory.UPPERCASE_LETTER.value, true) LT("Lt", { CachedCategory(CharCategory.TITLECASE_LETTER.value, false) }),
"Ll" -> CachedCategory(CharCategory.LOWERCASE_LETTER.value, true) LM("Lm", { CachedCategory(CharCategory.MODIFIER_LETTER.value, false) }),
"Lt" -> CachedCategory(CharCategory.TITLECASE_LETTER.value, false) LO("Lo", { CachedCategory(CharCategory.OTHER_LETTER.value, true) }),
"Lm" -> CachedCategory(CharCategory.MODIFIER_LETTER.value, false) ISM("IsM", { CachedCategoryScope(0x1C0, true) }),
"Lo" -> CachedCategory(CharCategory.OTHER_LETTER.value, true) MN("Mn", { CachedCategory(CharCategory.NON_SPACING_MARK.value, true) }),
"IsM" -> CachedCategoryScope(0x1C0, true) ME("Me", { CachedCategory(CharCategory.ENCLOSING_MARK.value, false) }),
"Mn" -> CachedCategory(CharCategory.NON_SPACING_MARK.value, true) MC("Mc", { CachedCategory(CharCategory.COMBINING_SPACING_MARK.value, true) }),
"Me" -> CachedCategory(CharCategory.ENCLOSING_MARK.value, false) N("N", { CachedCategoryScope(0xE00, true) }),
"Mc" -> CachedCategory(CharCategory.COMBINING_SPACING_MARK.value, true) ND("Nd", { CachedCategory(CharCategory.DECIMAL_DIGIT_NUMBER.value, true) }),
"N" -> CachedCategoryScope(0xE00, true) NL("Nl", { CachedCategory(CharCategory.LETTER_NUMBER.value, true) }),
"Nd" -> CachedCategory(CharCategory.DECIMAL_DIGIT_NUMBER.value, true) NO("No", { CachedCategory(CharCategory.OTHER_NUMBER.value, true) }),
"Nl" -> CachedCategory(CharCategory.LETTER_NUMBER.value, true) ISZ("IsZ", { CachedCategoryScope(0x7000, false) }),
"No" -> CachedCategory(CharCategory.OTHER_NUMBER.value, true) ZS("Zs", { CachedCategory(CharCategory.SPACE_SEPARATOR.value, false) }),
"IsZ" -> CachedCategoryScope(0x7000, false) ZL("Zl", { CachedCategory(CharCategory.LINE_SEPARATOR.value, false) }),
"Zs" -> CachedCategory(CharCategory.SPACE_SEPARATOR.value, false) ZP("Zp", { CachedCategory(CharCategory.PARAGRAPH_SEPARATOR.value, false) }),
"Zl" -> CachedCategory(CharCategory.LINE_SEPARATOR.value, false) ISC("IsC", { CachedCategoryScope(0xF0000, true, true) }),
"Zp" -> CachedCategory(CharCategory.PARAGRAPH_SEPARATOR.value, false) CC("Cc", { CachedCategory(CharCategory.CONTROL.value, false) }),
"IsC" -> CachedCategoryScope(0xF0000, true, true) CF("Cf", { CachedCategory(CharCategory.FORMAT.value, true) }),
"Cc" -> CachedCategory(CharCategory.CONTROL.value, false) CO("Co", { CachedCategory(CharCategory.PRIVATE_USE.value, true) }),
"Cf" -> CachedCategory(CharCategory.FORMAT.value, true) CS("Cs", { CachedCategory(CharCategory.SURROGATE.value, false, true) }),
"Co" -> CachedCategory(CharCategory.PRIVATE_USE.value, true) ISP("IsP", { CachedCategoryScope((1 shl CharCategory.DASH_PUNCTUATION.value)
"Cs" -> CachedCategory(CharCategory.SURROGATE.value, false, true) or (1 shl CharCategory.START_PUNCTUATION.value)
"IsP" -> CachedCategoryScope(1 shl CharCategory.DASH_PUNCTUATION.value or or (1 shl CharCategory.END_PUNCTUATION.value)
(1 shl CharCategory.START_PUNCTUATION.value) or or (1 shl CharCategory.CONNECTOR_PUNCTUATION.value)
(1 shl CharCategory.END_PUNCTUATION.value) or or (1 shl CharCategory.OTHER_PUNCTUATION.value)
(1 shl CharCategory.CONNECTOR_PUNCTUATION.value) or or (1 shl CharCategory.INITIAL_QUOTE_PUNCTUATION.value)
(1 shl CharCategory.OTHER_PUNCTUATION.value) or or (1 shl CharCategory.FINAL_QUOTE_PUNCTUATION.value), true) }),
(1 shl CharCategory.INITIAL_QUOTE_PUNCTUATION.value) or PD("Pd", { CachedCategory(CharCategory.DASH_PUNCTUATION.value, false) }),
(1 shl CharCategory.FINAL_QUOTE_PUNCTUATION.value), true) PS("Ps", { CachedCategory(CharCategory.START_PUNCTUATION.value, false) }),
"Pd" -> CachedCategory(CharCategory.DASH_PUNCTUATION.value, false) PE("Pe", { CachedCategory(CharCategory.END_PUNCTUATION.value, false) }),
"Ps" -> CachedCategory(CharCategory.START_PUNCTUATION.value, false) PC("Pc", { CachedCategory(CharCategory.CONNECTOR_PUNCTUATION.value, false) }),
"Pe" -> CachedCategory(CharCategory.END_PUNCTUATION.value, false) PO("Po", { CachedCategory(CharCategory.OTHER_PUNCTUATION.value, true) }),
"Pc" -> CachedCategory(CharCategory.CONNECTOR_PUNCTUATION.value, false) ISS("IsS", { CachedCategoryScope(0x7E000000, true) }),
"Po" -> CachedCategory(CharCategory.OTHER_PUNCTUATION.value, true) SM("Sm", { CachedCategory(CharCategory.MATH_SYMBOL.value, true) }),
"IsS" -> CachedCategoryScope(0x7E000000, true) SC("Sc", { CachedCategory(CharCategory.CURRENCY_SYMBOL.value, false) }),
"Sm" -> CachedCategory(CharCategory.MATH_SYMBOL.value, true) SK("Sk", { CachedCategory(CharCategory.MODIFIER_SYMBOL.value, false) }),
"Sc" -> CachedCategory(CharCategory.CURRENCY_SYMBOL.value, false) SO("So", { CachedCategory(CharCategory.OTHER_SYMBOL.value, true) }),
"Sk" -> CachedCategory(CharCategory.MODIFIER_SYMBOL.value, false) PI("Pi", { CachedCategory(CharCategory.INITIAL_QUOTE_PUNCTUATION.value, false) }),
"So" -> CachedCategory(CharCategory.OTHER_SYMBOL.value, true) PF("Pf", { CachedCategory(CharCategory.FINAL_QUOTE_PUNCTUATION.value, false) })
"Pi" -> CachedCategory(CharCategory.INITIAL_QUOTE_PUNCTUATION.value, false) }
"Pf" -> CachedCategory(CharCategory.FINAL_QUOTE_PUNCTUATION.value, false)
else -> throw PatternSyntaxException("No such character class") private val classCache = Array<konan.worker.AtomicReference<CachedCharClass>>(CharClasses.values().size, {
} konan.worker.AtomicReference<CachedCharClass>()
})
private val classCacheMap = CharClasses.values().associate { it -> it.regexName to it }
fun intersects(ch1: Int, ch2: Int): Boolean = ch1 == ch2 fun intersects(ch1: Int, ch2: Int): Boolean = ch1 == ch2
fun intersects(cc: AbstractCharClass, ch: Int): Boolean = cc.contains(ch) fun intersects(cc: AbstractCharClass, ch: Int): Boolean = cc.contains(ch)
@@ -502,15 +588,10 @@ internal abstract class AbstractCharClass : SpecialToken() {
} }
fun getPredefinedClass(name: String, negative: Boolean): AbstractCharClass { fun getPredefinedClass(name: String, negative: Boolean): AbstractCharClass {
var cache = classCache val charClass = classCacheMap[name] ?: throw PatternSyntaxException("No such character class")
if (cache == null) { val cachedClass = classCache[charClass.ordinal].get() ?: run {
cache = mutableMapOf() classCache[charClass.ordinal].compareAndSwap(null, charClass.factory().freeze())
classCache = cache classCache[charClass.ordinal].get()!!
}
var cachedClass = cache[name]
if (cachedClass == null) {
cachedClass = createClass(name)
cache[name] = cachedClass
} }
return cachedClass.getValue(negative) return cachedClass.getValue(negative)
} }
@@ -772,15 +772,15 @@ internal class Lexer(val patternString: String, flags: Int) {
* to description at http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf * to description at http://www.unicode.org/versions/Unicode4.0.0/ch03.pdf
* "3.12 Conjoining Jamo Behavior" * "3.12 Conjoining Jamo Behavior"
*/ */
val SBase = 0xAC00 const val SBase = 0xAC00
val LBase = 0x1100 const val LBase = 0x1100
val VBase = 0x1161 const val VBase = 0x1161
val TBase = 0x11A7 const val TBase = 0x11A7
val SCount = 11172 const val SCount = 11172
val LCount = 19 const val LCount = 19
val VCount = 21 const val VCount = 21
val TCount = 28 const val TCount = 28
val NCount = 588 const val NCount = 588
// Access to the decomposition tables. ========================================================================= // Access to the decomposition tables. =========================================================================
/** Gets canonical class for given codepoint from decomposition mappings table. */ /** Gets canonical class for given codepoint from decomposition mappings table. */
@@ -63,6 +63,7 @@ internal abstract class AbstractSet(val type: Int = 0) {
override fun hasConsumed(matchResult: MatchResultImpl): Boolean = override fun hasConsumed(matchResult: MatchResultImpl): Boolean =
throw AssertionError("This method is not expected to be called.") throw AssertionError("This method is not expected to be called.")
override fun processSecondPassInternal(): AbstractSet = this override fun processSecondPassInternal(): AbstractSet = this
override fun processSecondPass(): AbstractSet = this
} }
} }
@@ -151,7 +152,7 @@ internal abstract class AbstractSet(val type: Int = 0) {
/** /**
* This method performs the second pass without checking if it's already performed or not. * This method performs the second pass without checking if it's already performed or not.
*/ */
open fun processSecondPassInternal(): AbstractSet { protected open fun processSecondPassInternal(): AbstractSet {
if (!next.secondPassVisited) { if (!next.secondPassVisited) {
this.next = next.processSecondPass() this.next = next.processSecondPass()
} }