package main import ( "fmt" //"io/ioutil" "github.com/z7zmey/php-parser/node" "github.com/z7zmey/php-parser/node/stmt" "github.com/z7zmey/php-parser/walker" ) type normaliseAltsPass struct { } func (np *normaliseAltsPass) transformNonRecursive(n node.Node) (node.Node, bool) { switch n := n.(type) { case *stmt.AltIf: // Build replacement node ifStmt := stmt.NewIf(n.Cond, n.Stmt, n.ElseIf, n.Else) ifStmt.FreeFloating = n.FreeFloating ifStmt.Position = n.Position // ifStmt has no .Attributes prop return ifStmt, true case *stmt.AltElse: elseStmt := stmt.NewElse(n.Stmt) elseStmt.FreeFloating = n.FreeFloating elseStmt.Position = n.Position return elseStmt, true case *stmt.AltElseIf: elifStmt := stmt.NewElseIf(n.Cond, n.Stmt) elifStmt.FreeFloating = n.FreeFloating elifStmt.Position = n.Position return elifStmt, true default: return n, false // no change } } func (np *normaliseAltsPass) walkMutateArray(stmts []node.Node) { for i, _ := range stmts { np.walkMutate(&stmts[i]) } } func (np *normaliseAltsPass) walkMutate(child *node.Node) { v2, didChange := np.transformNonRecursive(*child) if didChange { v2.Walk(np) *child = v2 } else { (*child).Walk(np) } } func (np *normaliseAltsPass) EnterNode(w walker.Walkable) bool { n, ok := w.(node.Node) if !ok { panic(fmt.Errorf("Tried to walk non-node '%t'", w)) } // We need to override the .Walk() behaviour for all possible *parents* // of affected nodes. This is because the .Walk() interface does not give // us any opportunity to override single elements by the time we get there // Our custom Walk() implementation is not firing all EnterChildList/LeaveNode // visitors - but - that's fine since they're all noops anyway switch n := n.(type) { case *stmt.StmtList: np.walkMutateArray(n.Stmts) // mutate slice in place return false // Signal not to use upstream .Walk() implementation case *node.Root: np.walkMutateArray(n.Stmts) // mutate slice in place return false // Signal not to use upstream .Walk() implementation case *stmt.AltIf: panic("altif") np.walkMutate(&n.Cond) np.walkMutateArray(n.ElseIf) np.walkMutate(&n.Else) return false default: // No normalisation needed for this node type // Recurse deeper return true } } func (np *normaliseAltsPass) LeaveNode(w walker.Walkable) {} func (np *normaliseAltsPass) EnterChildNode(key string, w walker.Walkable) {} func (np *normaliseAltsPass) LeaveChildNode(key string, w walker.Walkable) {} func (np *normaliseAltsPass) EnterChildList(key string, w walker.Walkable) {} func (np *normaliseAltsPass) LeaveChildList(key string, w walker.Walkable) {} var _ walker.Visitor = &normaliseAltsPass{} // interface assertion