diff --git a/internal/php5/parser_test.go b/internal/php5/parser_test.go index 11e39da..0eb1d67 100644 --- a/internal/php5/parser_test.go +++ b/internal/php5/parser_test.go @@ -6431,7 +6431,7 @@ func TestStmtForeach_Alt(t *testing.T) { }, }, Stmts: []ast.Vertex{ - &ast.StmtAltForeach{ + &ast.StmtForeach{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, @@ -6440,6 +6440,7 @@ func TestStmtForeach_Alt(t *testing.T) { EndPos: 35, }, }, + Alt: true, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ diff --git a/internal/php5/php5.go b/internal/php5/php5.go index 324e992..498f6b5 100644 Binary files a/internal/php5/php5.go and b/internal/php5/php5.go differ diff --git a/internal/php5/php5.y b/internal/php5/php5.y index f599ddd..5fb516e 100644 --- a/internal/php5/php5.y +++ b/internal/php5/php5.y @@ -1094,79 +1094,39 @@ unticked_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 { - switch n := $8.(type) { - case *ast.StmtForeach : - n.Expr = $3 - n.Var = $5 - case *ast.StmtAltForeach : - n.Expr = $3 - n.Var = $5 - } + $8.(*ast.StmtForeach).Var = $5 } else { - switch n := $8.(type) { - case *ast.StmtForeach : - n.Expr = $3 - n.Key = $5 - n.Var = $6 - case *ast.StmtAltForeach : - n.Expr = $3 - n.Key = $5 - n.Var = $6 - } + $8.(*ast.StmtForeach).Key = $5 + $8.(*ast.StmtForeach).DoubleArrowTkn = $6.(*ast.StmtForeach).DoubleArrowTkn + $8.(*ast.StmtForeach).Var = $6.(*ast.StmtForeach).Var } + $8.(*ast.StmtForeach).CloseParenthesisTkn = $7 + $8.(*ast.StmtForeach).Node.Position = position.NewTokenNodePosition($1, $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 { + $8.(*ast.StmtForeach).ForeachTkn = $1 + $8.(*ast.StmtForeach).OpenParenthesisTkn = $2 + $8.(*ast.StmtForeach).Expr = $3 + $8.(*ast.StmtForeach).AsTkn = $4 if $6 == nil { - switch n := $8.(type) { - case *ast.StmtForeach : - n.Expr = $3 - n.Var = $5 - case *ast.StmtAltForeach : - n.Expr = $3 - n.Var = $5 - } + $8.(*ast.StmtForeach).Var = $5 } else { - switch n := $8.(type) { - case *ast.StmtForeach : - n.Expr = $3 - n.Key = $5 - n.Var = $6 - case *ast.StmtAltForeach : - n.Expr = $3 - n.Key = $5 - n.Var = $6 - } + $8.(*ast.StmtForeach).Key = $5 + $8.(*ast.StmtForeach).DoubleArrowTkn = $6.(*ast.StmtForeach).DoubleArrowTkn + $8.(*ast.StmtForeach).Var = $6.(*ast.StmtForeach).Var } + $8.(*ast.StmtForeach).CloseParenthesisTkn = $7 + $8.(*ast.StmtForeach).Node.Position = position.NewTokenNodePosition($1, $8) - // save position $$ = $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 { @@ -1586,10 +1546,10 @@ foreach_optional_arg: } | T_DOUBLE_ARROW foreach_variable { - $$ = $2 - - // save comments - yylex.(*Parser).setFreeFloating($$, token.Key, $1.SkippedTokens) + $$ = &ast.StmtForeach{ + DoubleArrowTkn: $1, + Var: $2, + } } ; @@ -1655,29 +1615,30 @@ for_statement: foreach_statement: statement { - $$ = &ast.StmtForeach{ast.Node{}, nil, nil, nil, $1} - - // save position - $$.GetNode().Position = position.NewNodePosition($1) + $$ = &ast.StmtForeach{ + Node: ast.Node{ + Position: position.NewNodePosition($1), + }, + Stmt: $1, + } } | ':' inner_statement_list T_ENDFOREACH ';' { - stmtList := &ast.StmtStmtList{ + $$ = &ast.StmtForeach{ 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) } ; diff --git a/internal/php5/php5_test.go b/internal/php5/php5_test.go index 8537e6c..406f860 100644 --- a/internal/php5/php5_test.go +++ b/internal/php5/php5_test.go @@ -4705,7 +4705,7 @@ func TestPhp5(t *testing.T) { Stmts: []ast.Vertex{}, }, }, - &ast.StmtAltForeach{ + &ast.StmtForeach{ Node: ast.Node{ Position: &position.Position{ StartLine: 81, @@ -4714,6 +4714,7 @@ func TestPhp5(t *testing.T) { EndPos: 1762, }, }, + Alt: true, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ diff --git a/internal/php7/parser_test.go b/internal/php7/parser_test.go index 5efe233..94835e1 100644 --- a/internal/php7/parser_test.go +++ b/internal/php7/parser_test.go @@ -7028,7 +7028,7 @@ func TestStmtForeach_Alt(t *testing.T) { }, }, Stmts: []ast.Vertex{ - &ast.StmtAltForeach{ + &ast.StmtForeach{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, @@ -7037,6 +7037,7 @@ func TestStmtForeach_Alt(t *testing.T) { EndPos: 35, }, }, + Alt: true, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ diff --git a/internal/php7/php7.go b/internal/php7/php7.go index 56d0fc9..4b801a5 100644 Binary files a/internal/php7/php7.go and b/internal/php7/php7.go differ diff --git a/internal/php7/php7.y b/internal/php7/php7.y index 8a2dfb4..2d9825a 100644 --- a/internal/php7/php7.y +++ b/internal/php7/php7.y @@ -1010,50 +1010,29 @@ statement: } | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement { - switch n := $7.(type) { - case *ast.StmtForeach : - n.Expr = $3 - n.Var = $5 - case *ast.StmtAltForeach : - n.Expr = $3 - n.Var = $5 - } + $7.(*ast.StmtForeach).ForeachTkn = $1 + $7.(*ast.StmtForeach).OpenParenthesisTkn = $2 + $7.(*ast.StmtForeach).Expr = $3 + $7.(*ast.StmtForeach).AsTkn = $4 + $7.(*ast.StmtForeach).Var = $5 + $7.(*ast.StmtForeach).CloseParenthesisTkn = $6 + $7.(*ast.StmtForeach).Node.Position = position.NewTokenNodePosition($1, $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 { - switch n := $9.(type) { - case *ast.StmtForeach : - n.Expr = $3 - n.Key = $5 - n.Var = $7 - case *ast.StmtAltForeach : - n.Expr = $3 - n.Key = $5 - n.Var = $7 - } + $9.(*ast.StmtForeach).ForeachTkn = $1 + $9.(*ast.StmtForeach).OpenParenthesisTkn = $2 + $9.(*ast.StmtForeach).Expr = $3 + $9.(*ast.StmtForeach).AsTkn = $4 + $9.(*ast.StmtForeach).Key = $5 + $9.(*ast.StmtForeach).DoubleArrowTkn = $6 + $9.(*ast.StmtForeach).Var = $7 + $9.(*ast.StmtForeach).CloseParenthesisTkn = $8 + $9.(*ast.StmtForeach).Node.Position = position.NewTokenNodePosition($1, $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 { @@ -1500,29 +1479,30 @@ for_statement: foreach_statement: statement { - $$ = &ast.StmtForeach{ast.Node{}, nil, nil, nil, $1} - - // save position - $$.GetNode().Position = position.NewNodePosition($1) + $$ = &ast.StmtForeach{ + Node: ast.Node{ + Position: position.NewNodePosition($1), + }, + Stmt: $1, + } } | ':' inner_statement_list T_ENDFOREACH ';' { - stmtList := &ast.StmtStmtList{ + $$ = &ast.StmtForeach{ 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) } ; diff --git a/internal/php7/php7_test.go b/internal/php7/php7_test.go index 06528b4..452a0a3 100644 --- a/internal/php7/php7_test.go +++ b/internal/php7/php7_test.go @@ -5590,7 +5590,7 @@ func TestPhp7(t *testing.T) { Stmts: []ast.Vertex{}, }, }, - &ast.StmtAltForeach{ + &ast.StmtForeach{ Node: ast.Node{ Position: &position.Position{ StartLine: 94, @@ -5599,6 +5599,7 @@ func TestPhp7(t *testing.T) { EndPos: 2014, }, }, + Alt: true, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ diff --git a/pkg/ast/ast.go b/pkg/ast/ast.go index 33713e7..aa2170a 100644 --- a/pkg/ast/ast.go +++ b/pkg/ast/ast.go @@ -27,7 +27,6 @@ type NodeVisitor interface { ArgumentList(n *ArgumentList) Argument(n *Argument) - StmtAltForeach(n *StmtAltForeach) StmtBreak(n *StmtBreak) StmtCase(n *StmtCase) StmtCatch(n *StmtCatch) diff --git a/pkg/ast/node.go b/pkg/ast/node.go index 50235a7..516019f 100644 --- a/pkg/ast/node.go +++ b/pkg/ast/node.go @@ -175,19 +175,6 @@ func (n *ScalarString) Accept(v NodeVisitor) { 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 type StmtBreak struct { Node @@ -452,10 +439,19 @@ func (n *StmtFor) Accept(v NodeVisitor) { // StmtForeach node type StmtForeach struct { Node - Expr Vertex - Key Vertex - Var Vertex - Stmt Vertex + Alt bool + ForeachTkn *token.Token + OpenParenthesisTkn *token.Token + 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) { diff --git a/pkg/ast/traverser/dfs.go b/pkg/ast/traverser/dfs.go index cca893c..615c682 100644 --- a/pkg/ast/traverser/dfs.go +++ b/pkg/ast/traverser/dfs.go @@ -119,33 +119,6 @@ func (t *DFS) Traverse(n ast.Vertex) { t.Traverse(nn.Expr) 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: if nn == nil { return diff --git a/pkg/ast/visitor/dump.go b/pkg/ast/visitor/dump.go index 5569a60..de06927 100644 --- a/pkg/ast/visitor/dump.go +++ b/pkg/ast/visitor/dump.go @@ -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) { v.printIndentIfNotSingle(v.indent - 1) v.print("&ast.StmtBreak{\n") diff --git a/pkg/ast/visitor/filter_parser_nodes.go b/pkg/ast/visitor/filter_parser_nodes.go index 0d7ce76..6ccd522 100644 --- a/pkg/ast/visitor/filter_parser_nodes.go +++ b/pkg/ast/visitor/filter_parser_nodes.go @@ -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) { for { if nn, ok := n.Key.(*ast.ParserBrackets); ok { diff --git a/pkg/ast/visitor/filter_tokens.go b/pkg/ast/visitor/filter_tokens.go index d3ad950..6c86b92 100644 --- a/pkg/ast/visitor/filter_tokens.go +++ b/pkg/ast/visitor/filter_tokens.go @@ -213,3 +213,14 @@ func (v *FilterTokens) StmtUnset(n *ast.StmtUnset) { 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 +} diff --git a/pkg/ast/visitor/null.go b/pkg/ast/visitor/null.go index 225a604..582033e 100644 --- a/pkg/ast/visitor/null.go +++ b/pkg/ast/visitor/null.go @@ -54,10 +54,6 @@ func (v *Null) Argument(_ *ast.Argument) { // do nothing } -func (v *Null) StmtAltForeach(_ *ast.StmtAltForeach) { - // do nothing -} - func (v *Null) StmtBreak(_ *ast.StmtBreak) { // do nothing } diff --git a/pkg/printer/pretty_printer.go b/pkg/printer/pretty_printer.go index 987655d..67d4571 100644 --- a/pkg/printer/pretty_printer.go +++ b/pkg/printer/pretty_printer.go @@ -297,8 +297,6 @@ func (p *PrettyPrinter) printNode(n ast.Vertex) { // stmt - case *ast.StmtAltForeach: - p.printStmtAltForeach(n) case *ast.StmtBreak: p.printStmtBreak(n) 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) { nn := n.(*ast.StmtIf) @@ -1749,6 +1723,11 @@ func (p *PrettyPrinter) printStmtAltFor(n ast.Vertex) { func (p *PrettyPrinter) printStmtForeach(n ast.Vertex) { nn := n.(*ast.StmtForeach) + if nn.Alt { + p.printStmtAltForeach(n) + return + } + io.WriteString(p.w, "foreach (") p.Print(nn.Expr) 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) { nn := n.(*ast.StmtFunction) diff --git a/pkg/printer/pretty_printer_test.go b/pkg/printer/pretty_printer_test.go index 54fcdd0..82ac6ef 100644 --- a/pkg/printer/pretty_printer_test.go +++ b/pkg/printer/pretty_printer_test.go @@ -2210,7 +2210,8 @@ func TestPrintAltForeach(t *testing.T) { p := printer.NewPrettyPrinter(o, " ") p.Print(&ast.StmtNamespace{ Stmts: []ast.Vertex{ - &ast.StmtAltForeach{ + &ast.StmtForeach{ + Alt: true, Expr: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("var")}}, Key: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("key")}}, Var: &ast.ExprReference{Var: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("val")}}}, diff --git a/pkg/printer/printer.go b/pkg/printer/printer.go index 0068785..b808de1 100644 --- a/pkg/printer/printer.go +++ b/pkg/printer/printer.go @@ -386,8 +386,6 @@ func (p *Printer) printNode(n ast.Vertex) { // stmt - case *ast.StmtAltForeach: - p.printStmtAltForeach(n) case *ast.StmtBreak: p.printStmtBreak(n) case *ast.StmtCase: @@ -1996,54 +1994,6 @@ func (p *Printer) printExprYield(n ast.Vertex) { // 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) { p.printToken(n.BreakTkn, "break") @@ -2407,42 +2357,50 @@ func (p *Printer) printStmtAltFor(n *ast.StmtFor) { p.printToken(n.SemiColonTkn, ";") } -func (p *Printer) printStmtForeach(n ast.Vertex) { - nn := n.(*ast.StmtForeach) - 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(" ")) +func (p *Printer) printStmtForeach(n *ast.StmtForeach) { + if n.Alt { + p.printStmtAltForeach(n) + return } - 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 { - if nn.Key.GetNode().Tokens.IsEmpty() { - p.write([]byte(" ")) - } - p.Print(nn.Key) - p.printFreeFloating(nn, token.Key) - p.write([]byte("=>")) +func (p *Printer) printStmtAltForeach(n *ast.StmtForeach) { + 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.printToken(n.ColonTkn, ":") + + if stmtList, ok := n.Stmt.(*ast.StmtStmtList); ok { + p.printNodes(stmtList.Stmts) } else { - if nn.Var.GetNode().Tokens.IsEmpty() { - p.write([]byte(" ")) - } + p.Print(n.Stmt) } - p.Print(nn.Var) - p.printFreeFloating(nn, token.Var) - p.write([]byte(")")) - - p.Print(nn.Stmt) - - p.printFreeFloating(nn, token.End) + p.printToken(n.EndForeachTkn, "endforeach") + p.printToken(n.SemiColonTkn, ";") } func (p *Printer) printStmtFunction(n ast.Vertex) { diff --git a/pkg/printer/printer_test.go b/pkg/printer/printer_test.go index de97168..8956574 100644 --- a/pkg/printer/printer_test.go +++ b/pkg/printer/printer_test.go @@ -2667,7 +2667,8 @@ func TestPrinterPrintAltForeach(t *testing.T) { o := bytes.NewBufferString("") p := printer.NewPrinter(o) - p.Print(&ast.StmtAltForeach{ + p.Print(&ast.StmtForeach{ + Alt: true, Expr: &ast.ExprVariable{ VarName: &ast.Identifier{Value: []byte("$var")}, },