diff --git a/internal/php5/parser_test.go b/internal/php5/parser_test.go index 725f642..1af3152 100644 --- a/internal/php5/parser_test.go +++ b/internal/php5/parser_test.go @@ -6141,7 +6141,7 @@ func TestStmtFor_Alt(t *testing.T) { }, }, Stmts: []ast.Vertex{ - &ast.StmtAltFor{ + &ast.StmtFor{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, @@ -6150,6 +6150,7 @@ func TestStmtFor_Alt(t *testing.T) { EndPos: 33, }, }, + Alt: true, Cond: []ast.Vertex{ &ast.ExprBinarySmaller{ Node: ast.Node{ diff --git a/internal/php5/php5.go b/internal/php5/php5.go index a5870d0..90079ef 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 c5e03a3..4bae606 100644 --- a/internal/php5/php5.y +++ b/internal/php5/php5.y @@ -926,28 +926,17 @@ unticked_statement: } | T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement { - switch n := $9.(type) { - case *ast.StmtFor : - n.Init = $3 - n.Cond = $5 - n.Loop = $7 - case *ast.StmtAltFor : - n.Init = $3 - n.Cond = $5 - n.Loop = $7 - } + $9.(*ast.StmtFor).ForTkn = $1 + $9.(*ast.StmtFor).OpenParenthesisTkn = $2 + $9.(*ast.StmtFor).Init = $3 + $9.(*ast.StmtFor).InitSemiColonTkn = $4 + $9.(*ast.StmtFor).Cond = $5 + $9.(*ast.StmtFor).CondSemiColonTkn = $6 + $9.(*ast.StmtFor).Loop = $7 + $9.(*ast.StmtFor).CloseParenthesisTkn = $8 + $9.(*ast.StmtFor).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.For, $2.SkippedTokens) - yylex.(*Parser).setFreeFloating($$, token.InitExpr, $4.SkippedTokens) - yylex.(*Parser).setFreeFloating($$, token.CondExpr, $6.SkippedTokens) - yylex.(*Parser).setFreeFloating($$, token.IncExpr, $8.SkippedTokens) } | T_SWITCH parenthesis_expr switch_case_list { @@ -1668,29 +1657,30 @@ foreach_variable: for_statement: statement { - $$ = &ast.StmtFor{ast.Node{}, nil, nil, nil, $1} - - // save position - $$.GetNode().Position = position.NewNodePosition($1) + $$ = &ast.StmtFor{ + Node: ast.Node{ + Position: position.NewNodePosition($1), + }, + Stmt: $1, + } } | ':' inner_statement_list T_ENDFOR ';' { - stmtList := &ast.StmtStmtList{ + $$ = &ast.StmtFor{ 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, + }, + EndForTkn: $3, + SemiColonTkn: $4, } - $$ = &ast.StmtAltFor{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 de9eb19..1fdd0e7 100644 --- a/internal/php5/php5_test.go +++ b/internal/php5/php5_test.go @@ -4490,7 +4490,7 @@ func TestPhp5(t *testing.T) { Stmts: []ast.Vertex{}, }, }, - &ast.StmtAltFor{ + &ast.StmtFor{ Node: ast.Node{ Position: &position.Position{ StartLine: 78, @@ -4499,6 +4499,7 @@ func TestPhp5(t *testing.T) { EndPos: 1685, }, }, + Alt: true, Cond: []ast.Vertex{ &ast.ExprBinarySmaller{ Node: ast.Node{ diff --git a/internal/php7/parser_test.go b/internal/php7/parser_test.go index 8421ca1..cfcf491 100644 --- a/internal/php7/parser_test.go +++ b/internal/php7/parser_test.go @@ -6738,7 +6738,7 @@ func TestStmtFor_Alt(t *testing.T) { }, }, Stmts: []ast.Vertex{ - &ast.StmtAltFor{ + &ast.StmtFor{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, @@ -6747,6 +6747,7 @@ func TestStmtFor_Alt(t *testing.T) { EndPos: 33, }, }, + Alt: true, Cond: []ast.Vertex{ &ast.ExprBinarySmaller{ Node: ast.Node{ diff --git a/internal/php7/php7.go b/internal/php7/php7.go index 2862d9e..80adf9a 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 e1914fe..0ecf1de 100644 --- a/internal/php7/php7.y +++ b/internal/php7/php7.y @@ -895,28 +895,17 @@ statement: } | T_FOR '(' for_exprs ';' for_exprs ';' for_exprs ')' for_statement { - switch n := $9.(type) { - case *ast.StmtFor : - n.Init = $3 - n.Cond = $5 - n.Loop = $7 - case *ast.StmtAltFor : - n.Init = $3 - n.Cond = $5 - n.Loop = $7 - } + $9.(*ast.StmtFor).ForTkn = $1 + $9.(*ast.StmtFor).OpenParenthesisTkn = $2 + $9.(*ast.StmtFor).Init = $3 + $9.(*ast.StmtFor).InitSemiColonTkn = $4 + $9.(*ast.StmtFor).Cond = $5 + $9.(*ast.StmtFor).CondSemiColonTkn = $6 + $9.(*ast.StmtFor).Loop = $7 + $9.(*ast.StmtFor).CloseParenthesisTkn = $8 + $9.(*ast.StmtFor).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.For, $2.SkippedTokens) - yylex.(*Parser).setFreeFloating($$, token.InitExpr, $4.SkippedTokens) - yylex.(*Parser).setFreeFloating($$, token.CondExpr, $6.SkippedTokens) - yylex.(*Parser).setFreeFloating($$, token.IncExpr, $8.SkippedTokens) } | T_SWITCH '(' expr ')' switch_case_list { @@ -1522,29 +1511,30 @@ foreach_variable: for_statement: statement { - $$ = &ast.StmtFor{ast.Node{}, nil, nil, nil, $1} - - // save position - $$.GetNode().Position = position.NewNodePosition($1) + $$ = &ast.StmtFor{ + Node: ast.Node{ + Position: position.NewNodePosition($1), + }, + Stmt: $1, + } } | ':' inner_statement_list T_ENDFOR ';' { - stmtList := &ast.StmtStmtList{ + $$ = &ast.StmtFor{ 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, + }, + EndForTkn: $3, + SemiColonTkn: $4, } - $$ = &ast.StmtAltFor{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 2204bc8..24499be 100644 --- a/internal/php7/php7_test.go +++ b/internal/php7/php7_test.go @@ -5397,7 +5397,7 @@ func TestPhp7(t *testing.T) { Stmts: []ast.Vertex{}, }, }, - &ast.StmtAltFor{ + &ast.StmtFor{ Node: ast.Node{ Position: &position.Position{ StartLine: 92, @@ -5406,6 +5406,7 @@ func TestPhp7(t *testing.T) { EndPos: 1959, }, }, + Alt: true, Cond: []ast.Vertex{ &ast.ExprBinarySmaller{ Node: ast.Node{ diff --git a/pkg/ast/ast.go b/pkg/ast/ast.go index cceb924..d86bf68 100644 --- a/pkg/ast/ast.go +++ b/pkg/ast/ast.go @@ -27,7 +27,6 @@ type NodeVisitor interface { ArgumentList(n *ArgumentList) Argument(n *Argument) - StmtAltFor(n *StmtAltFor) StmtAltForeach(n *StmtAltForeach) StmtAltSwitch(n *StmtAltSwitch) StmtBreak(n *StmtBreak) diff --git a/pkg/ast/node.go b/pkg/ast/node.go index 017d979..80685cd 100644 --- a/pkg/ast/node.go +++ b/pkg/ast/node.go @@ -175,19 +175,6 @@ func (n *ScalarString) Accept(v NodeVisitor) { v.ScalarString(n) } -// StmtAltFor node -type StmtAltFor struct { - Node - Init []Vertex - Cond []Vertex - Loop []Vertex - Stmt Vertex -} - -func (n *StmtAltFor) Accept(v NodeVisitor) { - v.StmtAltFor(n) -} - // StmtAltForeach node type StmtAltForeach struct { Node @@ -453,10 +440,19 @@ func (n *StmtFinally) Accept(v NodeVisitor) { // StmtFor node type StmtFor struct { Node - Init []Vertex - Cond []Vertex - Loop []Vertex - Stmt Vertex + Alt bool + ForTkn *token.Token + OpenParenthesisTkn *token.Token + Init []Vertex + InitSemiColonTkn *token.Token + Cond []Vertex + CondSemiColonTkn *token.Token + Loop []Vertex + CloseParenthesisTkn *token.Token + ColonTkn *token.Token + Stmt Vertex + EndForTkn *token.Token + SemiColonTkn *token.Token } func (n *StmtFor) Accept(v NodeVisitor) { diff --git a/pkg/ast/traverser/dfs.go b/pkg/ast/traverser/dfs.go index 5903f24..629d6ec 100644 --- a/pkg/ast/traverser/dfs.go +++ b/pkg/ast/traverser/dfs.go @@ -119,39 +119,6 @@ func (t *DFS) Traverse(n ast.Vertex) { t.Traverse(nn.Expr) t.visitor.Leave("Expr", true) } - case *ast.StmtAltFor: - if nn == nil { - return - } - if !t.visitor.EnterNode(nn) { - return - } - if nn.Init != nil { - t.visitor.Enter("Init", false) - for _, c := range nn.Init { - t.Traverse(c) - } - t.visitor.Leave("Init", false) - } - if nn.Cond != nil { - t.visitor.Enter("Cond", false) - for _, c := range nn.Cond { - t.Traverse(c) - } - t.visitor.Leave("Cond", false) - } - if nn.Loop != nil { - t.visitor.Enter("Loop", false) - for _, c := range nn.Loop { - t.Traverse(c) - } - t.visitor.Leave("Loop", false) - } - if nn.Stmt != nil { - t.visitor.Enter("Stmt", true) - t.Traverse(nn.Stmt) - t.visitor.Leave("Stmt", true) - } case *ast.StmtAltForeach: if nn == nil { return diff --git a/pkg/ast/visitor/dump.go b/pkg/ast/visitor/dump.go index c684ede..bd9cc4e 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) StmtAltFor(n *ast.StmtAltFor) { - v.printIndentIfNotSingle(v.indent - 1) - v.print("&ast.StmtAltFor{\n") - v.printNode(n.GetNode()) -} - func (v *Dump) StmtAltForeach(n *ast.StmtAltForeach) { v.printIndentIfNotSingle(v.indent - 1) v.print("&ast.StmtAltForeach{\n") @@ -414,6 +408,11 @@ func (v *Dump) StmtFor(n *ast.StmtFor) { v.printIndentIfNotSingle(v.indent - 1) v.print("&ast.StmtFor{\n") v.printNode(n.GetNode()) + + if n.Alt { + v.printIndent(v.indent) + v.print("Alt: true,\n") + } } func (v *Dump) StmtForeach(n *ast.StmtForeach) { diff --git a/pkg/ast/visitor/filter_parser_nodes.go b/pkg/ast/visitor/filter_parser_nodes.go index 83f9cb2..9160d72 100644 --- a/pkg/ast/visitor/filter_parser_nodes.go +++ b/pkg/ast/visitor/filter_parser_nodes.go @@ -209,44 +209,6 @@ func (v *FilterParserNodes) ExprVariable(n *ast.ExprVariable) { } } -func (v *FilterParserNodes) StmtFor(n *ast.StmtFor) { - for k, v := range n.Init { - for { - if nn, ok := v.(*ast.ParserBrackets); ok { - v = nn.Child - } else { - break - } - } - - n.Init[k] = v - } - - for k, v := range n.Cond { - for { - if nn, ok := v.(*ast.ParserBrackets); ok { - v = nn.Child - } else { - break - } - } - - n.Cond[k] = v - } - - for k, v := range n.Loop { - for { - if nn, ok := v.(*ast.ParserBrackets); ok { - v = nn.Child - } else { - break - } - } - - n.Loop[k] = v - } -} - func (v *FilterParserNodes) ExprAssign(n *ast.ExprAssign) { for { if nn, ok := n.Expr.(*ast.ParserBrackets); ok { diff --git a/pkg/ast/visitor/filter_tokens.go b/pkg/ast/visitor/filter_tokens.go index 3d60dd5..9ec8a3d 100644 --- a/pkg/ast/visitor/filter_tokens.go +++ b/pkg/ast/visitor/filter_tokens.go @@ -130,3 +130,14 @@ func (v *FilterTokens) StmtDo(n *ast.StmtDo) { n.CloseParenthesisTkn = nil n.SemiColonTkn = nil } + +func (v *FilterTokens) StmtFor(n *ast.StmtFor) { + n.ForTkn = nil + n.OpenParenthesisTkn = nil + n.InitSemiColonTkn = nil + n.CondSemiColonTkn = nil + n.CloseParenthesisTkn = nil + n.ColonTkn = nil + n.EndForTkn = nil + n.SemiColonTkn = nil +} diff --git a/pkg/ast/visitor/null.go b/pkg/ast/visitor/null.go index 4054486..7fd4992 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) StmtAltFor(_ *ast.StmtAltFor) { - // do nothing -} - func (v *Null) StmtAltForeach(_ *ast.StmtAltForeach) { // do nothing } diff --git a/pkg/printer/pretty_printer.go b/pkg/printer/pretty_printer.go index c172f41..1053b76 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.StmtAltFor: - p.printStmtAltFor(n) case *ast.StmtAltForeach: p.printStmtAltForeach(n) case *ast.StmtAltSwitch: @@ -1363,25 +1361,6 @@ func (p *PrettyPrinter) printStmtAltElse(n ast.Vertex) { } } -func (p *PrettyPrinter) printStmtAltFor(n ast.Vertex) { - nn := n.(*ast.StmtAltFor) - - io.WriteString(p.w, "for (") - p.joinPrint(", ", nn.Init) - io.WriteString(p.w, "; ") - p.joinPrint(", ", nn.Cond) - io.WriteString(p.w, "; ") - p.joinPrint(", ", nn.Loop) - 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, "endfor;") -} - func (p *PrettyPrinter) printStmtAltForeach(n ast.Vertex) { nn := n.(*ast.StmtAltForeach) @@ -1736,6 +1715,11 @@ func (p *PrettyPrinter) printStmtFinally(n ast.Vertex) { func (p *PrettyPrinter) printStmtFor(n ast.Vertex) { nn := n.(*ast.StmtFor) + if nn.Alt { + p.printStmtAltFor(nn) + return + } + io.WriteString(p.w, "for (") p.joinPrint(", ", nn.Init) io.WriteString(p.w, "; ") @@ -1760,6 +1744,25 @@ func (p *PrettyPrinter) printStmtFor(n ast.Vertex) { } } +func (p *PrettyPrinter) printStmtAltFor(n ast.Vertex) { + nn := n.(*ast.StmtFor) + + io.WriteString(p.w, "for (") + p.joinPrint(", ", nn.Init) + io.WriteString(p.w, "; ") + p.joinPrint(", ", nn.Cond) + io.WriteString(p.w, "; ") + p.joinPrint(", ", nn.Loop) + 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, "endfor;") +} + func (p *PrettyPrinter) printStmtForeach(n ast.Vertex) { nn := n.(*ast.StmtForeach) diff --git a/pkg/printer/pretty_printer_test.go b/pkg/printer/pretty_printer_test.go index a193202..0eec375 100644 --- a/pkg/printer/pretty_printer_test.go +++ b/pkg/printer/pretty_printer_test.go @@ -2172,7 +2172,8 @@ func TestPrintAltFor(t *testing.T) { p := printer.NewPrettyPrinter(o, " ") p.Print(&ast.StmtNamespace{ Stmts: []ast.Vertex{ - &ast.StmtAltFor{ + &ast.StmtFor{ + Alt: true, Init: []ast.Vertex{ &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("a")}}, }, diff --git a/pkg/printer/printer.go b/pkg/printer/printer.go index e678ae6..b7ded2f 100644 --- a/pkg/printer/printer.go +++ b/pkg/printer/printer.go @@ -359,8 +359,6 @@ func (p *Printer) printNode(n ast.Vertex) { // stmt - case *ast.StmtAltFor: - p.printStmtAltFor(n) case *ast.StmtAltForeach: p.printStmtAltForeach(n) case *ast.StmtAltSwitch: @@ -1973,39 +1971,6 @@ func (p *Printer) printExprYield(n ast.Vertex) { // smtm -func (p *Printer) printStmtAltFor(n ast.Vertex) { - nn := n.(*ast.StmtAltFor) - p.printFreeFloating(nn, token.Start) - - io.WriteString(p.w, "for") - p.printFreeFloating(nn, token.For) - io.WriteString(p.w, "(") - p.joinPrint(",", nn.Init) - p.printFreeFloating(nn, token.InitExpr) - io.WriteString(p.w, ";") - p.joinPrint(",", nn.Cond) - p.printFreeFloating(nn, token.CondExpr) - io.WriteString(p.w, ";") - p.joinPrint(",", nn.Loop) - p.printFreeFloating(nn, token.IncExpr) - io.WriteString(p.w, ")") - p.printFreeFloating(nn, token.Cond) - io.WriteString(p.w, ":") - - s := nn.Stmt.(*ast.StmtStmtList) - p.printNodes(s.Stmts) - p.printFreeFloating(nn, token.Stmts) - - io.WriteString(p.w, "endfor") - p.printFreeFloating(nn, token.AltEnd) - p.printFreeFloating(nn, token.SemiColon) - if nn.GetNode().Tokens.IsEmpty() { - io.WriteString(p.w, ";") - } - - p.printFreeFloating(nn, token.End) -} - func (p *Printer) printStmtAltForeach(n ast.Vertex) { nn := n.(*ast.StmtAltForeach) p.printFreeFloating(nn, token.Start) @@ -2477,26 +2442,43 @@ func (p *Printer) printStmtFinally(n ast.Vertex) { p.printFreeFloating(nn, token.End) } -func (p *Printer) printStmtFor(n ast.Vertex) { - nn := n.(*ast.StmtFor) - p.printFreeFloating(nn, token.Start) +func (p *Printer) printStmtFor(n *ast.StmtFor) { + if n.Alt { + p.printStmtAltFor(n) + return + } - io.WriteString(p.w, "for") - p.printFreeFloating(nn, token.For) - io.WriteString(p.w, "(") - p.joinPrint(",", nn.Init) - p.printFreeFloating(nn, token.InitExpr) - io.WriteString(p.w, ";") - p.joinPrint(",", nn.Cond) - p.printFreeFloating(nn, token.CondExpr) - io.WriteString(p.w, ";") - p.joinPrint(",", nn.Loop) - p.printFreeFloating(nn, token.IncExpr) - io.WriteString(p.w, ")") + p.printToken(n.ForTkn, "for") + p.printToken(n.OpenParenthesisTkn, "(") + p.joinPrint(",", n.Init) + p.printToken(n.InitSemiColonTkn, ";") + p.joinPrint(",", n.Cond) + p.printToken(n.CondSemiColonTkn, ";") + p.joinPrint(",", n.Loop) + p.printToken(n.CloseParenthesisTkn, ")") - p.Print(nn.Stmt) + p.Print(n.Stmt) +} - p.printFreeFloating(nn, token.End) +func (p *Printer) printStmtAltFor(n *ast.StmtFor) { + p.printToken(n.ForTkn, "for") + p.printToken(n.OpenParenthesisTkn, "(") + p.joinPrint(",", n.Init) + p.printToken(n.InitSemiColonTkn, ";") + p.joinPrint(",", n.Cond) + p.printToken(n.CondSemiColonTkn, ";") + p.joinPrint(",", n.Loop) + p.printToken(n.CloseParenthesisTkn, ")") + p.printToken(n.ColonTkn, ":") + + if stmtList, ok := n.Stmt.(*ast.StmtStmtList); ok { + p.printNodes(stmtList.Stmts) + } else { + p.printNode(n.Stmt) + } + + p.printToken(n.EndForTkn, "endfor") + p.printToken(n.SemiColonTkn, ";") } func (p *Printer) printStmtForeach(n ast.Vertex) { diff --git a/pkg/printer/printer_parsed_php5_test.go b/pkg/printer/printer_parsed_php5_test.go index ce35495..c607b65 100644 --- a/pkg/printer/printer_parsed_php5_test.go +++ b/pkg/printer/printer_parsed_php5_test.go @@ -762,7 +762,8 @@ func TestParseAndPrintPhp5AltIf(t *testing.T) { } func TestParseAndPrintPhp5AltFor(t *testing.T) { - src := `