先読みに対応してコードブロック後の装飾に対応

This commit is contained in:
usbharu 2024-11-14 14:19:12 +09:00
parent b61a40ea32
commit 3ad0cd6f92
Signed by: usbharu
GPG Key ID: 8CB1087135660B8D
3 changed files with 46 additions and 22 deletions

View File

@ -64,18 +64,13 @@ class Lexer {
if (iterator.peekOrNull() == '[') {
tokens.add(Exclamation)
} else {
tokens.add(Text("!"))
addText(tokens, "!")
}
}
else -> {
val lastToken = tokens.lastOrNull()
if (lastToken is Text) {
lastToken.text += next.toString()
} else {
tokens.add(Text(next.toString()))
}
addText(tokens, next.toString())
}
}
if (!inline && tokens.lastOrNull() !is Whitespace) { //行頭が空白の場合は一旦無視する
@ -105,13 +100,22 @@ class Lexer {
return tokens
}
private fun addText(tokens: MutableList<Token>, next: String) {
val lastToken = tokens.lastOrNull()
if (lastToken is Text) {
lastToken.text += next
} else {
tokens.add(Text(next))
}
}
private fun codeblock(
iterator: PeekableCharIterator,
next: Char,
tokens: MutableList<Token>,
inCode: Boolean,
codeBuffer: StringBuilder,
inline: Boolean
inline: Boolean,
): Boolean {
var inCode1 = inCode
if (iterator.peekOrNull() == next && !inline) { //行頭かつ次の文字が`
@ -157,20 +161,16 @@ class Lexer {
}
} else {
val codeBuilder = StringBuilder()
while (iterator.hasNext() && iterator.peekOrNull() != next) {
codeBuilder.append(iterator.next())
}
if (iterator.hasNext() && iterator.next() == next) { //インラインコードブロックかと思ったら違った
if (codeBuilder.isEmpty()) {
tokens.add(Text("$next$next"))
} else {
tokens.add(InlineCodeBlock(codeBuilder.toString()))
}
val peekString = peekString(next, iterator)
if (peekString != null && peekString.isEmpty()) {
addText(tokens, "$next$next")
iterator.next()
} else if (peekString != null) {
tokens.add(InlineCodeBlock(peekString))
iterator.skip(peekString.length + 1)
} else {
tokens.add(Text(codeBuilder.insert(0, next).toString()))
addText(tokens, next.toString())
}
}
return inCode1
}
@ -345,6 +345,19 @@ class Lexer {
return count
}
fun peekString(char: Char, iterator: PeekableCharIterator): String? {
var counter = 0
val stringBuilder = StringBuilder()
while (iterator.peekOrNull(counter) != null && iterator.peekOrNull(counter) != char) {
stringBuilder.append(iterator.peekOrNull(counter))
counter++
}
if (iterator.peekOrNull(counter) == null) {
return null
}
return stringBuilder.toString()
}
fun collect(iterator: PeekableCharIterator): String {
val char = mutableListOf<Char>()
while (iterator.hasNext()) {

View File

@ -15,6 +15,12 @@ class PeekableCharIterator(private val charArray: CharArray) : Iterator<Char> {
fun peekOrNull(): Char? = charArray.getOrNull(index)
fun current(): Int = index
fun peekOrNull(offset: Int): Char? = charArray.getOrNull(index + offset)
fun skip(count: Int = 0) {
index += count
}
}
class PeekableStringIterator(private val list: List<String>) : Iterator<String> {

View File

@ -756,7 +756,7 @@ class LexerTest {
assertContentEquals(
listOf(
Text("```"), Text("`aiueo")
Text("````aiueo")
), actual
)
}
@ -816,7 +816,12 @@ class LexerTest {
assertContentEquals(
listOf(
Text("aiueo"), Whitespace(1, ' '), Text("```abcd")
Text("aiueo"),
Whitespace(1, ' '),
Text("```abcd"),
Asterisk(1, '*'),
Text("a"),
Asterisk(1, '*')
), actual
)
}