comparison src/main/kotlin/name/blackcap/passman/Shplitter.kt @ 20:4391afcf6bd0

Fix more bugs, correct more bad tests.
author David Barts <n5jrn@me.com>
date Sun, 30 Jun 2024 22:28:52 -0700
parents 7d80cbcb67bb
children ea65ab890f66
comparison
equal deleted inserted replaced
19:7d80cbcb67bb 20:4391afcf6bd0
29 } 29 }
30 } 30 }
31 31
32 fun split(): Iterable<String> { 32 fun split(): Iterable<String> {
33 if (complete) { 33 if (complete) {
34 if (current.isNotEmpty()) { 34 if (state == ::nonspace) {
35 popState()
35 accum.add(current.toString()) 36 accum.add(current.toString())
36 current.clear() 37 current.clear()
37 }
38 if (state == ::nonspace) {
39 popState()
40 } 38 }
41 return accum 39 return accum
42 } else { 40 } else {
43 throw IllegalStateException("incomplete quoted expression") 41 throw IllegalStateException("incomplete quoted expression")
44 } 42 }
55 state = oldStates.removeLast() 53 state = oldStates.removeLast()
56 } 54 }
57 55
58 private fun lastState(): State = oldStates.last() 56 private fun lastState(): State = oldStates.last()
59 57
60 private fun endQuote(): Unit {
61 if (lastState() == ::space) {
62 accum.add(current.toString())
63 current.clear()
64 }
65 popState()
66 }
67
68 // States. A state is represented by a function that accepts the 58 // States. A state is represented by a function that accepts the
69 // character currently being processed, and returns whether it should 59 // character currently being processed, and returns whether it should
70 // immediately transition to the next state without reading a new 60 // immediately transition to the next state without reading a new
71 // character. 61 // character.
72 62
73 private fun space(ch: Char): Boolean = 63 private fun space(ch: Char): Boolean =
74 when (ch) { 64 when (ch) {
75 in WHITESPACE -> { false } 65 in WHITESPACE -> { false }
76 '\'' -> { pushState(::inSingle); false } 66 '\'' -> { pushState(::nonspace); pushState(::inSingle); false }
77 '"' -> { pushState(::inDouble); false } 67 '"' -> { pushState(::nonspace); pushState(::inDouble); false }
78 '\\' -> { pushState(::backslash); false } 68 '\\' -> { pushState(::nonspace); pushState(::backslash); false }
79 else -> { pushState(::nonspace); true } 69 else -> { pushState(::nonspace); true }
80 } 70 }
81 71
82 private fun nonspace(ch: Char): Boolean = 72 private fun nonspace(ch: Char): Boolean =
83 when (ch) { 73 when (ch) {
105 } 95 }
106 } 96 }
107 97
108 private fun inSingle(ch: Char): Boolean = 98 private fun inSingle(ch: Char): Boolean =
109 when (ch) { 99 when (ch) {
110 '\'' -> { endQuote(); false } 100 '\'' -> { popState(); false }
111 else -> { current.append(ch); false } 101 else -> { current.append(ch); false }
112 } 102 }
113 103
114 private fun inDouble(ch: Char): Boolean = 104 private fun inDouble(ch: Char): Boolean =
115 when (ch) { 105 when (ch) {
116 '\\' -> { pushState(::backslash); false } 106 '\\' -> { pushState(::backslash); false }
117 '"' -> { endQuote(); false } 107 '"' -> { popState(); false }
118 else -> { current.append(ch); false } 108 else -> { current.append(ch); false }
119 } 109 }
120 110
121 private fun backslash(ch: Char): Boolean { 111 private fun backslash(ch: Char): Boolean {
122 val last = lastState() 112 val last = lastState()