feat: whenの書き方を変更しアスタリスクに対応

This commit is contained in:
usbharu 2024-11-13 12:02:21 +09:00
parent 21087e0244
commit 0a972cb8eb
Signed by: usbharu
GPG Key ID: 8CB1087135660B8D
3 changed files with 103 additions and 53 deletions

View File

@ -6,6 +6,9 @@ class Lexer {
fun lex(input: String): List<Token> { fun lex(input: String): List<Token> {
val tokens = mutableListOf<Token>() val tokens = mutableListOf<Token>()
val lines = PeekableStringIterator(input.lines()) val lines = PeekableStringIterator(input.lines())
var inQuote = false
line@ while (lines.hasNext()) { line@ while (lines.hasNext()) {
if (lines.peekOrNull() == "") { if (lines.peekOrNull() == "") {
@ -15,10 +18,15 @@ class Lexer {
val iterator = PeekableCharIterator(line.toCharArray()) val iterator = PeekableCharIterator(line.toCharArray())
char@ while (iterator.hasNext()) { char@ while (iterator.hasNext()) {
when (val next = iterator.next()) { val next = iterator.next()
'#', '' -> header(iterator, tokens) when {
'>', '' -> quote(iterator, tokens) next == '#' || next == '' -> header(iterator, tokens)
'-', '=', 'ー', '' -> { (next == '>' || next == '') && !inQuote -> {
inQuote = true
quote(iterator, tokens)
}
next == '-' || next == '=' || next == 'ー' || next == '' -> {
if (iterator.peekOrNull()?.isWhitespace() == true) { //-の直後がスペースならリストの可能性 if (iterator.peekOrNull()?.isWhitespace() == true) { //-の直後がスペースならリストの可能性
list(iterator, tokens) list(iterator, tokens)
} else {//それ以外ならセパレーターの可能性 } else {//それ以外ならセパレーターの可能性
@ -26,56 +34,35 @@ class Lexer {
} }
} }
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '', '', '', '', '', '', '', '', '', '' -> next in '0'..'9' || next in ''..'' ->
decimalList(iterator, tokens, next) decimalList(iterator, tokens, next)
'[', '「' -> { next == '[' || next == '「' -> tokens.add(SquareBracketStart)
tokens.add(SquareBracketStart)
}
']', '」' -> { next == ']' || next == '」' -> tokens.add(SquareBracketEnd)
tokens.add(SquareBracketEnd)
}
'', '(' -> { next == '' || next == '(' -> tokens.add(ParenthesesStart)
tokens.add(ParenthesesStart)
}
')', '' -> { next == ')' || next == '' -> tokens.add(ParenthesesEnd)
tokens.add(ParenthesesEnd)
}
' ', ' ' -> { next.isWhitespace() -> tokens.add(
tokens.add(Whitespace(skipWhitespace(iterator) + 1, next)) //nextの分1足す Whitespace(
} skipWhitespace(iterator) + 1,
next
)
) //nextの分1足す
'h' -> { next == 'h' -> url(next, iterator, tokens)
//todo httpにも対応
val charIterator = "ttps://".iterator() next == '*' -> {
val urlBuilder = StringBuilder() var count = 1
urlBuilder.append(next) while (iterator.peekOrNull() == '*') {
while (charIterator.hasNext() && iterator.hasNext()) { count++
val nextC = charIterator.next() iterator.next()
val nextC2 = iterator.next()
urlBuilder.append(nextC2)
if (nextC != nextC2) {
tokens.add(Text(urlBuilder.toString()))
continue@char
}
} }
if (urlBuilder.length == 1) { tokens.add(Asterisk(count))
tokens.add(Text(urlBuilder.toString())) //hだけのときはURLじゃないのでテキストとして追加
} else {
while (iterator.hasNext() && iterator.peekOrNull()?.isWhitespace() != true) {
urlBuilder.append(iterator.next())
}
tokens.add(Url(urlBuilder.toString()))
}
} }
else -> { else -> {
val lastToken = tokens.lastOrNull() val lastToken = tokens.lastOrNull()
if (lastToken is Text) { if (lastToken is Text) {
@ -89,7 +76,7 @@ class Lexer {
tokens.add(Break(1)) tokens.add(Break(1))
} }
inQuote = false
} }
println(tokens) println(tokens)
@ -104,10 +91,38 @@ class Lexer {
return tokens return tokens
} }
private fun url(
next: Char,
iterator: PeekableCharIterator,
tokens: MutableList<Token>,
) {
//todo httpにも対応
val charIterator = "ttps://".iterator()
val urlBuilder = StringBuilder()
urlBuilder.append(next)
while (charIterator.hasNext() && iterator.hasNext()) {
val nextC = charIterator.next()
val nextC2 = iterator.next()
urlBuilder.append(nextC2)
if (nextC != nextC2) {
tokens.add(Text(urlBuilder.toString()))
return
}
}
if (urlBuilder.length == 1) {
tokens.add(Text(urlBuilder.toString())) //hだけのときはURLじゃないのでテキストとして追加
} else {
while (iterator.hasNext() && iterator.peekOrNull()?.isWhitespace() != true) {
urlBuilder.append(iterator.next())
}
tokens.add(Url(urlBuilder.toString()))
}
}
private fun decimalList( private fun decimalList(
iterator: PeekableCharIterator, iterator: PeekableCharIterator,
tokens: MutableList<Token>, tokens: MutableList<Token>,
next: Char next: Char,
) { ) {
val comma = iterator.peekOrNull() val comma = iterator.peekOrNull()
if (comma == null) { if (comma == null) {
@ -127,7 +142,7 @@ class Lexer {
private fun list( private fun list(
iterator: PeekableCharIterator, iterator: PeekableCharIterator,
tokens: MutableList<Token> tokens: MutableList<Token>,
) { ) {
if (iterator.peekOrNull()?.isWhitespace() == true) { if (iterator.peekOrNull()?.isWhitespace() == true) {
@ -159,7 +174,7 @@ class Lexer {
private fun separator( private fun separator(
next: Char, next: Char,
iterator: PeekableCharIterator, iterator: PeekableCharIterator,
tokens: MutableList<Token> tokens: MutableList<Token>,
) { ) {
val builder = StringBuilder() val builder = StringBuilder()
builder.append(next) builder.append(next)
@ -181,7 +196,7 @@ class Lexer {
private fun quote( private fun quote(
iterator: PeekableCharIterator, iterator: PeekableCharIterator,
tokens: MutableList<Token> tokens: MutableList<Token>,
) { ) {
var count = 1 var count = 1
while (iterator.peekOrNull()?.isWhitespace() == false) { while (iterator.peekOrNull()?.isWhitespace() == false) {
@ -190,12 +205,11 @@ class Lexer {
} }
tokens.add(Quote(count)) tokens.add(Quote(count))
skipWhitespace(iterator) skipWhitespace(iterator)
tokens.add(Text(collect(iterator)))
} }
private fun header( private fun header(
iterator: PeekableCharIterator, iterator: PeekableCharIterator,
tokens: MutableList<Token> tokens: MutableList<Token>,
) { ) {
var count = 1 var count = 1
while (iterator.peekOrNull()?.isWhitespace() == false) { while (iterator.peekOrNull()?.isWhitespace() == false) {
@ -229,7 +243,7 @@ class Lexer {
*/ */
private fun blankLine( private fun blankLine(
lines: PeekableStringIterator, lines: PeekableStringIterator,
tokens: MutableList<Token> tokens: MutableList<Token>,
) { ) {
var count = 0 var count = 0
while (lines.peekOrNull() == "") { while (lines.peekOrNull() == "") {

View File

@ -22,4 +22,5 @@ data object SquareBracketStart : Token()
data object SquareBracketEnd : Token() data object SquareBracketEnd : Token()
data object ParenthesesStart : Token() data object ParenthesesStart : Token()
data object ParenthesesEnd : Token() data object ParenthesesEnd : Token()
data class Url(var url: String) : Token() data class Url(var url: String) : Token()
data class Asterisk(var count: Int) : Token()

View File

@ -483,4 +483,39 @@ class LexerTest {
), actual ), actual
) )
} }
@Test
fun アスタリスク() {
val lexer = Lexer()
val actual = lexer.lex("*a*")
println(actual)
assertContentEquals(
listOf(
Asterisk(1),
Text("a"),
Asterisk(1)
), actual
)
}
@Test
fun アスタリスク2() {
val lexer = Lexer()
val actual = lexer.lex("> *a*")
println(actual)
assertContentEquals(
listOf(
Quote(1),
Asterisk(1),
Text("a"),
Asterisk(1)
), actual
)
}
} }