141 lines
No EOL
4.9 KiB
Kotlin
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")
|
|
}
|
|
} |