multiline string literals

This commit is contained in:
sergeych committed 2025-08-10 23:32:03 +03:00
1 parent ed0a21cb06
commit 63de82393a
8 files changed
+109 -18

No files matched your search

+1 -1
View File
@@ -4,7 +4,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
group = "net.sergeych"
version = "0.8.4-SNAPSHOT"
version = "0.8.5-SNAPSHOT"
buildscript {
repositories {
@@ -375,6 +375,32 @@ private class Parser(fromPos: Pos) {
private val currentChar: Char get() = pos.currentChar
private fun fixMultilineStringLiteral(source: String): String {
val sizes = mutableListOf<Int>()
val lines = source.lines().toMutableList()
if( lines.size == 0 ) return ""
if( lines[0].isBlank() ) lines.removeFirst()
if( lines.isEmpty()) return ""
if( lines.last().isBlank() ) lines.removeLast()
val normalized = lines.map { l ->
if( l.isBlank() ) {
sizes.add(-1)
""
}
else {
val margin = leftMargin(l)
sizes += margin
" ".repeat(margin) + l.trim()
}
}
val commonMargin = sizes.filter { it >= 0 }.min()
val fixed = if( commonMargin < 1 ) lines else normalized.map {
if( it.isBlank() ) "" else it.drop(commonMargin)
}
return fixed.joinToString("\n")
}
private fun loadStringToken(): Token {
val start = currentPos
@@ -383,6 +409,7 @@ private class Parser(fromPos: Pos) {
// start = start.back()
val sb = StringBuilder()
var newlineDetected = false
while (currentChar != '"') {
if (pos.end) throw ScriptError(start, "unterminated string started there")
when (currentChar) {
@@ -397,6 +424,12 @@ private class Parser(fromPos: Pos) {
}
}
'\n', '\r'-> {
newlineDetected = true
sb.append(currentChar)
pos.advance()
}
else -> {
sb.append(currentChar)
pos.advance()
@@ -404,7 +437,10 @@ private class Parser(fromPos: Pos) {
}
}
pos.advance()
return Token(sb.toString(), start, Token.Type.STRING)
val result = sb.toString().let { if( newlineDetected ) fixMultilineStringLiteral(it) else it }
return Token(result, start, Token.Type.STRING)
}
/**
@@ -0,0 +1,13 @@
package net.sergeych.lyng
fun leftMargin(s: String): Int {
var cnt = 0
for (c in s) {
when (c) {
' ' -> cnt++
'\t' -> cnt = (cnt / 4.0 + 0.9).toInt() * 4
else -> break
}
}
return cnt
}
@@ -2794,4 +2794,45 @@ class ScriptTest {
println(y.list)
}
@Test
fun testMultilineStrings() = runTest {
assertEquals(
"""
This is a multiline text.
This is a second line.
""".trimIndent(), eval(
"""
"
This is a multiline text.
This is a second line.
"
""".trimIndent()
).toString()
)
assertEquals(
"""
This is a multiline text.
""".trimIndent(), eval(
"""
"
This is a multiline text.
"
""".trimIndent()
).toString()
)
assertEquals(
"""
This is a multiline text.
""".trimIndent(), eval(
"""
"
This is a multiline text.
"
""".trimIndent()
).toString()
)
}
}
+1 -12
View File
@@ -6,6 +6,7 @@ import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import net.sergeych.lyng.Scope
import net.sergeych.lyng.Script
import net.sergeych.lyng.leftMargin
import net.sergeych.lyng.obj.ObjVoid
import java.nio.file.Files
import java.nio.file.Files.readAllLines
@@ -16,18 +17,6 @@ import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.fail
fun leftMargin(s: String): Int {
var cnt = 0
for (c in s) {
when (c) {
' ' -> cnt++
'\t' -> cnt = (cnt / 4.0 + 0.9).toInt() * 4
else -> break
}
}
return cnt
}
data class DocTest(
val fileName: String,
val line: Int,