~mna/siberian

a645b2d7c420414d5405d38896a5f94819995577 — Martin Angers 4 years ago 1b54b1d
add MatcherVisitor interface and implementation
5 files changed, 35 insertions(+), 10 deletions(-)

D ast.go
M ebnf.go
M matcher.go
M parse.go
D visit.go
D ast.go => ast.go +0 -1
@@ 1,1 0,0 @@
package siberian

M ebnf.go => ebnf.go +19 -0
@@ 19,6 19,13 @@ func (a *Alt) Match(b []byte, p int) int {
	return -1
}

// Visit implements MatcherVisitor for Atl.
func (a *Alt) Visit(fn func(m Matcher) Matcher) {
	for i, m := range a.Ms {
		a.Ms[i] = VisitMatcher(m, fn)
	}
}

// Not returns a Matcher that returns a zero-match if m does not match,
// and a no-match if m does match.
func Not(m Matcher) MatcherFunc {


@@ 117,6 124,11 @@ func (r *Repeat) Match(b []byte, p int) int {
	}
}

// Visit implements MatcherVisitor for Repeat.
func (r *Repeat) Visit(fn func(Matcher) Matcher) {
	r.M = VisitMatcher(r.M, fn)
}

// Seq is a Matcher that matches if the Ms all match in sequence.
// If Ms is empty, Seq is a 0 match.
type Seq struct {


@@ 135,3 147,10 @@ func (s *Seq) Match(b []byte, p int) int {
	}
	return n
}

// Visit implements MatcherVisitor for Seq.
func (s *Seq) Visit(fn func(Matcher) Matcher) {
	for i, m := range s.Ms {
		s.Ms[i] = VisitMatcher(m, fn)
	}
}

M matcher.go => matcher.go +7 -2
@@ 18,6 18,12 @@ type Matcher interface {
	Match(b []byte, p int) int
}

// MatcherVisitor defines the method to visit the Matchers and possibly
// replace or wrap them in a different Matcher.
type MatcherVisitor interface {
	Visit(fn func(Matcher) Matcher)
}

// MatcherFunc is a function type that implements Matcher by calling
// itself.
type MatcherFunc func([]byte, int) int


@@ 142,8 148,7 @@ func Runes(n int) MatcherFunc {
var EOF = MatcherFunc(eof)

func eof(b []byte, p int) int {
	b = b[p:]
	if len(b) == 0 {
	if len(b[p:]) == 0 {
		return 0
	}
	return -1

M parse.go => parse.go +9 -0
@@ 8,3 8,12 @@ func Matches(m Matcher, b []byte) bool {
	n := m.Match(b, 0)
	return n >= 0
}

// VisitMatcher visits m and any matchers it wraps, calling fn for each,
// possibly wrapping or replacing the matchers with its returned value.
func VisitMatcher(m Matcher, fn func(Matcher) Matcher) Matcher {
	if v, ok := m.(MatcherVisitor); ok {
		v.Visit(fn)
	}
	return fn(m)
}

D visit.go => visit.go +0 -7
@@ 1,7 0,0 @@
package siberian

/*
func Visit(m Matcher, fn func(m Matcher) Matcher) {

}
*/