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]) } }