feufaro/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/ParseULine.kt
2025-07-10 17:36:56 +02:00

141 lines
No EOL
4.9 KiB
Kotlin

package mg.dot.feufaro.solfa
class ParseULine (var line: String, var measure: Int) {
private var cursorX = 0
var parsedString = ""
private var afterDollar = false
private var inComment = false
private var charX = ' '
companion object {
val mapXLate = mutableMapOf<Char, List<String>>(
'1' to listOf("," , "." , "," , ":"),
'2' to listOf("." , ".-," , ":" , ":-,"),
'3' to listOf(".-," , ".-:" , ":-," , ":-."),
'4' to listOf(":" , ".-;-," , ":-." , ":-.-,"),
'y' to listOf(".,D:", ".-,:D,", ":,D.", ":-,.D,")
)
}
fun parsed() : String {
val matchResult = Regex("^z([048C]):(.+)$").find(line)
if (matchResult != null) {
val capturedChar = matchResult.groups[1]!!.value
cursorX = when (capturedChar) {
"C" -> 12
else -> capturedChar.toInt()
}
line = matchResult.groups[2]!!.value
parsedString = ":"
if (capturedChar == "0") {
parsedString = "|"
}
if (capturedChar == "8") {
parsedString = "!"
}
}
parseUStage1()
parseUStage3()
return parsedString
}
private fun parseUStage1() {
val parsedChars = line
// Beware, Android Regex requires "}" to be escaped!!!
.replace(Regex("\\$\\{x([1-9]\\d*)\\}(.*?)\\$\\{x0\\}")) { matchResult ->
val (nbIteration, iterable) = matchResult.destructured
val nTimes = nbIteration.toInt()
iterable.repeat(nTimes)
}.replace("y", "2z11").toCharArray()
var actualComment = ""
parsedChars.forEach {
if (inComment) {
parsedString += it
if (it == '}') {
inComment = false
val matchMeasure = Regex("^m:(\\d+)(/.*)?").find(actualComment)
if (matchMeasure != null) {
measure = matchMeasure.groups[1]!!.value.toInt()
}
actualComment = ""
} else {
actualComment += it
}
return@forEach
}
if (afterDollar) {
if (it == '{') {
inComment = true
}
afterDollar = false
parsedString += it
return@forEach
}
if (charX != 'z') {
charX = 'D'
}
when (it) {
'$' -> run {
afterDollar = !afterDollar
parsedString += "$"
}
'z', '-' -> run {
charX = it
}
'W' -> repeat(8) { parseUStage2('4')}
'G' -> repeat(4) { parseUStage2('4') }
'C' -> repeat(3) { parseUStage2('4') }
'8' -> repeat(2) { parseUStage2('4') }
'4', '3', '2', '1' -> parseUStage2(it)
'6' -> repeat(2) { parseUStage2('3')}
'9' -> repeat(3) { parseUStage2('3')}
'A' -> run {
parseUStage2('4')
parseUStage2('4')
parseUStage2('2')
}
'(', ')', '/' -> parsedString += it
}
}
}
private fun parseUStage2(codeChar : Char) {
val indexByFour = cursorX % 4
var sequence = mapXLate[codeChar]!![indexByFour]!!
if (charX == 'z') {
sequence = sequence.replace('-', charX)
}
cursorX += codeChar.toString().toInt()
if (sequence.contains(':')) {
val bar: Int = (cursorX / 4) % measure
var replacement = ':'
if ( (bar == 2 && measure == 4 )
|| (bar == 3 && measure in listOf(6, 9, 12))
|| (bar in listOf(6, 9) && measure in listOf(9, 12)))
{
replacement = '!'
}
if (bar == 0) {
replacement = '|'
}
if (replacement != ':') {
sequence = sequence.replace(':', replacement)
}
}
var noteChar = 'D'
if (charX in listOf('z', '-')) {
noteChar = charX
}
parsedString += noteChar + sequence
charX = '-'
}
private fun parseUStage3() {
parsedString = parsedString.replace("-,-", "")
.replace(Regex("([:!|])-,-([:!|])"), "$1-$2")
.replace(Regex("([:!|])-\\.-([:!|])"), "$1-$2")
.replace(Regex("[\\.,]-([:!|])"), "$1")
.replace(Regex("[\\.,]([:!|])"), "$1")
.replace(Regex("([:!|])\\)/"), ")$1/")
.replace(Regex("[:!|]/"), "/")
.replace(Regex("/[:!|]"), "/")
.replace(Regex("[z0]([:!|])"), "$1")
}
}