commonMain.org.intellij.markdown.parser.sequentialparsers.TokensCache.kt Maven / Gradle / Ivy
package org.intellij.markdown.parser.sequentialparsers
import org.intellij.markdown.IElementType
import org.intellij.markdown.lexer.Compat.assert
import org.intellij.markdown.lexer.TokenInfo
abstract class TokensCache {
abstract val cachedTokens: List
abstract val filteredTokens: List
abstract val originalText: CharSequence
abstract val originalTextRange: IntRange
fun getRawCharAt(index: Int): Char {
if (index < originalTextRange.first) return 0.toChar()
if (index > originalTextRange.last) return 0.toChar()
return originalText[index]
}
protected fun verify() {
for (i in cachedTokens.indices) {
assert(cachedTokens[i].rawIndex == i)
}
for (i in filteredTokens.indices) {
assert(filteredTokens[i].normIndex == i)
}
}
inner class RangesListIterator private constructor(private val ranges: List,
private val listIndex: Int,
value: Int) : Iterator(value) {
constructor(ranges: List) : this(ranges, 0, ranges.firstOrNull()?.start ?: -1)
override fun advance(): RangesListIterator {
if (listIndex >= ranges.size) {
return this
}
if (index == ranges[listIndex].last) {
return RangesListIterator(ranges, listIndex + 1, ranges.getOrNull(listIndex + 1)?.start ?: filteredTokens.size)
}
return RangesListIterator(ranges, listIndex, index + 1)
}
override fun rollback(): RangesListIterator {
if (listIndex < 0) {
return this
}
if (index == ranges[listIndex].first) {
return RangesListIterator(ranges, listIndex - 1, ranges.getOrNull(listIndex - 1)?.endInclusive ?: -1)
}
return RangesListIterator(ranges, listIndex, index - 1)
}
override fun rawLookup(steps: Int): IElementType? {
if (index + steps in ranges.getOrNull(listIndex) ?: return null) {
return super.rawLookup(steps)
}
return null
}
}
inner open class Iterator(val index: Int) {
val type : IElementType?
get() {
return info(0).type
}
val firstChar: Char
get() {
return getRawCharAt(info(0).tokenStart)
}
val length: Int
get() {
return info(0).tokenEnd - info(0).tokenStart
}
val start: Int
get() {
return info(0).tokenStart
}
val end: Int
get() {
return info(0).tokenEnd
}
open fun advance(): Iterator {
return Iterator(index + 1)
}
open fun rollback(): Iterator {
return Iterator(index - 1)
}
private fun info(rawSteps: Int): TokenInfo {
if (index < 0) {
return TokenInfo(null, originalTextRange.first, originalTextRange.first, 0, 0)
} else if (index > filteredTokens.size) {
return TokenInfo(null, originalTextRange.last + 1, originalTextRange.last + 1, 0, 0)
}
val rawIndex = if (index < filteredTokens.size)
filteredTokens[index].rawIndex + rawSteps
else
cachedTokens.size + rawSteps
if (rawIndex < 0) {
return TokenInfo(null, originalTextRange.first, originalTextRange.first, 0, 0)
} else if (rawIndex >= cachedTokens.size) {
return TokenInfo(null, originalTextRange.last + 1, originalTextRange.last + 1, 0, 0)
}
return cachedTokens[rawIndex]
}
open fun rawLookup(steps: Int): IElementType? {
return info(steps).type
}
fun rawStart(steps: Int): Int {
return info(steps).tokenStart
}
open fun charLookup(steps: Int): Char {
if (steps == 0) {
return getRawCharAt(start)
}
if (steps == 1) {
return getRawCharAt(end)
} else if (steps == -1) {
return getRawCharAt(start - 1)
} else {
val pos = if (steps > 0) rawStart(steps) else rawStart(steps + 1) - 1
return getRawCharAt(pos)
}
}
override fun toString(): String {
return "Iterator: $index: $type"
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy