mirror of
https://github.com/rwxrob/bonzai
synced 2024-11-14 18:12:59 +00:00
Add is.To and is.Inc
This commit is contained in:
parent
b86c1e15fb
commit
36c83cab0b
@ -75,8 +75,30 @@ type Any []any
|
||||
// found the scan is advanced (unlike Lk, which does not advance).
|
||||
type Opt []any
|
||||
|
||||
// To is a set of advancing expressions that mark an exclusive boundary
|
||||
// at which the scan should stop. The matching expression itself will
|
||||
// not be advanced.
|
||||
//
|
||||
// In order to work with escaped boundaries use a negative
|
||||
// look-ahead sequence combined with the boundary:
|
||||
//
|
||||
// is.To{s.Seq{is.Not{`\\`,`"`}}}
|
||||
//
|
||||
type To []any
|
||||
|
||||
// Inc is a set of advancing expressions that mark an inclusive boundary
|
||||
// after which the scan should stop. The matching expression will be
|
||||
// included in the advance (unlike is.To).
|
||||
type Inc []any
|
||||
|
||||
// --------------------------- parameterized --------------------------
|
||||
|
||||
// EscTo is identical to is.To{s.Seq{is.Not{E,To}}}.
|
||||
type EscTo struct {
|
||||
E any
|
||||
To any
|
||||
}
|
||||
|
||||
// MMx is a parameterized advancing expression that matches an inclusive
|
||||
// minimum and maximum count of the given expression (This). Use within
|
||||
// is.Lk to disable advancement.
|
||||
@ -113,12 +135,3 @@ type Rng struct {
|
||||
First rune
|
||||
Last rune
|
||||
}
|
||||
|
||||
// Esc is a parameterized advancing expression that matches everything
|
||||
// in the given expression (This) except for an expression (Not) that
|
||||
// requires being immediately preceded by the escape expression (Esc).
|
||||
type Esc struct {
|
||||
Not any
|
||||
Esc any
|
||||
This any
|
||||
}
|
||||
|
40
scan/scan.go
40
scan/scan.go
@ -279,6 +279,40 @@ func (s *R) Expect(scannables ...any) (*Cur, error) {
|
||||
end = s.Mark()
|
||||
s.Scan()
|
||||
|
||||
case is.Inc: // -----------------------------------------------------
|
||||
var m *Cur
|
||||
for m == nil && s.Cur.Rune != tk.EOD {
|
||||
for _, i := range v {
|
||||
m, _ = s.check(i)
|
||||
}
|
||||
s.Scan()
|
||||
}
|
||||
if m == nil {
|
||||
err := s.ErrorExpected(v)
|
||||
s.Jump(beg)
|
||||
return nil, err
|
||||
}
|
||||
end = m
|
||||
|
||||
case is.To: // -----------------------------------------------------
|
||||
var m *Cur
|
||||
OUT:
|
||||
for s.Cur.Rune != tk.EOD {
|
||||
for _, i := range v {
|
||||
m, _ = s.check(i)
|
||||
if m != nil {
|
||||
break OUT
|
||||
}
|
||||
}
|
||||
s.Scan()
|
||||
}
|
||||
if m == nil {
|
||||
err := s.ErrorExpected(v)
|
||||
s.Jump(beg)
|
||||
return nil, err
|
||||
}
|
||||
end = m
|
||||
|
||||
case is.Lk: // ----------------------------------------------------
|
||||
var m *Cur
|
||||
for _, i := range v {
|
||||
@ -407,9 +441,6 @@ func (s *R) Expect(scannables ...any) (*Cur, error) {
|
||||
end = s.Mark()
|
||||
s.Scan()
|
||||
|
||||
case is.Esc: // ----------------------------------------------------
|
||||
// TODO
|
||||
|
||||
case Hook: // ------------------------------------------------------
|
||||
if !v(s) {
|
||||
return nil, fmt.Errorf(
|
||||
@ -480,6 +511,9 @@ func (s *R) ErrorExpected(this any, args ...any) error {
|
||||
case is.Rng:
|
||||
str := `expected range [%v-%v]`
|
||||
msg = fmt.Sprintf(str, string(v.First), string(v.Last))
|
||||
case is.To, is.Inc:
|
||||
str := `%q not found`
|
||||
msg = fmt.Sprintf(str, v)
|
||||
default:
|
||||
msg = fmt.Sprintf(`expected %T %q`, v, v)
|
||||
}
|
||||
|
@ -383,7 +383,24 @@ func ExampleExpect_hook() {
|
||||
|
||||
}
|
||||
|
||||
// TODO Esc
|
||||
func ExampleExpect_inc() {
|
||||
s, _ := scan.New("some thing")
|
||||
s.Expect(is.Inc{`i`})
|
||||
s.Print()
|
||||
// Output:
|
||||
// U+006E 'n' 1,9-9 (9-9)
|
||||
}
|
||||
|
||||
func ExampleExpect_to() {
|
||||
s, _ := scan.New("some thing")
|
||||
s.Expect(is.To{`i`})
|
||||
s.Print()
|
||||
_, err := s.Expect(is.To{`z`})
|
||||
fmt.Println(err)
|
||||
// Output:
|
||||
// U+0069 'i' 1,8-8 (8-8)
|
||||
// ["z"] not found at <EOD>
|
||||
}
|
||||
|
||||
func ExampleSnap() {
|
||||
s, _ := scan.New("some thing")
|
||||
|
Loading…
Reference in New Issue
Block a user