summaryrefslogtreecommitdiff
path: root/internal/tokener/tokener.go
diff options
context:
space:
mode:
authorEyal Posener <[email protected]>2019-11-14 06:51:44 +0200
committerEyal Posener <[email protected]>2019-11-18 01:05:47 +0200
commit8724aaf18312e54750540a9578e00d61b1c545d8 (patch)
treed3e736b4fb279975bbcc017ae1bad53e454c5773 /internal/tokener/tokener.go
parent05b68ffc813dd10c420993cb1cf927b346c057b8 (diff)
V2
Diffstat (limited to 'internal/tokener/tokener.go')
-rw-r--r--internal/tokener/tokener.go67
1 files changed, 67 insertions, 0 deletions
diff --git a/internal/tokener/tokener.go b/internal/tokener/tokener.go
new file mode 100644
index 0000000..0886341
--- /dev/null
+++ b/internal/tokener/tokener.go
@@ -0,0 +1,67 @@
+package tokener
+
+type Tokener struct {
+ quotes []byte
+ escaped bool
+ fixed string
+ space bool
+}
+
+// Visit visit a byte and update the state of the quotes.
+// It returns true if the byte was quotes or escape character.
+func (t *Tokener) Visit(b byte) {
+ // Check space.
+ if b == ' ' {
+ if !t.escaped && !t.Quoted() {
+ t.space = true
+ }
+ } else {
+ t.space = false
+ }
+
+ // Check escaping
+ if b == '\\' {
+ t.escaped = !t.escaped
+ } else {
+ defer func() { t.escaped = false }()
+ }
+
+ // Check quotes.
+ if !t.escaped && (b == '"' || b == '\'') {
+ if t.Quoted() && t.quotes[len(t.quotes)-1] == b {
+ t.quotes = t.quotes[:len(t.quotes)-1]
+ } else {
+ t.quotes = append(t.quotes, b)
+ }
+ }
+
+ // If not quoted, insert escape before inserting space.
+ if t.LastSpace() {
+ t.fixed += "\\"
+ }
+ t.fixed += string(b)
+}
+
+func (t *Tokener) Escaped() bool {
+ return t.escaped
+}
+
+func (t *Tokener) Quoted() bool {
+ return len(t.quotes) > 0
+}
+
+func (t *Tokener) Fixed() string {
+ return t.fixed
+}
+
+func (t *Tokener) Closed() string {
+ fixed := t.fixed
+ for i := len(t.quotes) - 1; i >= 0; i-- {
+ fixed += string(t.quotes[i])
+ }
+ return fixed
+}
+
+func (t *Tokener) LastSpace() bool {
+ return t.space
+}