summaryrefslogtreecommitdiff
path: root/pointer.go
diff options
context:
space:
mode:
authorAdam Scarr <adam@vektah.net>2017-08-06 14:31:35 +1000
committerAdam Scarr <adam@vektah.net>2017-08-06 14:31:35 +1000
commit68cde88125e1f016c5706ca8d0b3db6ba06624a2 (patch)
treecdd2de679892179f537b22ab05bfe3820dc7b4bf /pointer.go
Initial commit
Diffstat (limited to 'pointer.go')
-rw-r--r--pointer.go81
1 files changed, 81 insertions, 0 deletions
diff --git a/pointer.go b/pointer.go
new file mode 100644
index 0000000..92b2bcb
--- /dev/null
+++ b/pointer.go
@@ -0,0 +1,81 @@
+package parsec
+
+import (
+ "strings"
+ "unicode/utf8"
+)
+
+const (
+ EOF rune = -1
+)
+
+func Input(s string) Pointer {
+ return Pointer{s, 0}
+}
+
+type Pointer struct {
+ input string
+ pos int
+}
+
+func (p Pointer) Advance(i int) Pointer {
+ return Pointer{p.input, p.pos + i}
+}
+
+func (p Pointer) Get() string {
+ return p.input[p.pos:]
+}
+
+func (p Pointer) Remaining() int {
+ remaining := len(p.input) - p.pos
+ if remaining < 0 {
+ return 0
+ }
+ return remaining
+}
+
+func (p Pointer) Next() (rune, Pointer) {
+ if int(p.pos) >= len(p.input) {
+ return EOF, p
+ }
+ r, w := utf8.DecodeRuneInString(p.input[p.pos:])
+ return r, p.Advance(w)
+}
+
+func (p Pointer) HasPrefix(s string) bool {
+ return strings.HasPrefix(p.input[p.pos:], s)
+}
+
+func (p Pointer) Accept(valid string) (string, Pointer) {
+ c, newP := p.Next()
+ if strings.ContainsRune(valid, c) {
+ return string(c), newP
+ }
+ return "", p
+}
+
+func (p Pointer) AcceptRun(valid string) (string, Pointer) {
+ matched := 0
+ for p.pos+matched < len(p.input) {
+ r, w := utf8.DecodeRuneInString(p.input[p.pos+matched:])
+ if !strings.ContainsRune(valid, r) {
+ break
+ }
+ matched += w
+ }
+
+ return p.input[p.pos : p.pos+matched], p.Advance(matched)
+}
+
+func (p Pointer) AcceptUntil(invalid string) (string, Pointer) {
+ matched := 0
+ for p.pos+matched < len(p.input) {
+ r, w := utf8.DecodeRuneInString(p.input[p.pos+matched:])
+ if strings.ContainsRune(invalid, r) {
+ break
+ }
+ matched += w
+ }
+
+ return p.input[p.pos : p.pos+matched], p.Advance(matched)
+}