class Lexical { fun analyze(source: String): MutableList> { var buffer = "" val tokens = mutableListOf>() for (i in source.indices) { buffer += source[i] val tokenType = getTokenType(buffer, if (source.length > i + 1) source[i + 1] else ' ') if (tokenType != TokenType.Skip) { tokens += buffer to tokenType buffer = "" } } return tokens } /** * Matches the tokens to a [TokenType] */ private fun getTokenType(token: String, next: Char): TokenType { return when { token + next in keyword -> TokenType.Skip token in keyword -> TokenType.Keyword token + next in comparison -> TokenType.Skip token in assignment -> TokenType.Assignment token + next in assignment -> TokenType.Skip token in arithmetic -> TokenType.Arithmetic token + next in comparison -> TokenType.Skip token in comparison -> TokenType.Comparison token + next in comparison -> TokenType.Skip token in logical -> TokenType.Logical (token + next).matches(Regex("[a-zA-Z]*")) -> TokenType.Skip token.matches(Regex("[a-zA-Z]*")) -> TokenType.Identifier (token + next).matches(Regex("[0-9]*")) -> TokenType.Skip token.matches(Regex("[0-9]*")) -> TokenType.Constant token in punctuation -> TokenType.Punctuation token == " " -> TokenType.Empty else -> TokenType.Skip } } private val keyword = listOf("print") // TODO: DataType matching private val assignment = listOf("=", "+=", "-=", "*=", "/*") private val arithmetic = listOf("+", "-", "*", "/", "%") private val comparison = listOf("==", "!=", "<", "<=", ">", ">=") private val logical = listOf("&&", "||", "!") private val punctuation = listOf(",", ":", ".") } enum class TokenType { Keyword, Assignment, Arithmetic, Comparison, Logical, Punctuation, Identifier, Constant, Empty, Skip }