@@ -66,19 +66,17 @@ class Lexer(
66
66
*/
67
67
private var currentLine: Option <String > = None
68
68
69
- private var tokenIndex = 0
70
- private var tokenStream = emptyList<Token >()
71
-
72
69
private var insideMultilineComment = false
73
70
74
- private val trieMap = StringTrieMap <Kind >()
71
+ private val _hardKeywords = StringTrieMap <Kind >()
72
+
75
73
private enum class Kind {
76
74
KEYWORD , OPERATOR , SEPARATOR
77
75
}
78
76
79
77
init {
80
78
hardKeywords.forEach {
81
- trieMap [it] = Kind .KEYWORD
79
+ _hardKeywords [it] = Kind .KEYWORD
82
80
}
83
81
}
84
82
@@ -89,25 +87,25 @@ class Lexer(
89
87
* @since 0.1.0
90
88
*/
91
89
internal fun nextToken (): Token {
90
+ // This is when the currentLine has not been loaded yet
92
91
currentLine.onNone { fetchLine() }
93
92
94
- currentLine.fold(
95
- ifEmpty = { return Token .EOF },
96
- ifSome = {
97
- if (it.isBlank()) {
98
- position = position.nextLine()
99
- return nextToken()
100
- }
101
- }
102
- )
103
-
93
+ // Empty lines and ignored contents should be skipped
94
+ while (currentLine.isSome { it.isEmpty() }) {
95
+ position = position.nextLine()
96
+ }
104
97
fastForwardToContent()
105
98
106
- val winner = listOf (identifiers())
107
- .mapNotNull { it.getOrNull() }
108
- .getWinnerOrNullOrThrow() ? : nextToken()
109
- position = position.copy(col = winner.end.col + 1 )
110
- return winner
99
+ // If the file is fully read, then return EOF
100
+ currentLine.onNone { return Token .EOF }
101
+
102
+ val winner = listOf (identifiers()).firstNotNullOfOrNull { it.getOrNull() }
103
+
104
+ if (winner != null ) {
105
+ position = position.copy(col = winner.end.col + 1 )
106
+ return winner
107
+ }
108
+ throw LexicalException (" " )
111
109
}
112
110
113
111
/* *
@@ -119,6 +117,7 @@ class Lexer(
119
117
do {
120
118
val ignoredMatch = startsWith(ignorePattern)
121
119
position = position.copy(col = ignoredMatch.range.last + 1 )
120
+ // This would break because changing the position can also change currentLine.
122
121
} while (true )
123
122
}
124
123
}
@@ -152,41 +151,6 @@ private fun <A> Option<A>.getOrThrow(cause: () -> Exception): A {
152
151
return getOrNull() ? : throw cause()
153
152
}
154
153
155
- private fun List<Token>.getWinnerOrNullOrThrow (): Token ? {
156
- if (this .isEmpty())
157
- return null
158
-
159
- var maxSize = 0
160
- val winners = mutableSetOf<Token >()
161
- for (token in this ) {
162
- if (token.size > maxSize) {
163
- winners.clear()
164
- winners.add(token)
165
- maxSize = token.size
166
- } else if (token.size == maxSize) {
167
- winners.add(token)
168
- }
169
- }
170
-
171
- when (winners.size) {
172
- 1 -> return winners.first()
173
- 2 -> {
174
- val keywordIdentifier = winners.separateEither {
175
- when (it) {
176
- is Token .Keyword -> it.left()
177
- is Token .Identifier -> it.right()
178
- else -> throw LexicalException (" Ambiguity error" )
179
- }
180
- }
181
- // first is the lefts containing keyword.
182
- // keywords triumph over identifiers.
183
- return keywordIdentifier.first[0 ]
184
- }
185
-
186
- else -> throw LexicalException (" Ambiguity error" )
187
- }
188
- }
189
-
190
154
// private fun updateTokenStream() {
191
155
// fetchNextLine()
192
156
// tokenIndex = 0 // reset the counter
0 commit comments