mirror of
https://github.com/rwxrob/bonzai
synced 2024-11-04 18:00:18 +00:00
Add scan.R.Parse*, z.P->z.Y, z.P for parse
This commit is contained in:
parent
c4f7274e01
commit
78a8a6fb65
@ -11,8 +11,12 @@ import (
|
||||
"github.com/rwxrob/bonzai/comp"
|
||||
"github.com/rwxrob/bonzai/filt"
|
||||
"github.com/rwxrob/bonzai/maps"
|
||||
"github.com/rwxrob/bonzai/term"
|
||||
)
|
||||
|
||||
var OBracketed = term.Under
|
||||
var CBracketed = term.Reset
|
||||
|
||||
// Cmd provides help documentation for the caller allowing the specific
|
||||
// section of help wanted to be passed as a tab-completable parameter.
|
||||
var Cmd = &bonzai.Cmd{
|
||||
@ -58,3 +62,27 @@ func helpCompleter(x comp.Command, args ...string) []string {
|
||||
|
||||
return filt.HasPrefix(list, args[0])
|
||||
}
|
||||
|
||||
// Render renders the incoming Help markup string for a curses terminal
|
||||
// detecting if the terminal is interactive and if not rendering as
|
||||
// plain text instead.
|
||||
func Render(in string) string {
|
||||
out := ""
|
||||
for i := 0; i < len([]rune(in)); i++ {
|
||||
cur := in[i]
|
||||
switch cur {
|
||||
|
||||
// <bracketed>
|
||||
case '<':
|
||||
out += OBracketed
|
||||
for {
|
||||
|
||||
}
|
||||
out += CBracketed
|
||||
}
|
||||
}
|
||||
return string(out)
|
||||
}
|
||||
|
||||
func parseBracketed() {
|
||||
}
|
||||
|
@ -60,17 +60,18 @@ package z
|
||||
|
||||
// ------------------------------- core -------------------------------
|
||||
|
||||
// Nd ("node") is a named sequence of expressions that will be captured
|
||||
// as a new Node and added to the scan.R.Nodes field effectively turning
|
||||
// the scan.R into a parser as well. The first string must always be the
|
||||
// name which can be any valid Go string. If any expression fails to
|
||||
// match the scan fails. Otherwise, a new tree.Node is added under the
|
||||
// current node and the scan proceeds. Nodes must either contain other
|
||||
// nodes or no nodes at all. If the first item in the sequence after the
|
||||
// name is not also a node (z.Nd) then the node is marked as "edge" (or
|
||||
// "leaf") and any nodes detected further in the sequence will cause the
|
||||
// scan to fail with a syntax error.
|
||||
type Nd []any
|
||||
// P ("parse") is a named sequence of expressions that will be parsed
|
||||
// and captured as a new Node and added to the scan.R.Nodes field
|
||||
// effectively turning the scan.R into a parser as well. The first
|
||||
// string must always be the name which can be any valid Go string. If
|
||||
// any expression fails to match the scan fails. Otherwise, a new
|
||||
// scan.Node is added under the current node and the scan proceeds.
|
||||
// Nodes must either contain other nodes or no nodes at all. If the
|
||||
// first item in the sequence after the name is not also a node (z.P)
|
||||
// then the node is marked as "edge" (or "leaf") and any nodes detected
|
||||
// further in the sequence will cause the scan to fail with a syntax
|
||||
// error.
|
||||
type P []any
|
||||
|
||||
// X ("expression") is a sequence of expressions. If any are not the
|
||||
// scan fails. (Equal to (?foo) in regular expressions.)
|
||||
@ -78,13 +79,12 @@ type X []any
|
||||
|
||||
// ------------------------------- sets -------------------------------
|
||||
|
||||
// P ("positive") is a set of positive lookahead expressions. If any are
|
||||
// Y ("yes") is a set of positive lookahead expressions. If any are
|
||||
// seen at the current cursor position the scan will proceed without
|
||||
// consuming them (unlike z.O and z.I). If none are found the scan
|
||||
// fails. This is useful when everything from one expression is wanted
|
||||
// except for a few positive exceptions. (Equal to ampersand (&) in
|
||||
// fails. (Equal to ampersand (&) in
|
||||
// PEGN.)
|
||||
type P []any
|
||||
type Y []any
|
||||
|
||||
// N ("not") is a set of negative lookahead expressions. If any are seen
|
||||
// at the current cursor position the scan will fail and the scan is
|
||||
|
23
scan/scan.go
23
scan/scan.go
@ -63,6 +63,10 @@ type R struct {
|
||||
// added as more state-modifying single-token expressions are
|
||||
// considered (like tk.IS and tk.NOT now).
|
||||
State int
|
||||
|
||||
// Nodes contains a collection of Nodes parsed when a z.P expression
|
||||
// is scanned by Expect.
|
||||
Nodes []*Node
|
||||
}
|
||||
|
||||
const (
|
||||
@ -224,6 +228,21 @@ func (s *R) Peek(n uint) string {
|
||||
return buf
|
||||
}
|
||||
|
||||
// Parse creates a new Node reference from the string returned by Look.
|
||||
func (s *R) Parse(to *Cur) *Node {
|
||||
n := new(Node)
|
||||
n.V = s.Look(to)
|
||||
return n
|
||||
}
|
||||
|
||||
// ParseSlice creates a new Node reference from the string returned by
|
||||
// LookSlice.
|
||||
func (s *R) ParseSlice(b *Cur, e *Cur) *Node {
|
||||
n := new(Node)
|
||||
n.V = s.LookSlice(b, e)
|
||||
return n
|
||||
}
|
||||
|
||||
// Look returns a string containing all the bytes from the current
|
||||
// scanner cursor position ahead or behind to the passed cursor
|
||||
// position. Neither the internal nor the passed cursor position is
|
||||
@ -371,7 +390,7 @@ func (s *R) Expect(expr any) (*Cur, error) {
|
||||
s.Jump(m)
|
||||
return nil, s.ErrorExpected(v)
|
||||
|
||||
case z.P: // ----------------------------------------------------
|
||||
case z.Y: // ----------------------------------------------------
|
||||
var m *Cur
|
||||
b := s.Mark()
|
||||
for _, i := range v {
|
||||
@ -547,7 +566,7 @@ func (s *R) ErrorExpected(this any, args ...any) error {
|
||||
switch v := this.(type) {
|
||||
case rune: // otherwise will use uint32
|
||||
msg = fmt.Sprintf(`expected rune %q`, v)
|
||||
case z.P:
|
||||
case z.Y:
|
||||
if len(v) > 1 {
|
||||
msg = fmt.Sprintf(`expected one of %q`, v)
|
||||
} else {
|
||||
|
@ -163,6 +163,29 @@ func ExampleNewLine() {
|
||||
// U+0073 's' 2,1-1 (1-1)
|
||||
}
|
||||
|
||||
func ExampleR_Parse() {
|
||||
s, _ := scan.New("some thing")
|
||||
s.Snap()
|
||||
s.ScanN(5)
|
||||
m := s.Mark()
|
||||
s.Back()
|
||||
n := s.Parse(m)
|
||||
n.Print()
|
||||
// Output:
|
||||
// {"V":"some t"}
|
||||
}
|
||||
|
||||
func ExampleR_ParseSlice() {
|
||||
s, _ := scan.New("some thing")
|
||||
b := s.Mark()
|
||||
s.ScanN(5)
|
||||
e := s.Mark()
|
||||
n := s.ParseSlice(b, e)
|
||||
n.Print()
|
||||
// Output:
|
||||
// {"V":"some t"}
|
||||
}
|
||||
|
||||
func ExampleErrorExpected() {
|
||||
s, _ := scan.New("some thing")
|
||||
fmt.Println(s.ErrorExpected("foo"))
|
||||
@ -226,7 +249,7 @@ func ExampleExpect_compound_Expr_Rune() {
|
||||
|
||||
func ExampleExpect_it_Success() {
|
||||
s, _ := scan.New("some thing")
|
||||
c, _ := s.Expect(z.P{"some"})
|
||||
c, _ := s.Expect(z.Y{"some"})
|
||||
c.Print() // even though true, not moved
|
||||
s.Print() // scanner also not moved
|
||||
// Output:
|
||||
@ -236,7 +259,7 @@ func ExampleExpect_it_Success() {
|
||||
|
||||
func ExampleExpect_it_Success_Middle() {
|
||||
s, _ := scan.New("some thing")
|
||||
c, _ := s.Expect(z.X{"some", z.P{' '}})
|
||||
c, _ := s.Expect(z.X{"some", z.Y{' '}})
|
||||
c.Print() // advanced up to (but not including) ' '
|
||||
s.Print() // scanner also not moved
|
||||
// Output:
|
||||
@ -246,7 +269,7 @@ func ExampleExpect_it_Success_Middle() {
|
||||
|
||||
func ExampleExpect_it_Fail() {
|
||||
s, _ := scan.New("some thing")
|
||||
_, err := s.Expect(z.X{"some", z.P{"thing"}})
|
||||
_, err := s.Expect(z.X{"some", z.Y{"thing"}})
|
||||
fmt.Println(err)
|
||||
s.Print() // but scanner did get "some" so advanced
|
||||
// Output:
|
||||
@ -256,7 +279,7 @@ func ExampleExpect_it_Fail() {
|
||||
|
||||
func ExampleExpect_it_Fail_X() {
|
||||
s, _ := scan.New("some thing")
|
||||
_, err := s.Expect(z.X{"some", z.P{"thing"}})
|
||||
_, err := s.Expect(z.X{"some", z.Y{"thing"}})
|
||||
fmt.Println(err)
|
||||
s.Print() // but scanner did get "some" so advanced
|
||||
// Output:
|
||||
|
Loading…
Reference in New Issue
Block a user