aboutsummaryrefslogtreecommitdiff
path: root/pkg/libs
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-05-09 00:01:02 +0200
committerMel <einebeere@gmail.com>2022-05-09 00:01:02 +0200
commitb09a14147d397904722ee7c25e4defc56135b96f (patch)
tree694dc725528310f3a65d04785b8eea33908ce69f /pkg/libs
parentb5a9660b6ac42bce27c746e76013c3ce5992743a (diff)
downloadjinx-b09a14147d397904722ee7c25e4defc56135b96f.tar.zst
jinx-b09a14147d397904722ee7c25e4defc56135b96f.zip
Extract source walk part of scanner
Diffstat (limited to 'pkg/libs')
-rw-r--r--pkg/libs/source/errors.go10
-rw-r--r--pkg/libs/source/loc.go10
-rw-r--r--pkg/libs/source/walker.go80
3 files changed, 100 insertions, 0 deletions
diff --git a/pkg/libs/source/errors.go b/pkg/libs/source/errors.go
new file mode 100644
index 0000000..cfcd9e3
--- /dev/null
+++ b/pkg/libs/source/errors.go
@@ -0,0 +1,10 @@
+package source
+
+type ErrUnexpectedChar struct {
+ Expected rune
+ Actual rune
+}
+
+func (e ErrUnexpectedChar) Error() string {
+ return "unexpected character: expected " + string(e.Expected) + ", actual " + string(e.Actual)
+}
diff --git a/pkg/libs/source/loc.go b/pkg/libs/source/loc.go
new file mode 100644
index 0000000..3089d3b
--- /dev/null
+++ b/pkg/libs/source/loc.go
@@ -0,0 +1,10 @@
+package source
+
+type Loc struct {
+ Row int
+ Col int
+}
+
+func NewLoc(row, col int) Loc {
+ return Loc{row, col}
+}
diff --git a/pkg/libs/source/walker.go b/pkg/libs/source/walker.go
new file mode 100644
index 0000000..aeac82a
--- /dev/null
+++ b/pkg/libs/source/walker.go
@@ -0,0 +1,80 @@
+package source
+
+import (
+ "bufio"
+ "errors"
+ "io"
+)
+
+type Walker struct {
+ source *bufio.Reader
+
+ row int
+ col int
+}
+
+func NewWalker(source io.Reader) *Walker {
+ return &Walker{
+ source: bufio.NewReader(source),
+ row: 0,
+ col: 0,
+ }
+}
+
+func (w *Walker) Loc() Loc {
+ return Loc{
+ Row: w.row,
+ Col: w.col,
+ }
+}
+
+func (w *Walker) Next() (rune, bool, error) {
+ r, _, err := w.source.ReadRune()
+ if err != nil {
+ if errors.Is(err, io.EOF) {
+ return 0, true, nil
+ }
+
+ return 0, false, err
+ }
+
+ if r == '\n' {
+ w.row++
+ w.col = 0
+ } else {
+ w.col++
+ }
+
+ return r, false, nil
+}
+
+func (w *Walker) Consume(want rune) (bool, error) {
+ c, _, err := w.Next()
+ if err != nil {
+ return false, err
+ }
+
+ if c != want {
+ return true, ErrUnexpectedChar{
+ Expected: want,
+ Actual: c,
+ }
+ }
+
+ return true, nil
+}
+
+func (w *Walker) Peek() (rune, bool, error) {
+ r, _, err := w.source.ReadRune()
+ defer w.source.UnreadRune()
+
+ if err != nil {
+ if errors.Is(err, io.EOF) {
+ return 0, true, nil
+ }
+
+ return 0, false, err
+ }
+
+ return r, false, nil
+}