aboutsummaryrefslogtreecommitdiff
path: root/src/runMain/kotlin/Lexical.kt
blob: 85290364e65386c2f89ead0707125271c27c09a2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import exceptions.UnknownType

class Lexical {
    fun analyze(source: String): MutableList<Pair<String, TokenType>> {
        var buffer = ""
        var statementEnd = false
        val tokens = mutableListOf<Pair<String, TokenType>>()
        for (i in source.indices) {
            buffer += source[i]
            statementEnd = 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.contains(" ") && token.length > 1 -> throw UnknownType(token)
            token == " " -> TokenType.Empty

            token in punctuation -> TokenType.Punctuation

            token in brackets -> TokenType.Bracket

            token in classifier -> TokenType.Classifier

            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(",", ":", ".", ";")
    private val brackets = listOf("(", ")", "[", "]", "{", "}") // TODO: Use brackets for functions
    private val classifier = listOf("\"", "'")
}