implement walkMutate(*node); completely transform AltIf->If
This commit is contained in:
parent
6d9aa8b022
commit
df2fc21324
@ -28,3 +28,11 @@ endif;
|
|||||||
|
|
||||||
// Unbraced
|
// Unbraced
|
||||||
if (true) echo "100";
|
if (true) echo "100";
|
||||||
|
|
||||||
|
// Colon style within deeper scope
|
||||||
|
|
||||||
|
{{{{
|
||||||
|
if (1 == 1):
|
||||||
|
echo "asdf";
|
||||||
|
endif;
|
||||||
|
}}}}
|
3
main.go
3
main.go
@ -48,8 +48,7 @@ func ConvertFile(filename string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pass 1: Normalise Alt** Stmt types
|
// Pass 1: Normalise Alt** Stmt types
|
||||||
normPass := normaliseAltsPass{}
|
walkMutate(&n, normaliseAltCb)
|
||||||
n.Walk(&normPass) // can't modify root node, but that's fine
|
|
||||||
|
|
||||||
// Debug pass: Walk and print JSON...
|
// Debug pass: Walk and print JSON...
|
||||||
if fh, err := os.OpenFile(filename+`.parse2.json`, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644); err == nil {
|
if fh, err := os.OpenFile(filename+`.parse2.json`, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644); err == nil {
|
||||||
|
54
mutatingwalker.go
Normal file
54
mutatingwalker.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
func walkMutate(n_ *node.Node, cb func(*node.Node)) {
|
||||||
|
|
||||||
|
// Mutate in-place, non recursive...
|
||||||
|
cb(n_)
|
||||||
|
|
||||||
|
// Walk on the mutated version
|
||||||
|
// We must reimplement .Walk() in order to get pointer behaviour
|
||||||
|
|
||||||
|
switch n := (*n_).(type) {
|
||||||
|
case *stmt.StmtList:
|
||||||
|
for i, _ := range n.Stmts {
|
||||||
|
walkMutate(&n.Stmts[i], cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *node.Root:
|
||||||
|
for i, _ := range n.Stmts {
|
||||||
|
walkMutate(&n.Stmts[i], cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *stmt.If:
|
||||||
|
walkMutate(&n.Cond, cb)
|
||||||
|
walkMutate(&n.Else, cb)
|
||||||
|
for i, _ := range n.ElseIf {
|
||||||
|
walkMutate(&n.ElseIf[i], cb)
|
||||||
|
}
|
||||||
|
walkMutate(&n.Stmt, cb)
|
||||||
|
|
||||||
|
case *stmt.Else:
|
||||||
|
walkMutate(&n.Stmt, cb)
|
||||||
|
|
||||||
|
case *stmt.ElseIf:
|
||||||
|
walkMutate(&n.Cond, cb)
|
||||||
|
walkMutate(&n.Stmt, cb)
|
||||||
|
|
||||||
|
default:
|
||||||
|
// FIXME need to implement Walk() for all node types, to ensure that
|
||||||
|
// we can perform mutation transforms in nested contexts
|
||||||
|
// bail
|
||||||
|
//panic(fmt.Sprintf("walkMutate: unimplemented type '%t'", n))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,101 +1,41 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
//"fmt"
|
||||||
//"io/ioutil"
|
//"io/ioutil"
|
||||||
|
|
||||||
"github.com/z7zmey/php-parser/node"
|
"github.com/z7zmey/php-parser/node"
|
||||||
"github.com/z7zmey/php-parser/node/stmt"
|
"github.com/z7zmey/php-parser/node/stmt"
|
||||||
"github.com/z7zmey/php-parser/walker"
|
//"github.com/z7zmey/php-parser/walker"
|
||||||
)
|
)
|
||||||
|
|
||||||
type normaliseAltsPass struct {
|
func normaliseAltCb(n_ *node.Node) {
|
||||||
}
|
|
||||||
|
|
||||||
func (np *normaliseAltsPass) transformNonRecursive(n node.Node) (node.Node, bool) {
|
switch n := (*n_).(type) {
|
||||||
|
|
||||||
switch n := n.(type) {
|
|
||||||
case *stmt.AltIf:
|
case *stmt.AltIf:
|
||||||
// Build replacement node
|
// Build replacement node
|
||||||
ifStmt := stmt.NewIf(n.Cond, n.Stmt, n.ElseIf, n.Else)
|
ifStmt := stmt.NewIf(n.Cond, n.Stmt, n.ElseIf, n.Else)
|
||||||
ifStmt.FreeFloating = n.FreeFloating
|
ifStmt.FreeFloating = n.FreeFloating
|
||||||
ifStmt.Position = n.Position
|
ifStmt.Position = n.Position
|
||||||
// ifStmt has no .Attributes prop
|
// ifStmt has no .Attributes prop
|
||||||
return ifStmt, true
|
|
||||||
|
*n_ = ifStmt
|
||||||
|
|
||||||
case *stmt.AltElse:
|
case *stmt.AltElse:
|
||||||
elseStmt := stmt.NewElse(n.Stmt)
|
elseStmt := stmt.NewElse(n.Stmt)
|
||||||
elseStmt.FreeFloating = n.FreeFloating
|
elseStmt.FreeFloating = n.FreeFloating
|
||||||
elseStmt.Position = n.Position
|
elseStmt.Position = n.Position
|
||||||
return elseStmt, true
|
|
||||||
|
*n_ = elseStmt
|
||||||
|
|
||||||
case *stmt.AltElseIf:
|
case *stmt.AltElseIf:
|
||||||
elifStmt := stmt.NewElseIf(n.Cond, n.Stmt)
|
elifStmt := stmt.NewElseIf(n.Cond, n.Stmt)
|
||||||
elifStmt.FreeFloating = n.FreeFloating
|
elifStmt.FreeFloating = n.FreeFloating
|
||||||
elifStmt.Position = n.Position
|
elifStmt.Position = n.Position
|
||||||
return elifStmt, true
|
|
||||||
|
*n_ = elifStmt
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return n, false // no change
|
return // 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
|
|
||||||
|
Loading…
Reference in New Issue
Block a user