transcendental-lisp/src/main/kotlin/token/TokenFactoryImpl.kt

57 lines
2.1 KiB
Kotlin

package token
import file.FilePosition
import token.TokenFactory.BadCharacterException
import token.TokenFactory.EmptyTokenTextException
import util.Characters.AT_SIGN
import util.Characters.BACKQUOTE
import util.Characters.COMMA
import util.Characters.DOUBLE_QUOTE
import util.Characters.LEFT_PARENTHESIS
import util.Characters.RIGHT_PARENTHESIS
import util.Characters.SINGLE_QUOTE
import util.Characters.isLegalIdentifierCharacter
import util.Characters.isNumberPrefix
import java.lang.Character.isDigit
class TokenFactoryImpl : TokenFactory {
override fun createToken(text: String, position: FilePosition): Token {
if (text.isEmpty())
throw EmptyTokenTextException(position)
val firstCharacter = text[0]
return when (firstCharacter) {
LEFT_PARENTHESIS -> LeftParenthesis(text, position)
RIGHT_PARENTHESIS -> RightParenthesis(text, position)
SINGLE_QUOTE -> QuoteMark(text, position)
DOUBLE_QUOTE -> QuotedString(text, position)
BACKQUOTE -> Backquote(text, position)
AT_SIGN -> AtSign(text, position)
COMMA -> Comma(text, position)
else -> when {
isNumeric(firstCharacter, text) -> Number(text, position)
isLegalIdentifierCharacter(firstCharacter) -> Identifier(text, position)
else -> throw BadCharacterException(text, position)
}
}
}
override fun createEofToken(position: FilePosition): Token {
return Eof("EOF", position)
}
private fun isNumeric(firstCharacter: Char, text: String): Boolean {
return isDigit(firstCharacter) || isPrefixedNumeric(firstCharacter, text)
}
private fun isPrefixedNumeric(firstCharacter: Char, text: String): Boolean {
return isNumberPrefix(firstCharacter) && isNextCharacterDigit(text)
}
private fun isNextCharacterDigit(text: String): Boolean {
return text.length > 1 && isDigit(text[1])
}
}