pretty printer: printing alternative statements

This commit is contained in:
z7zmey 2018-03-19 22:50:07 +02:00
parent c84c8b2106
commit 240efb20e5
2 changed files with 407 additions and 0 deletions

View File

@ -3,6 +3,8 @@ package printer
import (
"io"
"github.com/z7zmey/php-parser/node/stmt"
"github.com/z7zmey/php-parser/node"
"github.com/z7zmey/php-parser/node/expr"
"github.com/z7zmey/php-parser/node/expr/assign"
@ -27,6 +29,14 @@ func printComaSeparated(o io.Writer, nn []node.Node) {
}
}
func printNodes(o io.Writer, nn []node.Node) {
// TODO: handle indentations
for _, n := range nn {
Print(o, n)
io.WriteString(o, ";\n")
}
}
func getPrintFuncByNode(n node.Node) func(o io.Writer, n node.Node) {
switch n.(type) {
@ -256,6 +266,29 @@ func getPrintFuncByNode(n node.Node) func(o io.Writer, n node.Node) {
return printExprYieldFrom
case *expr.Yield:
return printExprYield
// stmt
case *stmt.AltElseIf:
return printStmtAltElseIf
case *stmt.AltElse:
return printStmtAltElse
case *stmt.AltFor:
return printStmtAltFor
case *stmt.AltForeach:
return printStmtAltForeach
case *stmt.AltIf:
return printStmtAltIf
case *stmt.AltSwitch:
return printStmtAltSwitch
case *stmt.AltWhile:
return printStmtAltWhile
case *stmt.Case:
return printStmtCase
case *stmt.StmtList:
return printStmtStmtList
case *stmt.Expression:
return printStmtExpression
}
panic("printer is missing for the node")
@ -1132,3 +1165,131 @@ func printExprYield(o io.Writer, n node.Node) {
Print(o, nn.Value)
}
// smtm
func printStmtAltElseIf(o io.Writer, n node.Node) {
nn := n.(*stmt.AltElseIf)
io.WriteString(o, "elseif (")
Print(o, nn.Cond)
io.WriteString(o, ") :\n")
Print(o, nn.Stmt)
}
func printStmtAltElse(o io.Writer, n node.Node) {
nn := n.(*stmt.AltElse)
io.WriteString(o, "else :\n")
Print(o, nn.Stmt)
}
func printStmtAltFor(o io.Writer, n node.Node) {
nn := n.(*stmt.AltFor)
io.WriteString(o, "for (")
printComaSeparated(o, nn.Init)
io.WriteString(o, "; ")
printComaSeparated(o, nn.Cond)
io.WriteString(o, "; ")
printComaSeparated(o, nn.Loop)
io.WriteString(o, ") :\n")
Print(o, nn.Stmt)
io.WriteString(o, "endfor;\n")
}
func printStmtAltForeach(o io.Writer, n node.Node) {
nn := n.(*stmt.AltForeach)
io.WriteString(o, "foreach (")
Print(o, nn.Expr)
io.WriteString(o, " as ")
if nn.Key != nil {
Print(o, nn.Key)
io.WriteString(o, " => ")
}
if nn.ByRef {
io.WriteString(o, "&")
}
Print(o, nn.Variable)
io.WriteString(o, ") :\n")
Print(o, nn.Stmt)
io.WriteString(o, "endforeach;\n")
}
func printStmtAltIf(o io.Writer, n node.Node) {
nn := n.(*stmt.AltIf)
io.WriteString(o, "if (")
Print(o, nn.Cond)
io.WriteString(o, ") :\n")
Print(o, nn.Stmt)
for _, elseif := range nn.ElseIf {
Print(o, elseif)
}
if nn.Else != nil {
Print(o, nn.Else)
}
io.WriteString(o, "endif;\n")
}
func printStmtAltSwitch(o io.Writer, n node.Node) {
nn := n.(*stmt.AltSwitch)
io.WriteString(o, "switch (")
Print(o, nn.Cond)
io.WriteString(o, ") :\n")
for _, c := range nn.Cases {
Print(o, c)
}
io.WriteString(o, "endswitch;\n")
}
func printStmtAltWhile(o io.Writer, n node.Node) {
nn := n.(*stmt.AltWhile)
io.WriteString(o, "while (")
Print(o, nn.Cond)
io.WriteString(o, ") :\n")
Print(o, nn.Stmt)
io.WriteString(o, "endwhile;\n")
}
func printStmtCase(o io.Writer, n node.Node) {
nn := n.(*stmt.Case)
io.WriteString(o, "case ")
Print(o, nn.Cond)
io.WriteString(o, ":\n")
printNodes(o, nn.Stmts)
}
func printStmtStmtList(o io.Writer, n node.Node) {
nn := n.(*stmt.StmtList)
printNodes(o, nn.Stmts)
}
func printStmtExpression(o io.Writer, n node.Node) {
nn := n.(*stmt.Expression)
Print(o, nn.Expr)
}

View File

@ -11,6 +11,7 @@ import (
"github.com/z7zmey/php-parser/node/expr/cast"
"github.com/z7zmey/php-parser/node/name"
"github.com/z7zmey/php-parser/node/scalar"
"github.com/z7zmey/php-parser/node/stmt"
"github.com/z7zmey/php-parser/printer"
"github.com/z7zmey/php-parser/walker"
)
@ -1816,3 +1817,248 @@ func TestPrintYieldFull(t *testing.T) {
t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
}
}
// stmt
func TestPrintAltElseIf(t *testing.T) {
o := bytes.NewBufferString("")
printer.Print(o, &stmt.AltElseIf{
Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
Stmt: &stmt.StmtList{
Stmts: []node.Node{
&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}}},
},
},
})
expected := "elseif ($a) :\n$b;\n"
actual := o.String()
if expected != actual {
t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
}
}
func TestPrintAltElse(t *testing.T) {
o := bytes.NewBufferString("")
printer.Print(o, &stmt.AltElse{
Stmt: &stmt.StmtList{
Stmts: []node.Node{
&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}}},
},
},
})
expected := "else :\n$b;\n"
actual := o.String()
if expected != actual {
t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
}
}
func TestPrintAltFor(t *testing.T) {
o := bytes.NewBufferString("")
printer.Print(o, &stmt.AltFor{
Init: []node.Node{
&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}}},
},
Cond: []node.Node{
&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}}},
},
Loop: []node.Node{
&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "c"}}},
},
Stmt: &stmt.StmtList{
Stmts: []node.Node{
&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "d"}}},
},
},
})
expected := "for ($a; $b; $c) :\n$d;\nendfor;\n"
actual := o.String()
if expected != actual {
t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
}
}
func TestPrintAltForeach(t *testing.T) {
o := bytes.NewBufferString("")
printer.Print(o, &stmt.AltForeach{
ByRef: true,
Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
Key: &expr.Variable{VarName: &node.Identifier{Value: "key"}},
Variable: &expr.Variable{VarName: &node.Identifier{Value: "val"}},
Stmt: &stmt.StmtList{
Stmts: []node.Node{
&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "d"}}},
},
},
})
expected := "foreach ($var as $key => &$val) :\n$d;\nendforeach;\n"
actual := o.String()
if expected != actual {
t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
}
}
func TestPrintAltIf(t *testing.T) {
o := bytes.NewBufferString("")
printer.Print(o, &stmt.AltIf{
Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
Stmt: &stmt.StmtList{
Stmts: []node.Node{
&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "d"}}},
},
},
ElseIf: []node.Node{
&stmt.AltElseIf{
Cond: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
Stmt: &stmt.StmtList{
Stmts: []node.Node{
&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}}},
},
},
},
&stmt.AltElseIf{
Cond: &expr.Variable{VarName: &node.Identifier{Value: "c"}},
Stmt: &stmt.StmtList{},
},
},
Else: &stmt.AltElse{
Stmt: &stmt.StmtList{
Stmts: []node.Node{
&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}}},
},
},
},
})
expected := `if ($a) :
$d;
elseif ($b) :
$b;
elseif ($c) :
else :
$b;
endif;
`
actual := o.String()
if expected != actual {
t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
}
}
func TestPrintStmtAltSwitch(t *testing.T) {
o := bytes.NewBufferString("")
printer.Print(o, &stmt.AltSwitch{
Cond: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
Cases: []node.Node{
&stmt.Case{
Cond: &scalar.String{Value: "a"},
Stmts: []node.Node{
&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}}},
},
},
&stmt.Case{
Cond: &scalar.String{Value: "b"},
Stmts: []node.Node{
&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}}},
},
},
},
})
expected := `switch ($var) :
case 'a':
$a;
case 'b':
$b;
endswitch;
`
actual := o.String()
if expected != actual {
t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
}
}
func TestPrintAltWhile(t *testing.T) {
o := bytes.NewBufferString("")
printer.Print(o, &stmt.AltWhile{
Cond: &stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}}},
Stmt: &stmt.StmtList{
Stmts: []node.Node{
&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}}},
},
},
})
expected := "while ($a) :\n$b;\nendwhile;\n"
actual := o.String()
if expected != actual {
t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
}
}
func TestPrintStmtCase(t *testing.T) {
o := bytes.NewBufferString("")
printer.Print(o, &stmt.Case{
Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
Stmts: []node.Node{
&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}}},
},
})
expected := "case $a:\n$a;\n"
actual := o.String()
if expected != actual {
t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
}
}
func TestPrintStmtList(t *testing.T) {
o := bytes.NewBufferString("")
printer.Print(o, &stmt.StmtList{
Stmts: []node.Node{
&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}}},
&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}}},
},
})
expected := "$a;\n$b;\n"
actual := o.String()
if expected != actual {
t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
}
}
func TestPrintExpression(t *testing.T) {
o := bytes.NewBufferString("")
printer.Print(o, &stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}}})
expected := "$a"
actual := o.String()
if expected != actual {
t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
}
}