[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 ========================================================================================
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 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. */
private val lexemes = Lexer(pattern, flags)
/** All back references that may be used in pattern. */
private val backRefs = arrayOfNulls<FSet>(BACK_REF_NUMBER)
/** List of all capturing groups in the pattern. Primarily used for handling back references. */
val capturingGroups = mutableListOf<FSet>()
/** Mapping from group name to its index */
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.*/
private var needsBackRefReplacement = false
/** Global count of found capturing groups. */
var capturingGroupCount = 0
private set
/** A number of group quantifiers in the pattern */
var groupQuantifierCount = 0
private set
/**
* 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
private set
@@ -127,16 +123,15 @@ internal class Pattern(val pattern: String, flags: Int = 0) {
fSet = FinalSet()
saveChangedFlags = true
} else {
fSet = FSet(capturingGroupCount)
}
if (capturingGroupCount < BACK_REF_NUMBER) {
backRefs[capturingGroupCount] = fSet
fSet = FSet(capturingGroups.size)
}
capturingGroups.add(fSet)
if (ch == Lexer.CHAR_NAMED_GROUP) {
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 '8'.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)
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. */
private fun createBackReference(groupIndex: Int): BackReferenceSet {
if (groupIndex >= 0 && groupIndex < capturingGroupCount) { // All is ok - the group exists.
// backRefs[groupIndex] is proved to be not null because the group is already created (groupIndex < capturingGroupCount)
backRefs[groupIndex]!!.isBackReferenced = true
if (groupIndex >= 0 && groupIndex < capturingGroups.size) {
capturingGroups[groupIndex].isBackReferenced = true
needsBackRefReplacement = true // And process back references in the second pass.
return BackReferenceSet(groupIndex, consumersCount++, hasFlag(CASE_INSENSITIVE))
} else {
@@ -888,9 +891,6 @@ internal class Pattern(val pattern: String, flags: Int = 0) {
*/
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 */
internal val flagsBitMask = Pattern.UNIX_LINES or
Pattern.CASE_INSENSITIVE or