Skip to content

Commit 084bb9e

Browse files
refactor: cleanup for identifiers
1 parent a4e50fb commit 084bb9e

File tree

4 files changed

+21
-57
lines changed

4 files changed

+21
-57
lines changed

core/src/main/kotlin/io/github/cybercodernaj/parkour/lexer/Lexer.kt

Lines changed: 19 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,17 @@ class Lexer(
6666
*/
6767
private var currentLine: Option<String> = None
6868

69-
private var tokenIndex = 0
70-
private var tokenStream = emptyList<Token>()
71-
7269
private var insideMultilineComment = false
7370

74-
private val trieMap = StringTrieMap<Kind>()
71+
private val _hardKeywords = StringTrieMap<Kind>()
72+
7573
private enum class Kind {
7674
KEYWORD, OPERATOR, SEPARATOR
7775
}
7876

7977
init {
8078
hardKeywords.forEach {
81-
trieMap[it] = Kind.KEYWORD
79+
_hardKeywords[it] = Kind.KEYWORD
8280
}
8381
}
8482

@@ -89,25 +87,25 @@ class Lexer(
8987
* @since 0.1.0
9088
*/
9189
internal fun nextToken(): Token {
90+
// This is when the currentLine has not been loaded yet
9291
currentLine.onNone { fetchLine() }
9392

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+
}
10497
fastForwardToContent()
10598

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("")
111109
}
112110

113111
/**
@@ -119,6 +117,7 @@ class Lexer(
119117
do {
120118
val ignoredMatch = startsWith(ignorePattern)
121119
position = position.copy(col = ignoredMatch.range.last + 1)
120+
// This would break because changing the position can also change currentLine.
122121
} while (true)
123122
}
124123
}
@@ -152,41 +151,6 @@ private fun <A> Option<A>.getOrThrow(cause: () -> Exception): A {
152151
return getOrNull() ?: throw cause()
153152
}
154153

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-
190154
// private fun updateTokenStream() {
191155
// fetchNextLine()
192156
// tokenIndex = 0 // reset the counter

core/src/main/kotlin/io/github/cybercodernaj/parkour/lexer/StringTrieMap.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@ private data class TrieNode<T, U>(
3232
var terminal: Boolean
3333
) {
3434
constructor(): this(mutableMapOf(), null, false)
35-
}
35+
}

core/src/main/kotlin/io/github/cybercodernaj/parkour/lexer/Token.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ internal sealed class Token(val value: Any, val start: Position, val end: Positi
2929
if (this === other) return true
3030
if (other !is Token) return false
3131

32+
if (this::class.simpleName != other::class.simpleName) return false
3233
if (value != other.value) return false
3334
if (start != other.start) return false
3435
if (end != other.end) return false

core/src/test/kotlin/io/github/cybercodernaj/parkour/lexer/LexerIdentifierTest.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ class LexerIdentifierTest {
101101
}
102102

103103
@Test
104-
@Ignore
105104
fun `throws error on unidentifiable token`() {
106105
lexer.source = StringSource("0na@me")
107106
try {

0 commit comments

Comments
 (0)