blob: d0a4a159ff70f8ee8976422ba0f09ba8677ed559 (
plain)
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
package moe.nea.lisp
import java.util.*
class StringRacer(val filename: String, val backing: String) {
var idx = 0
val stack = Stack<Int>()
fun pushState() {
stack.push(idx)
}
fun popState() {
idx = stack.pop()
}
fun span(start: Int) = LispPosition(start, idx, filename, backing)
fun discardState() {
stack.pop()
}
fun peek(count: Int): String {
return backing.substring(minOf(idx, backing.length), minOf(idx + count, backing.length))
}
fun finished(): Boolean {
return peek(1).isEmpty()
}
fun peekReq(count: Int): String? {
val p = peek(count)
if (p.length != count)
return null
return p
}
fun consumeCountReq(count: Int): String? {
val p = peekReq(count)
if (p != null)
idx += count
return p
}
fun tryConsume(string: String): Boolean {
val p = peek(string.length)
if (p != string)
return false
idx += p.length
return true
}
fun consumeWhile(shouldConsumeThisString: (String) -> Boolean): String {
var lastString: String = ""
while (true) {
val nextPart = peek(1)
if (nextPart.isEmpty()) break
val nextString = lastString + nextPart
if (!shouldConsumeThisString(nextString)) {
break
}
idx++
lastString = nextString
}
return lastString
}
fun expect(search: String, errorMessage: String) {
if (!tryConsume(search))
error(errorMessage)
}
fun error(errorMessage: String): Nothing {
throw LispParsingError(backing, idx, errorMessage)
}
fun skipWhitespace() {
consumeWhile { Character.isWhitespace(it.last()) }
}
}
|