diff --git a/internal/php5/parser_test.go b/internal/php5/parser_test.go index 0a8d776..725f642 100644 --- a/internal/php5/parser_test.go +++ b/internal/php5/parser_test.go @@ -12762,7 +12762,7 @@ func TestStmtBreak(t *testing.T) { }, }, Stmts: []ast.Vertex{ - &ast.StmtAltWhile{ + &ast.StmtWhile{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, @@ -12771,6 +12771,7 @@ func TestStmtBreak(t *testing.T) { EndPos: 34, }, }, + Alt: true, Cond: &ast.ScalarLnumber{ Node: ast.Node{ Position: &position.Position{ diff --git a/internal/php5/php5.go b/internal/php5/php5.go index 953db89..d6165d2 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 38a0d87..b760bdc 100644 --- a/internal/php5/php5.y +++ b/internal/php5/php5.y @@ -901,20 +901,13 @@ unticked_statement: } | T_WHILE parenthesis_expr while_statement { - switch n := $3.(type) { - case *ast.StmtWhile : - n.Cond = $2 - case *ast.StmtAltWhile : - n.Cond = $2 - } + $3.(*ast.StmtWhile).WhileTkn = $1 + $3.(*ast.StmtWhile).OpenParenthesisTkn = $2.(*ast.ParserBrackets).OpenBracketTkn + $3.(*ast.StmtWhile).Cond = $2.(*ast.ParserBrackets).Child + $3.(*ast.StmtWhile).CloseParenthesisTkn = $2.(*ast.ParserBrackets).CloseBracketTkn + $3.(*ast.StmtWhile).Node.Position = position.NewTokenNodePosition($1, $3) $$ = $3 - - // save position - $$.GetNode().Position = position.NewTokenNodePosition($1, $3) - - // save comments - yylex.(*Parser).setFreeFloating($$, token.Start, $1.SkippedTokens) } | T_DO statement T_WHILE parenthesis_expr ';' { @@ -1914,29 +1907,30 @@ case_separator: while_statement: statement { - $$ = &ast.StmtWhile{ast.Node{}, nil, $1} - - // save position - $$.GetNode().Position = position.NewNodePosition($1) + $$ = &ast.StmtWhile{ + Node: ast.Node{ + Position: position.NewNodePosition($1), + }, + Stmt: $1, + } } | ':' inner_statement_list T_ENDWHILE ';' { - stmtList := &ast.StmtStmtList{ + $$ = &ast.StmtWhile{ 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, + }, + EndWhileTkn: $3, + SemiColonTkn: $4, } - $$ = &ast.StmtAltWhile{ast.Node{}, 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 535f8c7..de9eb19 100644 --- a/internal/php5/php5_test.go +++ b/internal/php5/php5_test.go @@ -3049,7 +3049,7 @@ func TestPhp5(t *testing.T) { }, }, }, - &ast.StmtAltWhile{ + &ast.StmtWhile{ Node: ast.Node{ Position: &position.Position{ StartLine: 57, @@ -3058,6 +3058,7 @@ func TestPhp5(t *testing.T) { EndPos: 1046, }, }, + Alt: true, Cond: &ast.ScalarLnumber{ Node: ast.Node{ Position: &position.Position{ diff --git a/internal/php7/parser_test.go b/internal/php7/parser_test.go index 67ce06a..8421ca1 100644 --- a/internal/php7/parser_test.go +++ b/internal/php7/parser_test.go @@ -14441,7 +14441,7 @@ func TestStmtBreak(t *testing.T) { }, }, Stmts: []ast.Vertex{ - &ast.StmtAltWhile{ + &ast.StmtWhile{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, @@ -14450,6 +14450,7 @@ func TestStmtBreak(t *testing.T) { EndPos: 34, }, }, + Alt: true, Cond: &ast.ScalarLnumber{ Node: ast.Node{ Position: &position.Position{ diff --git a/internal/php7/php7.go b/internal/php7/php7.go index e1a071b..323095b 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 03fbb1e..bc12e9f 100644 --- a/internal/php7/php7.y +++ b/internal/php7/php7.y @@ -870,31 +870,13 @@ statement: } | T_WHILE '(' expr ')' while_statement { - exprBrackets := &ast.ParserBrackets{ - Node: ast.Node{ - Position: position.NewTokensPosition($2, $4), - }, - OpenBracketTkn: $2, - Child: $3, - CloseBracketTkn: $4, - } - - switch n := $5.(type) { - case *ast.StmtWhile : - n.Cond = exprBrackets - case *ast.StmtAltWhile : - n.Cond = exprBrackets - } + $5.(*ast.StmtWhile).WhileTkn = $1 + $5.(*ast.StmtWhile).OpenParenthesisTkn = $2 + $5.(*ast.StmtWhile).Cond = $3 + $5.(*ast.StmtWhile).CloseParenthesisTkn = $4 + $5.(*ast.StmtWhile).Node.Position = position.NewTokenNodePosition($1, $5) $$ = $5 - - // save position - $$.GetNode().Position = position.NewTokenNodePosition($1, $5) - - // save comments - yylex.(*Parser).setFreeFloating($$, token.Start, $1.SkippedTokens) - yylex.(*Parser).setFreeFloatingTokens(exprBrackets, token.Start, $2.SkippedTokens) - yylex.(*Parser).setFreeFloatingTokens(exprBrackets, token.End, $4.SkippedTokens) } | T_DO statement T_WHILE '(' expr ')' ';' { @@ -1740,29 +1722,30 @@ case_separator: while_statement: statement { - $$ = &ast.StmtWhile{ast.Node{}, nil, $1} - - // save position - $$.GetNode().Position = position.NewNodePosition($1) + $$ = &ast.StmtWhile{ + Node: ast.Node{ + Position: position.NewNodePosition($1), + }, + Stmt: $1, + } } | ':' inner_statement_list T_ENDWHILE ';' { - stmtList := &ast.StmtStmtList{ + $$ = &ast.StmtWhile{ 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, + }, + EndWhileTkn: $3, + SemiColonTkn: $4, } - $$ = &ast.StmtAltWhile{ast.Node{}, 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 a12803b..2204bc8 100644 --- a/internal/php7/php7_test.go +++ b/internal/php7/php7_test.go @@ -3821,7 +3821,7 @@ func TestPhp7(t *testing.T) { }, }, }, - &ast.StmtAltWhile{ + &ast.StmtWhile{ Node: ast.Node{ Position: &position.Position{ StartLine: 69, @@ -3830,6 +3830,7 @@ func TestPhp7(t *testing.T) { EndPos: 1290, }, }, + Alt: true, Cond: &ast.ScalarLnumber{ Node: ast.Node{ Position: &position.Position{ diff --git a/pkg/ast/ast.go b/pkg/ast/ast.go index 4b60110..cceb924 100644 --- a/pkg/ast/ast.go +++ b/pkg/ast/ast.go @@ -30,7 +30,6 @@ type NodeVisitor interface { StmtAltFor(n *StmtAltFor) StmtAltForeach(n *StmtAltForeach) StmtAltSwitch(n *StmtAltSwitch) - StmtAltWhile(n *StmtAltWhile) StmtBreak(n *StmtBreak) StmtCase(n *StmtCase) StmtCaseList(n *StmtCaseList) diff --git a/pkg/ast/node.go b/pkg/ast/node.go index 993b65b..80ca23e 100644 --- a/pkg/ast/node.go +++ b/pkg/ast/node.go @@ -212,17 +212,6 @@ func (n *StmtAltSwitch) Accept(v NodeVisitor) { v.StmtAltSwitch(n) } -// StmtAltWhile node -type StmtAltWhile struct { - Node - Cond Vertex - Stmt Vertex -} - -func (n *StmtAltWhile) Accept(v NodeVisitor) { - v.StmtAltWhile(n) -} - // StmtBreak node type StmtBreak struct { Node @@ -839,8 +828,15 @@ func (n *StmtUseDeclaration) Accept(v NodeVisitor) { // StmtWhile node type StmtWhile struct { Node - Cond Vertex - Stmt Vertex + Alt bool + WhileTkn *token.Token + OpenParenthesisTkn *token.Token + Cond Vertex + CloseParenthesisTkn *token.Token + ColonTkn *token.Token + Stmt Vertex + EndWhileTkn *token.Token + SemiColonTkn *token.Token } func (n *StmtWhile) Accept(v NodeVisitor) { diff --git a/pkg/ast/traverser/dfs.go b/pkg/ast/traverser/dfs.go index 89d6977..5903f24 100644 --- a/pkg/ast/traverser/dfs.go +++ b/pkg/ast/traverser/dfs.go @@ -196,23 +196,6 @@ func (t *DFS) Traverse(n ast.Vertex) { t.Traverse(nn.CaseList) t.visitor.Leave("CaseList", true) } - case *ast.StmtAltWhile: - if nn == nil { - return - } - if !t.visitor.EnterNode(nn) { - return - } - if nn.Cond != nil { - t.visitor.Enter("Cond", true) - t.Traverse(nn.Cond) - t.visitor.Leave("Cond", 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 874e88d..c684ede 100644 --- a/pkg/ast/visitor/dump.go +++ b/pkg/ast/visitor/dump.go @@ -270,12 +270,6 @@ func (v *Dump) StmtAltSwitch(n *ast.StmtAltSwitch) { v.printNode(n.GetNode()) } -func (v *Dump) StmtAltWhile(n *ast.StmtAltWhile) { - v.printIndentIfNotSingle(v.indent - 1) - v.print("&ast.StmtAltWhile{\n") - v.printNode(n.GetNode()) -} - func (v *Dump) StmtBreak(n *ast.StmtBreak) { v.printIndentIfNotSingle(v.indent - 1) v.print("&ast.StmtBreak{\n") @@ -637,6 +631,11 @@ func (v *Dump) StmtWhile(n *ast.StmtWhile) { v.printIndentIfNotSingle(v.indent - 1) v.print("&ast.StmtWhile{\n") v.printNode(n.GetNode()) + + if n.Alt { + v.printIndent(v.indent) + v.print("Alt: true,\n") + } } func (v *Dump) ExprArray(n *ast.ExprArray) { diff --git a/pkg/ast/visitor/filter_parser_nodes.go b/pkg/ast/visitor/filter_parser_nodes.go index 859778f..20ed98d 100644 --- a/pkg/ast/visitor/filter_parser_nodes.go +++ b/pkg/ast/visitor/filter_parser_nodes.go @@ -13,26 +13,6 @@ func (v *FilterParserNodes) EnterNode(n ast.Vertex) bool { return true } -func (v *FilterParserNodes) StmtWhile(n *ast.StmtWhile) { - for { - if nn, ok := n.Cond.(*ast.ParserBrackets); ok { - n.Cond = nn.Child - } else { - break - } - } -} - -func (v *FilterParserNodes) StmtAltWhile(n *ast.StmtAltWhile) { - for { - if nn, ok := n.Cond.(*ast.ParserBrackets); ok { - n.Cond = nn.Child - } else { - break - } - } -} - func (v *FilterParserNodes) StmtDo(n *ast.StmtDo) { for { if nn, ok := n.Cond.(*ast.ParserBrackets); ok { diff --git a/pkg/ast/visitor/filter_tokens.go b/pkg/ast/visitor/filter_tokens.go index a1df886..620b703 100644 --- a/pkg/ast/visitor/filter_tokens.go +++ b/pkg/ast/visitor/filter_tokens.go @@ -113,3 +113,12 @@ func (v *FilterTokens) ParserBrackets(n *ast.ParserBrackets) { n.OpenBracketTkn = nil n.CloseBracketTkn = nil } + +func (v *FilterTokens) StmtWhile(n *ast.StmtWhile) { + n.WhileTkn = nil + n.OpenParenthesisTkn = nil + n.CloseParenthesisTkn = nil + n.ColonTkn = nil + n.EndWhileTkn = nil + n.SemiColonTkn = nil +} diff --git a/pkg/ast/visitor/null.go b/pkg/ast/visitor/null.go index 83c590d..4054486 100644 --- a/pkg/ast/visitor/null.go +++ b/pkg/ast/visitor/null.go @@ -66,10 +66,6 @@ func (v *Null) StmtAltSwitch(_ *ast.StmtAltSwitch) { // do nothing } -func (v *Null) StmtAltWhile(_ *ast.StmtAltWhile) { - // 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 b089a24..c172f41 100644 --- a/pkg/printer/pretty_printer.go +++ b/pkg/printer/pretty_printer.go @@ -303,8 +303,6 @@ func (p *PrettyPrinter) printNode(n ast.Vertex) { p.printStmtAltForeach(n) case *ast.StmtAltSwitch: p.printStmtAltSwitch(n) - case *ast.StmtAltWhile: - p.printStmtAltWhile(n) case *ast.StmtBreak: p.printStmtBreak(n) case *ast.StmtCase: @@ -1450,21 +1448,6 @@ func (p *PrettyPrinter) printStmtAltSwitch(n ast.Vertex) { io.WriteString(p.w, "endswitch;") } -func (p *PrettyPrinter) printStmtAltWhile(n ast.Vertex) { - nn := n.(*ast.StmtAltWhile) - - io.WriteString(p.w, "while (") - p.Print(nn.Cond) - 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, "endwhile;") -} - func (p *PrettyPrinter) printStmtBreak(n ast.Vertex) { nn := n.(*ast.StmtBreak) @@ -2190,6 +2173,11 @@ func (p *PrettyPrinter) printStmtUseDeclaration(n ast.Vertex) { func (p *PrettyPrinter) printStmtWhile(n ast.Vertex) { nn := n.(*ast.StmtWhile) + if nn.Alt { + p.printStmtAltWhile(nn) + return + } + io.WriteString(p.w, "while (") p.Print(nn.Cond) io.WriteString(p.w, ")") @@ -2209,3 +2197,18 @@ func (p *PrettyPrinter) printStmtWhile(n ast.Vertex) { p.indentDepth-- } } + +func (p *PrettyPrinter) printStmtAltWhile(n ast.Vertex) { + nn := n.(*ast.StmtWhile) + + io.WriteString(p.w, "while (") + p.Print(nn.Cond) + 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, "endwhile;") +} diff --git a/pkg/printer/pretty_printer_test.go b/pkg/printer/pretty_printer_test.go index f4a3188..6bb07ea 100644 --- a/pkg/printer/pretty_printer_test.go +++ b/pkg/printer/pretty_printer_test.go @@ -2091,7 +2091,7 @@ func TestPrintAltElseIf(t *testing.T) { p := printer.NewPrettyPrinter(o, " ") p.Print(&ast.StmtElseIf{ - Alt: true, + Alt: true, Cond: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("a")}}, Stmt: &ast.StmtStmtList{ Stmts: []ast.Vertex{ @@ -2114,7 +2114,7 @@ func TestPrintAltElseIfEmpty(t *testing.T) { p := printer.NewPrettyPrinter(o, " ") p.Print(&ast.StmtElseIf{ - Alt: true, + Alt: true, Cond: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("a")}}, Stmt: &ast.StmtStmtList{}, }) @@ -2154,7 +2154,7 @@ func TestPrintAltElseEmpty(t *testing.T) { p := printer.NewPrettyPrinter(o, " ") p.Print(&ast.StmtElse{ - Alt: true, + Alt: true, Stmt: &ast.StmtStmtList{}, }) @@ -2241,7 +2241,7 @@ func TestPrintAltIf(t *testing.T) { p.Print(&ast.StmtNamespace{ Stmts: []ast.Vertex{ &ast.StmtIf{ - Alt: true, + Alt: true, Cond: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("a")}}, Stmt: &ast.StmtStmtList{ Stmts: []ast.Vertex{ @@ -2250,7 +2250,7 @@ func TestPrintAltIf(t *testing.T) { }, ElseIf: []ast.Vertex{ &ast.StmtElseIf{ - Alt: true, + Alt: true, Cond: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("b")}}, Stmt: &ast.StmtStmtList{ Stmts: []ast.Vertex{ @@ -2259,7 +2259,7 @@ func TestPrintAltIf(t *testing.T) { }, }, &ast.StmtElseIf{ - Alt: true, + Alt: true, Cond: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("c")}}, Stmt: &ast.StmtStmtList{}, }, @@ -2342,7 +2342,8 @@ func TestPrintAltWhile(t *testing.T) { p := printer.NewPrettyPrinter(o, " ") p.Print(&ast.StmtNamespace{ Stmts: []ast.Vertex{ - &ast.StmtAltWhile{ + &ast.StmtWhile{ + Alt: true, Cond: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("a")}}, Stmt: &ast.StmtStmtList{ Stmts: []ast.Vertex{ diff --git a/pkg/printer/printer.go b/pkg/printer/printer.go index afc80a8..8275817 100644 --- a/pkg/printer/printer.go +++ b/pkg/printer/printer.go @@ -365,8 +365,6 @@ func (p *Printer) printNode(n ast.Vertex) { p.printStmtAltForeach(n) case *ast.StmtAltSwitch: p.printStmtAltSwitch(n) - case *ast.StmtAltWhile: - p.printStmtAltWhile(n) case *ast.StmtBreak: p.printStmtBreak(n) case *ast.StmtCase: @@ -2091,39 +2089,6 @@ func (p *Printer) printStmtAltSwitch(n ast.Vertex) { p.printFreeFloating(nn, token.End) } -func (p *Printer) printStmtAltWhile(n ast.Vertex) { - nn := n.(*ast.StmtAltWhile) - p.printFreeFloating(nn, token.Start) - - io.WriteString(p.w, "while") - - if _, ok := nn.Cond.(*ast.ParserBrackets); !ok { - io.WriteString(p.w, "(") - } - - p.Print(nn.Cond) - - if _, ok := nn.Cond.(*ast.ParserBrackets); !ok { - 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, "endwhile") - 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) printStmtBreak(n ast.Vertex) { nn := n.(*ast.StmtBreak) p.printFreeFloating(nn, token.Start) @@ -3169,25 +3134,35 @@ func (p *Printer) printStmtUseDeclaration(n *ast.StmtUseDeclaration) { p.printToken(n.CommaTkn, "") } -func (p *Printer) printStmtWhile(n ast.Vertex) { - nn := n.(*ast.StmtWhile) - p.printFreeFloating(nn, token.Start) - - io.WriteString(p.w, "while") - - if _, ok := nn.Cond.(*ast.ParserBrackets); !ok { - io.WriteString(p.w, "(") +func (p *Printer) printStmtWhile(n *ast.StmtWhile) { + if n.Alt { + p.printStmtAltWhile(n) + return } - p.Print(nn.Cond) + p.printToken(n.WhileTkn, "while") + p.printToken(n.OpenParenthesisTkn, "(") + p.Print(n.Cond) + p.printToken(n.CloseParenthesisTkn, ")") - if _, ok := nn.Cond.(*ast.ParserBrackets); !ok { - io.WriteString(p.w, ")") + p.Print(n.Stmt) +} + +func (p *Printer) printStmtAltWhile(n *ast.StmtWhile) { + p.printToken(n.WhileTkn, "while") + p.printToken(n.OpenParenthesisTkn, "(") + p.Print(n.Cond) + p.printToken(n.CloseParenthesisTkn, ")") + p.printToken(n.ColonTkn, ":") + + if stmtList, ok := n.Stmt.(*ast.StmtStmtList); ok { + p.printNodes(stmtList.Stmts) + } else { + p.Print(n.Stmt) } - p.Print(nn.Stmt) - - p.printFreeFloating(nn, token.End) + p.printToken(n.EndWhileTkn, "endwhile") + p.printToken(n.SemiColonTkn, ";") } func (p *Printer) printParserAs(n ast.Vertex) { diff --git a/pkg/printer/printer_parsed_php5_test.go b/pkg/printer/printer_parsed_php5_test.go index 82dd9a2..1af1e60 100644 --- a/pkg/printer/printer_parsed_php5_test.go +++ b/pkg/printer/printer_parsed_php5_test.go @@ -820,7 +820,8 @@ func TestParseAndPrintPhp5AltSwitch(t *testing.T) { } func TestParseAndPrintPhp5AltWhile(t *testing.T) { - src := `