Initial QSfera import
This commit is contained in:
+86
@@ -0,0 +1,86 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user