Finish all scan.Scanner stuff

pull/53/head
rwxrob 2 years ago
parent 2fa80f99a4
commit b649d38c13
No known key found for this signature in database
GPG Key ID: 2B9111F33082AE77

@ -37,8 +37,9 @@ var ExtendExpect func(s *Scanner, scannable ...any) (*Cur, error)
// buffer and cursor are directly exposed to facilitate
// higher-performance, direct access when needed.
type Scanner struct {
Buf []byte
Cur *Cur
Buf []byte
Cur *Cur
Snapped *Cur
}
// New returns a newly initialized non-linear, rune-centric, buffered
@ -149,6 +150,12 @@ func (p *Scanner) Mark() *Cur {
return &cp
}
// Snap sets an extra internal cursor to the current cursor. See Mark.
func (p *Scanner) Snap() { p.Snapped = p.Mark() }
// Back jumps the current cursor to the last Snap (Snapped).
func (p *Scanner) Back() { p.Jump(p.Snapped) }
// Jump replaces the internal cursor with a copy of the one passed
// effectively repositioning the scanner's current position in the
// buffered data. Beware, however, that the new cursor must originate
@ -158,8 +165,8 @@ func (p *Scanner) Jump(c *Cur) { nc := *c; p.Cur = &nc }
// Peek returns a string containing all the runes from the current
// scanner cursor position forward to the number of runes passed.
// If end of data is countered will everything up until that point.
// Also so Look and LookSlice.
// If end of data is encountered it will return everything up until that
// point. Also see Look and LookSlice.
func (p *Scanner) Peek(n uint) string {
buf := ""
pos := p.Cur.Byte
@ -283,7 +290,7 @@ func (p *Scanner) Expect(scannables ...any) (*Cur, error) {
m, err = p.Expect(is.MMx{0, 1, i})
if err != nil {
p.Jump(beg)
return nil, err
return nil, p.ErrorExpected(v)
}
}
end = m
@ -309,7 +316,7 @@ func (p *Scanner) Expect(scannables ...any) (*Cur, error) {
}
if !(v.Min <= c && c <= v.Max) {
p.Jump(last)
return nil, err
return nil, p.ErrorExpected(v)
}
end = last
@ -328,7 +335,7 @@ func (p *Scanner) Expect(scannables ...any) (*Cur, error) {
}
if c < v.Min {
p.Jump(beg)
return nil, err
return nil, p.ErrorExpected(v)
}
end = last
@ -336,7 +343,7 @@ func (p *Scanner) Expect(scannables ...any) (*Cur, error) {
m, err := p.Expect(is.MMx{v.X, v.X, v.This})
if err != nil {
p.Jump(beg)
return nil, err
return nil, p.ErrorExpected(v)
}
end = m
@ -377,7 +384,28 @@ func (p *Scanner) ErrorExpected(this any, args ...any) error {
case rune: // otherwise will use uint32
msg = fmt.Sprintf(`expected rune %q`, v)
case is.Not:
msg = fmt.Sprintf(`not expecting %q`, args[0])
msg = fmt.Sprintf(`unexpected %q`, args[0])
case is.In:
str := `expected one of %q`
msg = fmt.Sprintf(str, v)
case is.Seq:
str := `expected %q in sequence %q`
msg = fmt.Sprintf(str, args[0], v)
case is.Opt:
str := `expected an optional %v`
msg = fmt.Sprintf(str, v)
case is.Min:
str := `expected min %v of %q`
msg = fmt.Sprintf(str, v.Min, v.This)
case is.MMx:
str := `expected min %v, max %v of %q`
msg = fmt.Sprintf(str, v.Min, v.Max, v.This)
case is.X:
str := `expected exactly %v of %q`
msg = fmt.Sprintf(str, v.X, v.This)
case is.Rng:
str := `expected range [%v-%v]`
msg = fmt.Sprintf(str, string(v.First), string(v.Last))
default:
msg = fmt.Sprintf(`expected %T %q`, v, v)
}

@ -214,18 +214,105 @@ func ExampleExpect_not() {
// U+0073 's' 1,1-1 (1-1)
// <nil>
// <nil>
// not expecting "some" at U+0073 's' 1,1-1 (1-1)
// unexpected "some" at U+0073 's' 1,1-1 (1-1)
}
func ExampleExpect_in() {
s, _ := scan.New("some thing")
s.Scan()
c1, _ := s.Expect(is.In{'O', 'o', "ome"})
c1.Print()
c, _ := s.Expect(is.In{'O', 'o', "ome"})
c.Print()
s.Print()
_, err := s.Expect(is.In{'x', 'y', "zee"})
fmt.Println(err)
// Output:
// U+006F 'o' 1,2-2 (2-2)
// U+006D 'm' 1,3-3 (3-3)
// expected one of ['x' 'y' "zee"] at U+006D 'm' 1,3-3 (3-3)
}
func ExampleExpect_seq() {
s, _ := scan.New("some thing")
s.Snap()
s.Expect(is.Seq{"some", ' ', "thing"})
s.Print()
s.Back()
s.Print()
_, err := s.Expect(is.Seq{"some", "thing"})
fmt.Println(err)
// Output:
// <EOD>
// U+0073 's' 1,1-1 (1-1)
// expected rune 't' at U+0020 ' ' 1,5-5 (5-5)
}
func ExampleExpect_opt() {
s, _ := scan.New("some thing")
c, _ := s.Expect(is.Opt{"thing", "some"})
c.Print()
s.Print()
c, _ = s.Expect(is.Opt{"foo"})
s.Print() // no change
// Output:
// U+0065 'e' 1,4-4 (4-4)
// U+0020 ' ' 1,5-5 (5-5)
// U+0020 ' ' 1,5-5 (5-5)
}
func ExampleExpect_min() {
s, _ := scan.New("sommme thing")
start := s.Mark()
s.ScanN(2)
c, _ := s.Expect(is.Min{2, 'm'}) // goggles up all three
c.Print()
s.Print()
s.Jump(start)
_, e := s.Expect(is.Min{2, 's'}) // nope, only one found
fmt.Println(e)
s.Print()
// Output:
// U+006D 'm' 1,5-5 (5-5)
// U+0065 'e' 1,6-6 (6-6)
// expected min 2 of 's' at U+006F 'o' 1,2-2 (2-2)
// U+006F 'o' 1,2-2 (2-2)
}
func ExampleExpect_min_Max() {
s, _ := scan.New("sommme thing")
s.Snap()
s.ScanN(2)
s.Print()
s.Expect(is.MMx{1, 3, 'm'}) // goggles up all three
s.Print()
s.Back()
s.Expect(is.MMx{1, 3, 's'}) // yep, at least one
s.Print()
_, err := s.Expect(is.MMx{1, 3, 'X'}) // nope
fmt.Println(err)
// Output:
// U+006D 'm' 1,3-3 (3-3)
// U+0065 'e' 1,6-6 (6-6)
// U+006F 'o' 1,2-2 (2-2)
// expected min 1, max 3 of 'X' at U+006F 'o' 1,2-2 (2-2)
}
func ExampleExpect_count() {
s, _ := scan.New("sommme thing")
s.Snap()
s.ScanN(2)
s.Print()
s.Expect(is.X{3, 'm'}) // goggles up all three
s.Print()
s.Back()
s.Expect(is.X{1, 's'}) // yes, but silly since 's' is easier
s.Print()
_, err := s.Expect(is.X{3, 'X'}) // nope
fmt.Println(err)
// Output:
// U+006D 'm' 1,3-3 (3-3)
// U+0065 'e' 1,6-6 (6-6)
// U+006F 'o' 1,2-2 (2-2)
// expected exactly 3 of 'X' at U+006F 'o' 1,2-2 (2-2)
}
func ExampleExpect_in_Range() {
@ -239,17 +326,21 @@ func ExampleExpect_in_Range() {
// U+006D 'm' 1,3-3 (3-3)
}
func ExampleExpect_seq() {
func ExampleExtendExpect() {
// TODO
}
func ExampleSnap() {
s, _ := scan.New("some thing")
c1, e1 := s.Expect(is.Seq{"some", "thing"})
c1.Print()
fmt.Println(e1)
c2, e2 := s.Expect(is.Not{is.Seq{"some", "thing"}})
c2.Print()
fmt.Println(e2)
s.ScanN(3)
s.Snap()
s.Print()
s.ScanN(4)
s.Print()
s.Back()
s.Print()
// Output:
// U+0073 's' 1,1-1 (1-1)
// <nil>
// <nil>
// not expecting "some" at U+0073 's' 1,1-1 (1-1)
// U+0065 'e' 1,4-4 (4-4)
// U+0069 'i' 1,8-8 (8-8)
// U+0065 'e' 1,4-4 (4-4)
}

Loading…
Cancel
Save