feat: whenの書き方を変更しアスタリスクに対応
This commit is contained in:
parent
21087e0244
commit
0a972cb8eb
|
@ -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,55 +34,34 @@ class Lexer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ->
|
next in '0'..'9' || next in '0'..'9' ->
|
||||||
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
|
||||||
'h' -> {
|
)
|
||||||
//todo httpにも対応
|
) //nextの分1足す
|
||||||
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()))
|
|
||||||
continue@char
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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()))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
next == 'h' -> url(next, iterator, tokens)
|
||||||
|
|
||||||
|
next == '*' -> {
|
||||||
|
var count = 1
|
||||||
|
while (iterator.peekOrNull() == '*') {
|
||||||
|
count++
|
||||||
|
iterator.next()
|
||||||
|
}
|
||||||
|
tokens.add(Asterisk(count))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
val lastToken = tokens.lastOrNull()
|
val lastToken = tokens.lastOrNull()
|
||||||
|
@ -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() == "") {
|
||||||
|
|
|
@ -23,3 +23,4 @@ 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()
|
|
@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue