From 47ee497b0db18fb08fb1a59ee92c20f5ca02c007 Mon Sep 17 00:00:00 2001 From: rwxrob Date: Fri, 4 Mar 2022 16:12:21 -0500 Subject: [PATCH] Add z name, z.N and z.X --- scan/is/compound.go | 2 +- scan/is/is.go | 52 ++++++++++++++++++++++++++++++--------------- scan/scan.go | 6 +++--- scan/scan_test.go | 10 ++++----- 4 files changed, 44 insertions(+), 26 deletions(-) diff --git a/scan/is/compound.go b/scan/is/compound.go index 55c0f42..4db2c79 100644 --- a/scan/is/compound.go +++ b/scan/is/compound.go @@ -1,4 +1,4 @@ -package is +package z // keep only compound expressions here diff --git a/scan/is/is.go b/scan/is/is.go index 85cc4db..b15072b 100644 --- a/scan/is/is.go +++ b/scan/is/is.go @@ -2,13 +2,19 @@ // SPDX-License-Identifier: Apache-2.0 /* -Package is defines the Bonzai Parsing Expression Grammar Notation -(BPEGN) implemented entirely using Go types (mostly slices and structs). -BPEGN can be 100% transpiled to and from the Parsing Expression Grammer -Notation (PEGN). Code in one and use "bonzai pegn" command to easily -generate the other. BPEGN is sometimes referred to informally as "Bonzai -Scanner Expect" language as well since it is passed directly to -scan.Expect or scan.Check. +Package z (often imported as "is") defines the Bonzai Parsing Expression +Grammar Notation (BPEGN) (aka "Bonzai Scanner Expect" language) +implemented entirely using Go types (mostly slices and structs). BPEGN +can be 100% transpiled to and from the Parsing Expression Grammer +Notation (PEGN). Code in one grammar and use the bonzai command to +easily generate the other. + +Nodes and Expressions + +Nodes (z.N) indicate something to be captured as a part of the resulting +abstract syntax tree. They are functionally equivalent to parenthesis in +regular expressions but with the obvious advantage of capturing a rooted +node tree instead of an array. Expressions (z.X) indicate a sequence to be scanned but not captured unless the expression itself is within a node (z.N). Tokens @@ -49,15 +55,27 @@ a scan.R). A Hook is passed only the scanner struct and must return a bool indicating if the scan should proceed. See scan.Hook for more information. */ -package is +package z + +// ------------------------------- core ------------------------------- + +// N ("node") is a named sequence of expressions that will be captured +// into a node. 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.N) 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 N []any + +// X ("expression") is a sequence of expressions. If any are not the +// scan fails. (Equal to (?foo) in regular expressions.) +type X []any // ------------------------------- sets ------------------------------- -// X (the slice) groups expressions into a sequence. It ensures that all -// expressions appears in that specific order. If any are not the scan -// fails. (Equal to parenthesis in PEGN.) -type X []any - // It (the slice) is a set of positive lookahead expressions. If any are // seen at the current cursor position the scan will proceed without // consuming them (unlike is.O and is.In). If none are found the scan @@ -121,15 +139,15 @@ type Min struct { // Mn1 is shorthand for is.Min{1,This}. type Mn1 struct{ This any } -// N is a parameterized advancing expression that matches exactly -// N number of the given expression (This). Use within is.It to disable +// C is a parameterized advancing expression that matches an exact count +// of the given expression (This). Use within is.It to disable // advancement. -type N struct { +type C struct { N int This any } -// Any is short for is.N{tk.ANY}. +// Any is short for is.C{tk.ANY}. type Any struct { N int } diff --git a/scan/scan.go b/scan/scan.go index 8aae3b6..7e7939f 100644 --- a/scan/scan.go +++ b/scan/scan.go @@ -22,7 +22,7 @@ import ( "io" "unicode/utf8" - "github.com/rwxrob/bonzai/scan/is" + is "github.com/rwxrob/bonzai/scan/is" "github.com/rwxrob/bonzai/scan/tk" "github.com/rwxrob/bonzai/util" ) @@ -446,7 +446,7 @@ func (s *R) Expect(expr any) (*Cur, error) { } return last, nil - case is.N: // ------------------------------------------------------ + case is.C: // ------------------------------------------------------ b := s.Mark() m, err := s.Expect(is.MMx{v.N, v.N, v.This}) if err != nil { @@ -539,7 +539,7 @@ func (s *R) ErrorExpected(this any, args ...any) error { case is.MMx: str := `expected min %v, max %v of %q` msg = fmt.Sprintf(str, v.Min, v.Max, v.This) - case is.N: + case is.C: str := `expected exactly %v of %q` msg = fmt.Sprintf(str, v.N, v.This) case is.Rng: diff --git a/scan/scan_test.go b/scan/scan_test.go index 44ded5b..18f81ab 100644 --- a/scan/scan_test.go +++ b/scan/scan_test.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/rwxrob/bonzai/scan" - "github.com/rwxrob/bonzai/scan/is" + is "github.com/rwxrob/bonzai/scan/is" "github.com/rwxrob/bonzai/scan/tk" ) @@ -464,17 +464,17 @@ func ExampleExpect_mMx() { // expected min 1, max 3 of 'X' at U+006F 'o' 1,2-2 (2-2) } -func ExampleExpect_n() { +func ExampleExpect_c() { s, _ := scan.New("sommme thing") s.Snap() s.ScanN(2) s.Print() - s.Expect(is.N{3, 'm'}) // goggles up all three + s.Expect(is.C{3, 'm'}) // goggles up all three s.Print() s.Back() - s.Expect(is.N{1, 's'}) // yes, but silly since 's' is easier + s.Expect(is.C{1, 's'}) // yes, but silly since 's' is easier s.Print() - _, err := s.Expect(is.N{3, 'X'}) // nope + _, err := s.Expect(is.C{3, 'X'}) // nope fmt.Println(err) // Output: // U+006D 'm' 1,3-3 (3-3)