[K/N and WASM] Support back references to groups with multi-digit index #KT-51776

This commit is contained in:
Abduqodiri Qurbonzoda
2022-02-17 20:05:12 +03:00
committed by Space
parent 9c4c1ed557
commit d500d03baa
2 changed files with 21 additions and 21 deletions
@@ -36,7 +36,7 @@ constructor (internal val input: CharSequence,
// Harmony's implementation ======================================================================================== // Harmony's implementation ========================================================================================
private val nativePattern = regex.nativePattern private val nativePattern = regex.nativePattern
private val groupCount = nativePattern.capturingGroupCount private val groupCount = nativePattern.capturingGroups.size
private val groupBounds = IntArray(groupCount * 2) { -1 } private val groupBounds = IntArray(groupCount * 2) { -1 }
private val consumers = IntArray(nativePattern.consumersCount + 1) { -1 } private val consumers = IntArray(nativePattern.consumersCount + 1) { -1 }
@@ -32,8 +32,8 @@ internal class Pattern(val pattern: String, flags: Int = 0) {
/** A lexer instance used to get tokens from the pattern. */ /** A lexer instance used to get tokens from the pattern. */
private val lexemes = Lexer(pattern, flags) private val lexemes = Lexer(pattern, flags)
/** All back references that may be used in pattern. */ /** List of all capturing groups in the pattern. Primarily used for handling back references. */
private val backRefs = arrayOfNulls<FSet>(BACK_REF_NUMBER) val capturingGroups = mutableListOf<FSet>()
/** Mapping from group name to its index */ /** Mapping from group name to its index */
val groupNameToIndex = hashMapOf<String, Int>() val groupNameToIndex = hashMapOf<String, Int>()
@@ -41,17 +41,13 @@ internal class Pattern(val pattern: String, flags: Int = 0) {
/** Is true if back referenced sets replacement by second compilation pass is needed.*/ /** Is true if back referenced sets replacement by second compilation pass is needed.*/
private var needsBackRefReplacement = false private var needsBackRefReplacement = false
/** Global count of found capturing groups. */
var capturingGroupCount = 0
private set
/** A number of group quantifiers in the pattern */ /** A number of group quantifiers in the pattern */
var groupQuantifierCount = 0 var groupQuantifierCount = 0
private set private set
/** /**
* A number of consumers found in the pattern. * A number of consumers found in the pattern.
* Consumer is any expression ending with an FSet except capturing groups (they are counted by [capturingGroupCount]) * Consumer is any expression ending with an FSet except capturing groups (they are counted by [capturingGroups])
*/ */
var consumersCount = 0 var consumersCount = 0
private set private set
@@ -127,16 +123,15 @@ internal class Pattern(val pattern: String, flags: Int = 0) {
fSet = FinalSet() fSet = FinalSet()
saveChangedFlags = true saveChangedFlags = true
} else { } else {
fSet = FSet(capturingGroupCount) fSet = FSet(capturingGroups.size)
}
if (capturingGroupCount < BACK_REF_NUMBER) {
backRefs[capturingGroupCount] = fSet
} }
capturingGroups.add(fSet)
if (ch == Lexer.CHAR_NAMED_GROUP) { if (ch == Lexer.CHAR_NAMED_GROUP) {
val name = (lexemes.curSpecialToken as NamedGroup).name val name = (lexemes.curSpecialToken as NamedGroup).name
groupNameToIndex[name] = capturingGroupCount groupNameToIndex[name] = fSet.groupIndex
} }
capturingGroupCount++
} }
} }
@@ -579,7 +574,16 @@ internal class Pattern(val pattern: String, flags: Int = 0) {
0x80000000.toInt() or '7'.toInt(), 0x80000000.toInt() or '7'.toInt(),
0x80000000.toInt() or '8'.toInt(), 0x80000000.toInt() or '8'.toInt(),
0x80000000.toInt() or '9'.toInt() -> { 0x80000000.toInt() or '9'.toInt() -> {
val groupIndex = (char and 0x7FFFFFFF) - '0'.toInt() var groupIndex = (char and 0x7FFFFFFF) - '0'.code
while (lexemes.lookAhead in '0'.code..'9'.code) {
val newGroupIndex = (groupIndex * 10) + (lexemes.lookAhead - '0'.code)
if (newGroupIndex in 0 until capturingGroups.size) {
groupIndex = newGroupIndex
lexemes.next()
} else {
break
}
}
term = createBackReference(groupIndex) term = createBackReference(groupIndex)
lexemes.next() lexemes.next()
} }
@@ -636,9 +640,8 @@ internal class Pattern(val pattern: String, flags: Int = 0) {
/** Creates a back reference to the group with specified [groupIndex], or throws if the group doesn't exist yet. */ /** Creates a back reference to the group with specified [groupIndex], or throws if the group doesn't exist yet. */
private fun createBackReference(groupIndex: Int): BackReferenceSet { private fun createBackReference(groupIndex: Int): BackReferenceSet {
if (groupIndex >= 0 && groupIndex < capturingGroupCount) { // All is ok - the group exists. if (groupIndex >= 0 && groupIndex < capturingGroups.size) {
// backRefs[groupIndex] is proved to be not null because the group is already created (groupIndex < capturingGroupCount) capturingGroups[groupIndex].isBackReferenced = true
backRefs[groupIndex]!!.isBackReferenced = true
needsBackRefReplacement = true // And process back references in the second pass. needsBackRefReplacement = true // And process back references in the second pass.
return BackReferenceSet(groupIndex, consumersCount++, hasFlag(CASE_INSENSITIVE)) return BackReferenceSet(groupIndex, consumersCount++, hasFlag(CASE_INSENSITIVE))
} else { } else {
@@ -888,9 +891,6 @@ internal class Pattern(val pattern: String, flags: Int = 0) {
*/ */
val CANON_EQ = 1 shl 6 val CANON_EQ = 1 shl 6
/** Max number of back references supported. */
internal val BACK_REF_NUMBER = 10
/** A bit mask that includes all defined match flags */ /** A bit mask that includes all defined match flags */
internal val flagsBitMask = Pattern.UNIX_LINES or internal val flagsBitMask = Pattern.UNIX_LINES or
Pattern.CASE_INSENSITIVE or Pattern.CASE_INSENSITIVE or