sergeych 71a2933066 more on classes
universal args declaration parser, lambda code rewritten to it
2025-06-08 13:35:51 +04:00

85 lines
2.2 KiB
Kotlin

package net.sergeych.lyng
data class Pos(val source: Source, val line: Int, val column: Int) {
override fun toString(): String {
return "${source.fileName}:${line+1}:${column}"
}
fun back(): Pos =
if( column > 0) Pos(source, line, column-1)
else if( line > 0) Pos(source, line-1, source.lines[line-1].length - 1)
else throw IllegalStateException("can't go back from line 0, column 0")
val currentLine: String get() = if( end ) "EOF" else source.lines[line]
val end: Boolean get() = line >= source.lines.size
companion object {
val builtIn = Pos(Source.builtIn, 0, 0)
val UNKNOWN = Pos(Source.UNKNOWN, -1, -1)
}
}
class MutablePos(private val from: Pos) {
val lines = from.source.lines
var line = from.line
private set
var column = from.column
private set
val end: Boolean get() =
line == lines.size
fun toPos(): Pos = Pos(from.source, line, column)
fun advance(): Char? {
if (end) return null
val current = lines[line]
return if (column < current.length) {
column++
currentChar
} else {
column = 0
if(++line >= lines.size) null
else currentChar
}
}
fun resetTo(pos: Pos) { line = pos.line; column = pos.column }
fun back() {
if (column > 0) column--
else if (line > 0)
column = lines[--line].length - 1
else throw IllegalStateException("can't go back from line 0, column 0")
}
val currentChar: Char
get() {
if (end) return 0.toChar()
val current = lines[line]
return if (column >= current.length) '\n'
else current[column]
}
/**
* If the next characters are equal to the fragment, advances the position and returns true.
* Otherwise, does nothing and returns false.
*/
fun readFragment(fragment: String): Boolean {
val mark = toPos()
for(ch in fragment)
if( currentChar != ch ) { resetTo(mark); return false }
else advance()
return true
}
override fun toString() = "($line:$column)"
init {
if( lines[0].isEmpty()) advance()
}
}