package traverser import "github.com/z7zmey/php-parser/pkg/ast" type DFS struct { visitor ast.Visitor } func NewDFS(visitor ast.Visitor) *DFS { return &DFS{ visitor: visitor, } } func (t *DFS) Traverse(n ast.Vertex) { if n == nil { return } if !t.visitor.EnterNode(n) { return } switch nn := n.(type) { case *ast.Root: t.traverseArray("Stmts", nn.Stmts) case *ast.Nullable: t.traverseSingle("Expr", nn.Expr) case *ast.Parameter: t.traverseSingle("Type", nn.Type) t.traverseSingle("Var", nn.Var) t.traverseSingle("DefaultValue", nn.DefaultValue) case *ast.Identifier: case *ast.ArgumentList: t.traverseArray("Arguments", nn.Arguments) case *ast.Argument: t.traverseSingle("Expr", nn.Expr) case *ast.StmtAltElse: t.traverseSingle("Stmt", nn.Stmt) case *ast.StmtAltElseIf: t.traverseSingle("Cond", nn.Cond) t.traverseSingle("Stmt", nn.Stmt) case *ast.StmtAltFor: t.traverseArray("Init", nn.Init) t.traverseArray("Cond", nn.Cond) t.traverseArray("Loop", nn.Loop) t.traverseSingle("Stmt", nn.Stmt) case *ast.StmtAltForeach: t.traverseSingle("Expr", nn.Expr) t.traverseSingle("Key", nn.Key) t.traverseSingle("Var", nn.Var) t.traverseSingle("Stmt", nn.Stmt) case *ast.StmtAltIf: t.traverseSingle("Cond", nn.Cond) t.traverseSingle("Stmt", nn.Stmt) t.traverseArray("ElseIf", nn.ElseIf) t.traverseSingle("Else", nn.Else) case *ast.StmtAltSwitch: t.traverseSingle("Cond", nn.Cond) t.traverseSingle("CaseList", nn.CaseList) case *ast.StmtAltWhile: t.traverseSingle("Cond", nn.Cond) t.traverseSingle("Stmt", nn.Stmt) case *ast.StmtBreak: t.traverseSingle("Expr", nn.Expr) case *ast.StmtCase: t.traverseSingle("Cond", nn.Cond) t.traverseArray("Stmts", nn.Stmts) case *ast.StmtCaseList: t.traverseArray("Cases", nn.Cases) case *ast.StmtCatch: t.traverseArray("Types", nn.Types) t.traverseSingle("Var", nn.Var) t.traverseArray("Stmts", nn.Stmts) case *ast.StmtClass: t.traverseSingle("ClassName", nn.ClassName) t.traverseArray("Modifiers", nn.Modifiers) t.traverseArray("Stmts", nn.Stmts) case *ast.StmtClassConstList: t.traverseArray("Modifiers", nn.Modifiers) t.traverseArray("Consts", nn.Consts) case *ast.StmtClassExtends: t.traverseSingle("ClassName", nn.ClassName) case *ast.StmtClassImplements: t.traverseArray("InterfaceNames", nn.InterfaceNames) case *ast.StmtClassMethod: t.traverseSingle("MethodName", nn.MethodName) t.traverseArray("Modifiers", nn.Modifiers) t.traverseArray("Params", nn.Params) t.traverseSingle("ReturnType", nn.ReturnType) t.traverseSingle("Stmt", nn.Stmt) case *ast.StmtConstList: t.traverseArray("Consts", nn.Consts) case *ast.StmtConstant: t.traverseSingle("ConstantName", nn.ConstantName) t.traverseSingle("Expr", nn.Expr) case *ast.StmtContinue: t.traverseSingle("Expr", nn.Expr) case *ast.StmtDeclare: t.traverseArray("Consts", nn.Consts) t.traverseSingle("Stmt", nn.Stmt) case *ast.StmtDefault: t.traverseArray("Stmts", nn.Stmts) case *ast.StmtDo: t.traverseSingle("Stmt", nn.Stmt) t.traverseSingle("Cond", nn.Cond) case *ast.StmtEcho: t.traverseArray("Exprs", nn.Exprs) case *ast.StmtElse: t.traverseSingle("Stmt", nn.Stmt) case *ast.StmtElseIf: t.traverseSingle("Cond", nn.Cond) t.traverseSingle("Stmt", nn.Stmt) case *ast.StmtExpression: t.traverseSingle("Expr", nn.Expr) case *ast.StmtFinally: t.traverseArray("Stmts", nn.Stmts) case *ast.StmtFor: t.traverseArray("Init", nn.Init) t.traverseArray("Cond", nn.Cond) t.traverseArray("Loop", nn.Loop) t.traverseSingle("Stmt", nn.Stmt) case *ast.StmtForeach: t.traverseSingle("Expr", nn.Expr) t.traverseSingle("Key", nn.Key) t.traverseSingle("Var", nn.Var) t.traverseSingle("Stmt", nn.Stmt) case *ast.StmtFunction: t.traverseSingle("FunctionName", nn.FunctionName) t.traverseArray("Params", nn.Params) t.traverseSingle("ReturnType", nn.ReturnType) t.traverseArray("Stmts", nn.Stmts) case *ast.StmtGlobal: t.traverseArray("Vars", nn.Vars) case *ast.StmtGoto: t.traverseSingle("Label", nn.Label) case *ast.StmtGroupUse: t.traverseSingle("UseType", nn.UseType) t.traverseSingle("Prefix", nn.Prefix) t.traverseArray("UseList", nn.UseList) case *ast.StmtHaltCompiler: case *ast.StmtIf: t.traverseSingle("Cond", nn.Cond) t.traverseSingle("Stmt", nn.Stmt) t.traverseArray("ElseIf", nn.ElseIf) t.traverseSingle("Else", nn.Else) case *ast.StmtInlineHtml: case *ast.StmtInterface: t.traverseSingle("InterfaceName", nn.InterfaceName) t.traverseArray("Stmts", nn.Stmts) case *ast.StmtInterfaceExtends: t.traverseArray("InterfaceNames", nn.InterfaceNames) case *ast.StmtLabel: t.traverseSingle("LabelName", nn.LabelName) case *ast.StmtNamespace: t.traverseSingle("NamespaceName", nn.NamespaceName) t.traverseArray("Stmts", nn.Stmts) case *ast.StmtNop: case *ast.StmtProperty: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.StmtPropertyList: t.traverseArray("Modifiers", nn.Modifiers) t.traverseSingle("Type", nn.Type) t.traverseArray("Properties", nn.Properties) case *ast.StmtReturn: t.traverseSingle("Expr", nn.Expr) case *ast.StmtStatic: t.traverseArray("Vars", nn.Vars) case *ast.StmtStaticVar: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.StmtStmtList: t.traverseArray("Stmts", nn.Stmts) case *ast.StmtSwitch: t.traverseSingle("Cond", nn.Cond) case *ast.StmtThrow: t.traverseSingle("Expr", nn.Expr) case *ast.StmtTrait: t.traverseSingle("TraitName", nn.TraitName) t.traverseArray("Stmts", nn.Stmts) case *ast.StmtTraitAdaptationList: t.traverseArray("Adaptations", nn.Adaptations) case *ast.StmtTraitMethodRef: t.traverseSingle("Trait", nn.Trait) t.traverseSingle("Method", nn.Method) case *ast.StmtTraitUse: t.traverseArray("Traits", nn.Traits) t.traverseSingle("TraitAdaptationList", nn.TraitAdaptationList) case *ast.StmtTraitUseAlias: t.traverseSingle("Ref", nn.Ref) t.traverseSingle("Modifier", nn.Modifier) t.traverseSingle("Alias", nn.Alias) case *ast.StmtTraitUsePrecedence: t.traverseSingle("Ref", nn.Ref) t.traverseArray("Insteadof", nn.Insteadof) case *ast.StmtTry: t.traverseArray("Stmts", nn.Stmts) t.traverseArray("Catches", nn.Catches) t.traverseSingle("Finally", nn.Finally) case *ast.StmtUnset: t.traverseArray("Vars", nn.Vars) case *ast.StmtUse: t.traverseSingle("UseType", nn.UseType) t.traverseSingle("Use", nn.Use) t.traverseSingle("Alias", nn.Alias) case *ast.StmtUseList: t.traverseSingle("UseType", nn.UseType) t.traverseArray("Uses", nn.Uses) case *ast.StmtWhile: t.traverseSingle("Cond", nn.Cond) t.traverseSingle("Stmt", nn.Stmt) case *ast.ExprArray: t.traverseArray("Items", nn.Items) case *ast.ExprArrayDimFetch: t.traverseSingle("Var", nn.Var) t.traverseSingle("Dim", nn.Dim) case *ast.ExprArrayItem: t.traverseSingle("Key", nn.Key) t.traverseSingle("Val", nn.Val) case *ast.ExprArrowFunction: t.traverseArray("Params", nn.Params) t.traverseSingle("ReturnType", nn.ReturnType) t.traverseSingle("Expr", nn.Expr) case *ast.ExprBitwiseNot: t.traverseSingle("Expr", nn.Expr) case *ast.ExprBooleanNot: t.traverseSingle("Expr", nn.Expr) case *ast.ExprClassConstFetch: t.traverseSingle("Class", nn.Class) t.traverseSingle("ConstantName", nn.ConstantName) case *ast.ExprClone: t.traverseSingle("Expr", nn.Expr) case *ast.ExprClosure: t.traverseArray("Params", nn.Params) t.traverseSingle("ClosureUse", nn.ClosureUse) t.traverseSingle("ReturnType", nn.ReturnType) t.traverseArray("Stmts", nn.Stmts) case *ast.ExprClosureUse: t.traverseArray("Uses", nn.Uses) case *ast.ExprConstFetch: t.traverseSingle("Const", nn.Const) case *ast.ExprEmpty: t.traverseSingle("Expr", nn.Expr) case *ast.ExprErrorSuppress: t.traverseSingle("Expr", nn.Expr) case *ast.ExprEval: t.traverseSingle("Expr", nn.Expr) case *ast.ExprExit: t.traverseSingle("Expr", nn.Expr) case *ast.ExprFunctionCall: t.traverseSingle("Function", nn.Function) t.traverseSingle("ArgumentList", nn.ArgumentList) case *ast.ExprInclude: t.traverseSingle("Expr", nn.Expr) case *ast.ExprIncludeOnce: t.traverseSingle("Expr", nn.Expr) case *ast.ExprInstanceOf: t.traverseSingle("Expr", nn.Expr) t.traverseSingle("Class", nn.Class) case *ast.ExprIsset: t.traverseArray("Vars", nn.Vars) case *ast.ExprList: t.traverseArray("Items", nn.Items) case *ast.ExprMethodCall: t.traverseSingle("Var", nn.Var) t.traverseSingle("Method", nn.Method) case *ast.ExprNew: t.traverseSingle("Class", nn.Class) case *ast.ExprPostDec: t.traverseSingle("Var", nn.Var) case *ast.ExprPostInc: t.traverseSingle("Var", nn.Var) case *ast.ExprPreDec: t.traverseSingle("Var", nn.Var) case *ast.ExprPreInc: t.traverseSingle("Var", nn.Var) case *ast.ExprPrint: t.traverseSingle("Expr", nn.Expr) case *ast.ExprPropertyFetch: t.traverseSingle("Var", nn.Var) t.traverseSingle("Property", nn.Property) case *ast.ExprReference: t.traverseSingle("Var", nn.Var) case *ast.ExprRequire: t.traverseSingle("Expr", nn.Expr) case *ast.ExprRequireOnce: t.traverseSingle("Expr", nn.Expr) case *ast.ExprShellExec: t.traverseArray("Parts", nn.Parts) case *ast.ExprShortArray: t.traverseArray("Items", nn.Items) case *ast.ExprShortList: t.traverseArray("Items", nn.Items) case *ast.ExprStaticCall: t.traverseSingle("Class", nn.Class) t.traverseSingle("Call", nn.Call) t.traverseSingle("ArgumentList", nn.ArgumentList) case *ast.ExprStaticPropertyFetch: t.traverseSingle("Class", nn.Class) t.traverseSingle("Property", nn.Property) case *ast.ExprTernary: t.traverseSingle("Condition", nn.Condition) t.traverseSingle("IfTrue", nn.IfTrue) t.traverseSingle("IfFalse", nn.IfFalse) case *ast.ExprUnaryMinus: t.traverseSingle("Expr", nn.Expr) case *ast.ExprUnaryPlus: t.traverseSingle("Expr", nn.Expr) case *ast.ExprVariable: t.traverseSingle("VarName", nn.VarName) case *ast.ExprYield: t.traverseSingle("Key", nn.Key) t.traverseSingle("Value", nn.Value) case *ast.ExprYieldFrom: t.traverseSingle("Expr", nn.Expr) case *ast.ExprAssign: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.ExprAssignReference: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.ExprAssignBitwiseAnd: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.ExprAssignBitwiseOr: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.ExprAssignBitwiseXor: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.ExprAssignCoalesce: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.ExprAssignConcat: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.ExprAssignDiv: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.ExprAssignMinus: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.ExprAssignMod: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.ExprAssignMul: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.ExprAssignPlus: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.ExprAssignPow: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.ExprAssignShiftLeft: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.ExprAssignShiftRight: t.traverseSingle("Var", nn.Var) t.traverseSingle("Expr", nn.Expr) case *ast.ExprBinaryBitwiseAnd: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryBitwiseOr: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryBitwiseXor: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryBooleanAnd: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryBooleanOr: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryCoalesce: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryConcat: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryDiv: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryEqual: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryGreater: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryGreaterOrEqual: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryIdentical: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryLogicalAnd: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryLogicalOr: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryLogicalXor: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryMinus: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryMod: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryMul: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryNotEqual: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryNotIdentical: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryPlus: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryPow: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryShiftLeft: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinaryShiftRight: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinarySmaller: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinarySmallerOrEqual: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprBinarySpaceship: t.traverseSingle("Left", nn.Left) t.traverseSingle("Right", nn.Right) case *ast.ExprCastArray: t.traverseSingle("Expr", nn.Expr) case *ast.ExprCastBool: t.traverseSingle("Expr", nn.Expr) case *ast.ExprCastDouble: t.traverseSingle("Expr", nn.Expr) case *ast.ExprCastInt: t.traverseSingle("Expr", nn.Expr) case *ast.ExprCastObject: t.traverseSingle("Expr", nn.Expr) case *ast.ExprCastString: t.traverseSingle("Expr", nn.Expr) case *ast.ExprCastUnset: t.traverseSingle("Expr", nn.Expr) case *ast.ScalarDnumber: case *ast.ScalarEncapsed: t.traverseArray("Parts", nn.Parts) case *ast.ScalarEncapsedStringPart: case *ast.ScalarHeredoc: t.traverseArray("Parts", nn.Parts) case *ast.ScalarLnumber: case *ast.ScalarMagicConstant: case *ast.ScalarString: } t.visitor.LeaveNode(n) } func (t *DFS) traverseSingle(key string, n ast.Vertex) { if n == nil { return } t.visitor.Enter(key, true) t.Traverse(n) t.visitor.Leave(key, true) } func (t *DFS) traverseArray(key string, nn []ast.Vertex) { if nn == nil { return } t.visitor.Enter(key, false) for _, c := range nn { t.Traverse(c) } t.visitor.Leave(key, false) }