[refactoring] update ast structure of "Foreach" node

This commit is contained in:
Vadym Slizov 2020-09-14 18:36:55 +03:00
parent 62fc16da97
commit 69bc0af2be
19 changed files with 179 additions and 322 deletions

View File

@ -6431,7 +6431,7 @@ func TestStmtForeach_Alt(t *testing.T) {
}, },
}, },
Stmts: []ast.Vertex{ Stmts: []ast.Vertex{
&ast.StmtAltForeach{ &ast.StmtForeach{
Node: ast.Node{ Node: ast.Node{
Position: &position.Position{ Position: &position.Position{
StartLine: 1, StartLine: 1,
@ -6440,6 +6440,7 @@ func TestStmtForeach_Alt(t *testing.T) {
EndPos: 35, EndPos: 35,
}, },
}, },
Alt: true,
Expr: &ast.ExprVariable{ Expr: &ast.ExprVariable{
Node: ast.Node{ Node: ast.Node{
Position: &position.Position{ Position: &position.Position{

BIN
internal/php5/php5.go generated

Binary file not shown.

View File

@ -1094,79 +1094,39 @@ unticked_statement:
} }
| T_FOREACH '(' variable T_AS foreach_variable foreach_optional_arg ')' foreach_statement | T_FOREACH '(' variable T_AS foreach_variable foreach_optional_arg ')' foreach_statement
{ {
$8.(*ast.StmtForeach).ForeachTkn = $1
$8.(*ast.StmtForeach).OpenParenthesisTkn = $2
$8.(*ast.StmtForeach).Expr = $3
$8.(*ast.StmtForeach).AsTkn = $4
if $6 == nil { if $6 == nil {
switch n := $8.(type) { $8.(*ast.StmtForeach).Var = $5
case *ast.StmtForeach :
n.Expr = $3
n.Var = $5
case *ast.StmtAltForeach :
n.Expr = $3
n.Var = $5
}
} else { } else {
switch n := $8.(type) { $8.(*ast.StmtForeach).Key = $5
case *ast.StmtForeach : $8.(*ast.StmtForeach).DoubleArrowTkn = $6.(*ast.StmtForeach).DoubleArrowTkn
n.Expr = $3 $8.(*ast.StmtForeach).Var = $6.(*ast.StmtForeach).Var
n.Key = $5
n.Var = $6
case *ast.StmtAltForeach :
n.Expr = $3
n.Key = $5
n.Var = $6
}
} }
$8.(*ast.StmtForeach).CloseParenthesisTkn = $7
$8.(*ast.StmtForeach).Node.Position = position.NewTokenNodePosition($1, $8)
$$ = $8 $$ = $8
// save position
$$.GetNode().Position = position.NewTokenNodePosition($1, $8)
// save comments
yylex.(*Parser).setFreeFloating($$, token.Start, $1.SkippedTokens)
yylex.(*Parser).setFreeFloating($$, token.Foreach, $2.SkippedTokens)
yylex.(*Parser).setFreeFloating($$, token.Expr, $4.SkippedTokens)
if $6 != nil {
yylex.(*Parser).setFreeFloatingTokens($$, token.Key, $6.GetNode().Tokens[token.Key]); delete($6.GetNode().Tokens, token.Key)
}
yylex.(*Parser).setFreeFloating($$, token.Var, $7.SkippedTokens)
} }
| T_FOREACH '(' expr_without_variable T_AS foreach_variable foreach_optional_arg ')' foreach_statement | T_FOREACH '(' expr_without_variable T_AS foreach_variable foreach_optional_arg ')' foreach_statement
{ {
$8.(*ast.StmtForeach).ForeachTkn = $1
$8.(*ast.StmtForeach).OpenParenthesisTkn = $2
$8.(*ast.StmtForeach).Expr = $3
$8.(*ast.StmtForeach).AsTkn = $4
if $6 == nil { if $6 == nil {
switch n := $8.(type) { $8.(*ast.StmtForeach).Var = $5
case *ast.StmtForeach :
n.Expr = $3
n.Var = $5
case *ast.StmtAltForeach :
n.Expr = $3
n.Var = $5
}
} else { } else {
switch n := $8.(type) { $8.(*ast.StmtForeach).Key = $5
case *ast.StmtForeach : $8.(*ast.StmtForeach).DoubleArrowTkn = $6.(*ast.StmtForeach).DoubleArrowTkn
n.Expr = $3 $8.(*ast.StmtForeach).Var = $6.(*ast.StmtForeach).Var
n.Key = $5
n.Var = $6
case *ast.StmtAltForeach :
n.Expr = $3
n.Key = $5
n.Var = $6
}
} }
$8.(*ast.StmtForeach).CloseParenthesisTkn = $7
$8.(*ast.StmtForeach).Node.Position = position.NewTokenNodePosition($1, $8)
// save position
$$ = $8 $$ = $8
$$.GetNode().Position = position.NewTokenNodePosition($1, $8)
// save comments
yylex.(*Parser).setFreeFloating($$, token.Start, $1.SkippedTokens)
yylex.(*Parser).setFreeFloating($$, token.Foreach, $2.SkippedTokens)
yylex.(*Parser).setFreeFloating($$, token.Expr, $4.SkippedTokens)
if $6 != nil {
yylex.(*Parser).setFreeFloatingTokens($$, token.Key, $6.GetNode().Tokens[token.Key]); delete($6.GetNode().Tokens, token.Key)
}
yylex.(*Parser).setFreeFloating($$, token.Var, $7.SkippedTokens)
} }
| T_DECLARE '(' declare_list ')' declare_statement | T_DECLARE '(' declare_list ')' declare_statement
{ {
@ -1586,10 +1546,10 @@ foreach_optional_arg:
} }
| T_DOUBLE_ARROW foreach_variable | T_DOUBLE_ARROW foreach_variable
{ {
$$ = $2 $$ = &ast.StmtForeach{
DoubleArrowTkn: $1,
// save comments Var: $2,
yylex.(*Parser).setFreeFloating($$, token.Key, $1.SkippedTokens) }
} }
; ;
@ -1655,29 +1615,30 @@ for_statement:
foreach_statement: foreach_statement:
statement statement
{ {
$$ = &ast.StmtForeach{ast.Node{}, nil, nil, nil, $1} $$ = &ast.StmtForeach{
Node: ast.Node{
// save position Position: position.NewNodePosition($1),
$$.GetNode().Position = position.NewNodePosition($1) },
Stmt: $1,
}
} }
| ':' inner_statement_list T_ENDFOREACH ';' | ':' inner_statement_list T_ENDFOREACH ';'
{ {
stmtList := &ast.StmtStmtList{ $$ = &ast.StmtForeach{
Node: ast.Node{ Node: ast.Node{
Position: position.NewNodeListPosition($2), Position: position.NewTokensPosition($1, $4),
}, },
Stmts: $2, Alt: true,
ColonTkn: $1,
Stmt: &ast.StmtStmtList{
Node: ast.Node{
Position: position.NewNodeListPosition($2),
},
Stmts: $2,
},
EndForeachTkn: $3,
SemiColonTkn: $4,
} }
$$ = &ast.StmtAltForeach{ast.Node{}, nil, nil, nil, stmtList}
// save position
$$.GetNode().Position = position.NewTokensPosition($1, $4)
// save comments
yylex.(*Parser).setFreeFloating($$, token.Cond, $1.SkippedTokens)
yylex.(*Parser).setFreeFloating($$, token.Stmts, $3.SkippedTokens)
yylex.(*Parser).setFreeFloating($$, token.AltEnd, $4.SkippedTokens)
yylex.(*Parser).setToken($$, token.SemiColon, $4.SkippedTokens)
} }
; ;

View File

@ -4705,7 +4705,7 @@ func TestPhp5(t *testing.T) {
Stmts: []ast.Vertex{}, Stmts: []ast.Vertex{},
}, },
}, },
&ast.StmtAltForeach{ &ast.StmtForeach{
Node: ast.Node{ Node: ast.Node{
Position: &position.Position{ Position: &position.Position{
StartLine: 81, StartLine: 81,
@ -4714,6 +4714,7 @@ func TestPhp5(t *testing.T) {
EndPos: 1762, EndPos: 1762,
}, },
}, },
Alt: true,
Expr: &ast.ExprVariable{ Expr: &ast.ExprVariable{
Node: ast.Node{ Node: ast.Node{
Position: &position.Position{ Position: &position.Position{

View File

@ -7028,7 +7028,7 @@ func TestStmtForeach_Alt(t *testing.T) {
}, },
}, },
Stmts: []ast.Vertex{ Stmts: []ast.Vertex{
&ast.StmtAltForeach{ &ast.StmtForeach{
Node: ast.Node{ Node: ast.Node{
Position: &position.Position{ Position: &position.Position{
StartLine: 1, StartLine: 1,
@ -7037,6 +7037,7 @@ func TestStmtForeach_Alt(t *testing.T) {
EndPos: 35, EndPos: 35,
}, },
}, },
Alt: true,
Expr: &ast.ExprVariable{ Expr: &ast.ExprVariable{
Node: ast.Node{ Node: ast.Node{
Position: &position.Position{ Position: &position.Position{

BIN
internal/php7/php7.go generated

Binary file not shown.

View File

@ -1010,50 +1010,29 @@ statement:
} }
| T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement
{ {
switch n := $7.(type) { $7.(*ast.StmtForeach).ForeachTkn = $1
case *ast.StmtForeach : $7.(*ast.StmtForeach).OpenParenthesisTkn = $2
n.Expr = $3 $7.(*ast.StmtForeach).Expr = $3
n.Var = $5 $7.(*ast.StmtForeach).AsTkn = $4
case *ast.StmtAltForeach : $7.(*ast.StmtForeach).Var = $5
n.Expr = $3 $7.(*ast.StmtForeach).CloseParenthesisTkn = $6
n.Var = $5 $7.(*ast.StmtForeach).Node.Position = position.NewTokenNodePosition($1, $7)
}
$$ = $7 $$ = $7
// save position
$$.GetNode().Position = position.NewTokenNodePosition($1, $7)
// save comments
yylex.(*Parser).setFreeFloating($$, token.Start, $1.SkippedTokens)
yylex.(*Parser).setFreeFloating($$, token.Foreach, $2.SkippedTokens)
yylex.(*Parser).setFreeFloating($$, token.Expr, $4.SkippedTokens)
yylex.(*Parser).setFreeFloating($$, token.Var, $6.SkippedTokens)
} }
| T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement
{ {
switch n := $9.(type) { $9.(*ast.StmtForeach).ForeachTkn = $1
case *ast.StmtForeach : $9.(*ast.StmtForeach).OpenParenthesisTkn = $2
n.Expr = $3 $9.(*ast.StmtForeach).Expr = $3
n.Key = $5 $9.(*ast.StmtForeach).AsTkn = $4
n.Var = $7 $9.(*ast.StmtForeach).Key = $5
case *ast.StmtAltForeach : $9.(*ast.StmtForeach).DoubleArrowTkn = $6
n.Expr = $3 $9.(*ast.StmtForeach).Var = $7
n.Key = $5 $9.(*ast.StmtForeach).CloseParenthesisTkn = $8
n.Var = $7 $9.(*ast.StmtForeach).Node.Position = position.NewTokenNodePosition($1, $9)
}
$$ = $9 $$ = $9
// save position
$$.GetNode().Position = position.NewTokenNodePosition($1, $9)
// save comments
yylex.(*Parser).setFreeFloating($$, token.Start, $1.SkippedTokens)
yylex.(*Parser).setFreeFloating($$, token.Foreach, $2.SkippedTokens)
yylex.(*Parser).setFreeFloating($$, token.Expr, $4.SkippedTokens)
yylex.(*Parser).setFreeFloating($$, token.Key, $6.SkippedTokens)
yylex.(*Parser).setFreeFloating($$, token.Var, $8.SkippedTokens)
} }
| T_DECLARE '(' const_list ')' declare_statement | T_DECLARE '(' const_list ')' declare_statement
{ {
@ -1500,29 +1479,30 @@ for_statement:
foreach_statement: foreach_statement:
statement statement
{ {
$$ = &ast.StmtForeach{ast.Node{}, nil, nil, nil, $1} $$ = &ast.StmtForeach{
Node: ast.Node{
// save position Position: position.NewNodePosition($1),
$$.GetNode().Position = position.NewNodePosition($1) },
Stmt: $1,
}
} }
| ':' inner_statement_list T_ENDFOREACH ';' | ':' inner_statement_list T_ENDFOREACH ';'
{ {
stmtList := &ast.StmtStmtList{ $$ = &ast.StmtForeach{
Node: ast.Node{ Node: ast.Node{
Position: position.NewNodeListPosition($2), Position: position.NewTokensPosition($1, $4),
}, },
Stmts: $2, Alt: true,
ColonTkn: $1,
Stmt: &ast.StmtStmtList{
Node: ast.Node{
Position: position.NewNodeListPosition($2),
},
Stmts: $2,
},
EndForeachTkn: $3,
SemiColonTkn: $4,
} }
$$ = &ast.StmtAltForeach{ast.Node{}, nil, nil, nil, stmtList}
// save position
$$.GetNode().Position = position.NewTokensPosition($1, $4)
// save comments
yylex.(*Parser).setFreeFloating($$, token.Cond, $1.SkippedTokens)
yylex.(*Parser).setFreeFloating($$, token.Stmts, $3.SkippedTokens)
yylex.(*Parser).setFreeFloating($$, token.AltEnd, $4.SkippedTokens)
yylex.(*Parser).setToken($$, token.SemiColon, $4.SkippedTokens)
} }
; ;

View File

@ -5590,7 +5590,7 @@ func TestPhp7(t *testing.T) {
Stmts: []ast.Vertex{}, Stmts: []ast.Vertex{},
}, },
}, },
&ast.StmtAltForeach{ &ast.StmtForeach{
Node: ast.Node{ Node: ast.Node{
Position: &position.Position{ Position: &position.Position{
StartLine: 94, StartLine: 94,
@ -5599,6 +5599,7 @@ func TestPhp7(t *testing.T) {
EndPos: 2014, EndPos: 2014,
}, },
}, },
Alt: true,
Expr: &ast.ExprVariable{ Expr: &ast.ExprVariable{
Node: ast.Node{ Node: ast.Node{
Position: &position.Position{ Position: &position.Position{

View File

@ -27,7 +27,6 @@ type NodeVisitor interface {
ArgumentList(n *ArgumentList) ArgumentList(n *ArgumentList)
Argument(n *Argument) Argument(n *Argument)
StmtAltForeach(n *StmtAltForeach)
StmtBreak(n *StmtBreak) StmtBreak(n *StmtBreak)
StmtCase(n *StmtCase) StmtCase(n *StmtCase)
StmtCatch(n *StmtCatch) StmtCatch(n *StmtCatch)

View File

@ -175,19 +175,6 @@ func (n *ScalarString) Accept(v NodeVisitor) {
v.ScalarString(n) v.ScalarString(n)
} }
// StmtAltForeach node
type StmtAltForeach struct {
Node
Expr Vertex
Key Vertex
Var Vertex
Stmt Vertex
}
func (n *StmtAltForeach) Accept(v NodeVisitor) {
v.StmtAltForeach(n)
}
// StmtBreak node // StmtBreak node
type StmtBreak struct { type StmtBreak struct {
Node Node
@ -452,10 +439,19 @@ func (n *StmtFor) Accept(v NodeVisitor) {
// StmtForeach node // StmtForeach node
type StmtForeach struct { type StmtForeach struct {
Node Node
Expr Vertex Alt bool
Key Vertex ForeachTkn *token.Token
Var Vertex OpenParenthesisTkn *token.Token
Stmt Vertex Expr Vertex
AsTkn *token.Token
Key Vertex
DoubleArrowTkn *token.Token
Var Vertex
CloseParenthesisTkn *token.Token
ColonTkn *token.Token
Stmt Vertex
EndForeachTkn *token.Token
SemiColonTkn *token.Token
} }
func (n *StmtForeach) Accept(v NodeVisitor) { func (n *StmtForeach) Accept(v NodeVisitor) {

View File

@ -119,33 +119,6 @@ func (t *DFS) Traverse(n ast.Vertex) {
t.Traverse(nn.Expr) t.Traverse(nn.Expr)
t.visitor.Leave("Expr", true) t.visitor.Leave("Expr", true)
} }
case *ast.StmtAltForeach:
if nn == nil {
return
}
if !t.visitor.EnterNode(nn) {
return
}
if nn.Expr != nil {
t.visitor.Enter("Expr", true)
t.Traverse(nn.Expr)
t.visitor.Leave("Expr", true)
}
if nn.Key != nil {
t.visitor.Enter("Key", true)
t.Traverse(nn.Key)
t.visitor.Leave("Key", true)
}
if nn.Var != nil {
t.visitor.Enter("Var", true)
t.Traverse(nn.Var)
t.visitor.Leave("Var", true)
}
if nn.Stmt != nil {
t.visitor.Enter("Stmt", true)
t.Traverse(nn.Stmt)
t.visitor.Leave("Stmt", true)
}
case *ast.StmtBreak: case *ast.StmtBreak:
if nn == nil { if nn == nil {
return return

View File

@ -252,12 +252,6 @@ func (v *Dump) Argument(n *ast.Argument) {
} }
} }
func (v *Dump) StmtAltForeach(n *ast.StmtAltForeach) {
v.printIndentIfNotSingle(v.indent - 1)
v.print("&ast.StmtAltForeach{\n")
v.printNode(n.GetNode())
}
func (v *Dump) StmtBreak(n *ast.StmtBreak) { func (v *Dump) StmtBreak(n *ast.StmtBreak) {
v.printIndentIfNotSingle(v.indent - 1) v.printIndentIfNotSingle(v.indent - 1)
v.print("&ast.StmtBreak{\n") v.print("&ast.StmtBreak{\n")

View File

@ -111,26 +111,6 @@ func (v *FilterParserNodes) StmtReturn(n *ast.StmtReturn) {
} }
} }
func (v *FilterParserNodes) StmtForeach(n *ast.StmtForeach) {
for {
if nn, ok := n.Expr.(*ast.ParserBrackets); ok {
n.Expr = nn.Child
} else {
break
}
}
}
func (v *FilterParserNodes) StmtAltForeach(n *ast.StmtAltForeach) {
for {
if nn, ok := n.Expr.(*ast.ParserBrackets); ok {
n.Expr = nn.Child
} else {
break
}
}
}
func (v *FilterParserNodes) ExprYield(n *ast.ExprYield) { func (v *FilterParserNodes) ExprYield(n *ast.ExprYield) {
for { for {
if nn, ok := n.Key.(*ast.ParserBrackets); ok { if nn, ok := n.Key.(*ast.ParserBrackets); ok {

View File

@ -213,3 +213,14 @@ func (v *FilterTokens) StmtUnset(n *ast.StmtUnset) {
n.SemiColonTkn = nil n.SemiColonTkn = nil
n.SemiColonTkn = nil n.SemiColonTkn = nil
} }
func (v *FilterTokens) StmtForeach(n *ast.StmtForeach) {
n.ForeachTkn = nil
n.OpenParenthesisTkn = nil
n.AsTkn = nil
n.DoubleArrowTkn = nil
n.CloseParenthesisTkn = nil
n.ColonTkn = nil
n.EndForeachTkn = nil
n.SemiColonTkn = nil
}

View File

@ -54,10 +54,6 @@ func (v *Null) Argument(_ *ast.Argument) {
// do nothing // do nothing
} }
func (v *Null) StmtAltForeach(_ *ast.StmtAltForeach) {
// do nothing
}
func (v *Null) StmtBreak(_ *ast.StmtBreak) { func (v *Null) StmtBreak(_ *ast.StmtBreak) {
// do nothing // do nothing
} }

View File

@ -297,8 +297,6 @@ func (p *PrettyPrinter) printNode(n ast.Vertex) {
// stmt // stmt
case *ast.StmtAltForeach:
p.printStmtAltForeach(n)
case *ast.StmtBreak: case *ast.StmtBreak:
p.printStmtBreak(n) p.printStmtBreak(n)
case *ast.StmtCase: case *ast.StmtCase:
@ -1359,30 +1357,6 @@ func (p *PrettyPrinter) printStmtAltElse(n ast.Vertex) {
} }
} }
func (p *PrettyPrinter) printStmtAltForeach(n ast.Vertex) {
nn := n.(*ast.StmtAltForeach)
io.WriteString(p.w, "foreach (")
p.Print(nn.Expr)
io.WriteString(p.w, " as ")
if nn.Key != nil {
p.Print(nn.Key)
io.WriteString(p.w, " => ")
}
p.Print(nn.Var)
io.WriteString(p.w, ") :\n")
s := nn.Stmt.(*ast.StmtStmtList)
p.printNodes(s.Stmts)
io.WriteString(p.w, "\n")
p.printIndent()
io.WriteString(p.w, "endforeach;")
}
func (p *PrettyPrinter) printStmtAltIf(n ast.Vertex) { func (p *PrettyPrinter) printStmtAltIf(n ast.Vertex) {
nn := n.(*ast.StmtIf) nn := n.(*ast.StmtIf)
@ -1749,6 +1723,11 @@ func (p *PrettyPrinter) printStmtAltFor(n ast.Vertex) {
func (p *PrettyPrinter) printStmtForeach(n ast.Vertex) { func (p *PrettyPrinter) printStmtForeach(n ast.Vertex) {
nn := n.(*ast.StmtForeach) nn := n.(*ast.StmtForeach)
if nn.Alt {
p.printStmtAltForeach(n)
return
}
io.WriteString(p.w, "foreach (") io.WriteString(p.w, "foreach (")
p.Print(nn.Expr) p.Print(nn.Expr)
io.WriteString(p.w, " as ") io.WriteString(p.w, " as ")
@ -1777,6 +1756,30 @@ func (p *PrettyPrinter) printStmtForeach(n ast.Vertex) {
} }
} }
func (p *PrettyPrinter) printStmtAltForeach(n ast.Vertex) {
nn := n.(*ast.StmtForeach)
io.WriteString(p.w, "foreach (")
p.Print(nn.Expr)
io.WriteString(p.w, " as ")
if nn.Key != nil {
p.Print(nn.Key)
io.WriteString(p.w, " => ")
}
p.Print(nn.Var)
io.WriteString(p.w, ") :\n")
s := nn.Stmt.(*ast.StmtStmtList)
p.printNodes(s.Stmts)
io.WriteString(p.w, "\n")
p.printIndent()
io.WriteString(p.w, "endforeach;")
}
func (p *PrettyPrinter) printStmtFunction(n ast.Vertex) { func (p *PrettyPrinter) printStmtFunction(n ast.Vertex) {
nn := n.(*ast.StmtFunction) nn := n.(*ast.StmtFunction)

View File

@ -2210,7 +2210,8 @@ func TestPrintAltForeach(t *testing.T) {
p := printer.NewPrettyPrinter(o, " ") p := printer.NewPrettyPrinter(o, " ")
p.Print(&ast.StmtNamespace{ p.Print(&ast.StmtNamespace{
Stmts: []ast.Vertex{ Stmts: []ast.Vertex{
&ast.StmtAltForeach{ &ast.StmtForeach{
Alt: true,
Expr: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("var")}}, Expr: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("var")}},
Key: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("key")}}, Key: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("key")}},
Var: &ast.ExprReference{Var: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("val")}}}, Var: &ast.ExprReference{Var: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("val")}}},

View File

@ -386,8 +386,6 @@ func (p *Printer) printNode(n ast.Vertex) {
// stmt // stmt
case *ast.StmtAltForeach:
p.printStmtAltForeach(n)
case *ast.StmtBreak: case *ast.StmtBreak:
p.printStmtBreak(n) p.printStmtBreak(n)
case *ast.StmtCase: case *ast.StmtCase:
@ -1996,54 +1994,6 @@ func (p *Printer) printExprYield(n ast.Vertex) {
// smtm // smtm
func (p *Printer) printStmtAltForeach(n ast.Vertex) {
nn := n.(*ast.StmtAltForeach)
p.printFreeFloating(nn, token.Start)
p.write([]byte("foreach"))
p.printFreeFloating(nn, token.Foreach)
p.write([]byte("("))
p.Print(nn.Expr)
p.printFreeFloating(nn, token.Expr)
if nn.GetNode().Tokens.IsEmpty() {
p.write([]byte(" "))
}
p.write([]byte("as"))
if nn.Key != nil {
if nn.Key.GetNode().Tokens.IsEmpty() {
p.write([]byte(" "))
}
p.Print(nn.Key)
p.printFreeFloating(nn, token.Key)
p.write([]byte("=>"))
} else {
if nn.Var.GetNode().Tokens.IsEmpty() {
p.write([]byte(" "))
}
}
p.Print(nn.Var)
p.printFreeFloating(nn, token.Var)
p.write([]byte(")"))
p.printFreeFloating(nn, token.Cond)
p.write([]byte(":"))
s := nn.Stmt.(*ast.StmtStmtList)
p.printNodes(s.Stmts)
p.printFreeFloating(nn, token.Stmts)
p.write([]byte("endforeach"))
p.printFreeFloating(nn, token.AltEnd)
p.printFreeFloating(nn, token.SemiColon)
if nn.GetNode().Tokens.IsEmpty() {
p.write([]byte(";"))
}
p.printFreeFloating(nn, token.End)
}
func (p *Printer) printStmtBreak(n *ast.StmtBreak) { func (p *Printer) printStmtBreak(n *ast.StmtBreak) {
p.printToken(n.BreakTkn, "break") p.printToken(n.BreakTkn, "break")
@ -2407,42 +2357,50 @@ func (p *Printer) printStmtAltFor(n *ast.StmtFor) {
p.printToken(n.SemiColonTkn, ";") p.printToken(n.SemiColonTkn, ";")
} }
func (p *Printer) printStmtForeach(n ast.Vertex) { func (p *Printer) printStmtForeach(n *ast.StmtForeach) {
nn := n.(*ast.StmtForeach) if n.Alt {
p.printFreeFloating(nn, token.Start) p.printStmtAltForeach(n)
return
p.write([]byte("foreach"))
p.printFreeFloating(nn, token.Foreach)
p.write([]byte("("))
p.Print(nn.Expr)
p.printFreeFloating(nn, token.Expr)
if nn.GetNode().Tokens.IsEmpty() {
p.write([]byte(" "))
} }
p.write([]byte("as")) p.printToken(n.ForeachTkn, "foreach")
p.printToken(n.OpenParenthesisTkn, "(")
p.Print(n.Expr)
p.bufStart = " "
p.printToken(n.AsTkn, "as")
p.bufStart = " "
if n.Key != nil {
p.Print(n.Key)
p.printToken(n.DoubleArrowTkn, "=>")
}
p.Print(n.Var)
p.printToken(n.CloseParenthesisTkn, ")")
p.Print(n.Stmt)
}
if nn.Key != nil { func (p *Printer) printStmtAltForeach(n *ast.StmtForeach) {
if nn.Key.GetNode().Tokens.IsEmpty() { p.printToken(n.ForeachTkn, "foreach")
p.write([]byte(" ")) p.printToken(n.OpenParenthesisTkn, "(")
} p.Print(n.Expr)
p.Print(nn.Key) p.bufStart = " "
p.printFreeFloating(nn, token.Key) p.printToken(n.AsTkn, "as")
p.write([]byte("=>")) p.bufStart = " "
if n.Key != nil {
p.Print(n.Key)
p.printToken(n.DoubleArrowTkn, "=>")
}
p.Print(n.Var)
p.printToken(n.CloseParenthesisTkn, ")")
p.printToken(n.ColonTkn, ":")
if stmtList, ok := n.Stmt.(*ast.StmtStmtList); ok {
p.printNodes(stmtList.Stmts)
} else { } else {
if nn.Var.GetNode().Tokens.IsEmpty() { p.Print(n.Stmt)
p.write([]byte(" "))
}
} }
p.Print(nn.Var)
p.printFreeFloating(nn, token.Var)
p.write([]byte(")")) p.printToken(n.EndForeachTkn, "endforeach")
p.printToken(n.SemiColonTkn, ";")
p.Print(nn.Stmt)
p.printFreeFloating(nn, token.End)
} }
func (p *Printer) printStmtFunction(n ast.Vertex) { func (p *Printer) printStmtFunction(n ast.Vertex) {

View File

@ -2667,7 +2667,8 @@ func TestPrinterPrintAltForeach(t *testing.T) {
o := bytes.NewBufferString("") o := bytes.NewBufferString("")
p := printer.NewPrinter(o) p := printer.NewPrinter(o)
p.Print(&ast.StmtAltForeach{ p.Print(&ast.StmtForeach{
Alt: true,
Expr: &ast.ExprVariable{ Expr: &ast.ExprVariable{
VarName: &ast.Identifier{Value: []byte("$var")}, VarName: &ast.Identifier{Value: []byte("$var")},
}, },