Files
QSfera/Server/vendor/github.com/mna/pigeon/ast/ast_walk.go
T
Курнат Андрей 2315f25754 Initial QSfera import
2026-06-07 10:20:04 +03:00

87 lines
2.0 KiB
Go

package ast
import "fmt"
// A Visitor implements a Visit method, which is invoked for each Expression
// encountered by Walk.
// If the result visitor w is not nil, Walk visits each of the children
// of Expression with the visitor w, followed by a call of w.Visit(nil).
type Visitor interface {
Visit(expr Expression) (w Visitor)
}
// Walk traverses an AST in depth-first order: It starts by calling
// v.Visit(expr); Expression must not be nil. If the visitor w returned by
// v.Visit(expr) is not nil, Walk is invoked recursively with visitor
// w for each of the non-nil children of Expression, followed by a call of
// w.Visit(nil).
func Walk(v Visitor, expr Expression) {
if v = v.Visit(expr); v == nil {
return
}
switch expr := expr.(type) {
case *ActionExpr:
Walk(v, expr.Expr)
case *AndCodeExpr:
// Nothing to do
case *AndExpr:
Walk(v, expr.Expr)
case *AnyMatcher:
// Nothing to do
case *CharClassMatcher:
// Nothing to do
case *ChoiceExpr:
for _, e := range expr.Alternatives {
Walk(v, e)
}
case *Grammar:
for _, e := range expr.Rules {
Walk(v, e)
}
case *LabeledExpr:
Walk(v, expr.Expr)
case *LitMatcher:
// Nothing to do
case *NotCodeExpr:
// Nothing to do
case *NotExpr:
Walk(v, expr.Expr)
case *OneOrMoreExpr:
Walk(v, expr.Expr)
case *Rule:
Walk(v, expr.Expr)
case *RuleRefExpr:
// Nothing to do
case *SeqExpr:
for _, e := range expr.Exprs {
Walk(v, e)
}
case *StateCodeExpr:
// Nothing to do
case *ZeroOrMoreExpr:
Walk(v, expr.Expr)
case *ZeroOrOneExpr:
Walk(v, expr.Expr)
default:
panic(fmt.Sprintf("unknown expression type %T", expr))
}
}
type inspector func(Expression) bool
func (f inspector) Visit(expr Expression) Visitor {
if f(expr) {
return f
}
return nil
}
// Inspect traverses an AST in depth-first order: It starts by calling
// f(expr); expr must not be nil. If f returns true, Inspect invokes f
// recursively for each of the non-nil children of expr, followed by a
// call of f(nil).
func Inspect(expr Expression, f func(Expression) bool) {
Walk(inspector(f), expr)
}