diff --git a/internal/php5/php5.go b/internal/php5/php5.go index 908d035..466cd09 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 23864be..d17ba27 100644 --- a/internal/php5/php5.y +++ b/internal/php5/php5.y @@ -930,24 +930,33 @@ unticked_statement: } | T_IF parenthesis_expr ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';' { + exprBrackets := &ast.ParserBrackets{ast.Node{}, $2} stmts := &ast.StmtStmtList{ast.Node{}, $4} - $$ = &ast.StmtAltIf{ast.Node{}, $2, stmts, $5, $6} + stmtsBrackets := &ast.ParserBrackets{ast.Node{}, stmts} + $$ = &ast.StmtAltIf{ast.Node{}, exprBrackets, stmtsBrackets, $5, $6} // save position + exprBrackets.GetNode().Position = position.NewNodePosition($2) stmts.GetNode().Position = position.NewNodeListPosition($4) + stmtsBrackets.GetNode().Position = position.NewTokenNodeListPosition($3, $4) $$.GetNode().Position = position.NewTokensPosition($1, $8) // save comments yylex.(*Parser).setFreeFloating($$, token.Start, $1.Tokens) if len($2.GetNode().Tokens[token.OpenParenthesisToken]) > 0 { - yylex.(*Parser).setFreeFloatingTokens($$, token.If, $2.GetNode().Tokens[token.OpenParenthesisToken][:len($2.GetNode().Tokens[token.OpenParenthesisToken])-1]); delete($2.GetNode().Tokens, token.OpenParenthesisToken) + yylex.(*Parser).setFreeFloatingTokens(exprBrackets, token.Start, $2.GetNode().Tokens[token.OpenParenthesisToken]); delete($2.GetNode().Tokens, token.OpenParenthesisToken) } if len($2.GetNode().Tokens[token.CloseParenthesisToken]) > 0 { - yylex.(*Parser).setFreeFloatingTokens($$, token.Expr, $2.GetNode().Tokens[token.CloseParenthesisToken][:len($2.GetNode().Tokens[token.CloseParenthesisToken])-1]); delete($2.GetNode().Tokens, token.CloseParenthesisToken) + yylex.(*Parser).setFreeFloatingTokens(exprBrackets, token.End, $2.GetNode().Tokens[token.CloseParenthesisToken]); delete($2.GetNode().Tokens, token.CloseParenthesisToken) + } + yylex.(*Parser).setFreeFloatingTokens(stmtsBrackets, token.Start, $3.Tokens) + if $6 != nil { + yylex.(*Parser).setFreeFloating($6.(*ast.StmtAltElse).Stmt, token.End, append($7.Tokens, $8.Tokens...)) + } else if len($5) > 0 { + yylex.(*Parser).setFreeFloating($5[len($5)-1].(*ast.StmtAltElseIf).Stmt, token.End, append($7.Tokens, $8.Tokens...)) + } else { + yylex.(*Parser).setFreeFloating(stmtsBrackets, token.End, append($7.Tokens, $8.Tokens...)) } - yylex.(*Parser).setFreeFloating($$, token.Cond, $3.Tokens) - yylex.(*Parser).setFreeFloating($$, token.Stmts, $7.Tokens) - yylex.(*Parser).setFreeFloating($$, token.AltEnd, $8.Tokens) yylex.(*Parser).setToken($$, token.SemiColon, $8.Tokens) yylex.(*Parser).returnTokenToPool(yyDollar, &yyVAL) @@ -2175,23 +2184,27 @@ new_elseif_list: } | new_elseif_list T_ELSEIF parenthesis_expr ':' inner_statement_list { + exprBrackets := &ast.ParserBrackets{ast.Node{}, $3} stmts := &ast.StmtStmtList{ast.Node{}, $5} - _elseIf := &ast.StmtAltElseIf{ast.Node{}, $3, stmts} + stmtsBrackets := &ast.ParserBrackets{ast.Node{}, stmts} + _elseIf := &ast.StmtAltElseIf{ast.Node{}, exprBrackets, stmtsBrackets} $$ = append($1, _elseIf) // save position + exprBrackets.GetNode().Position = position.NewNodePosition($3) stmts.GetNode().Position = position.NewNodeListPosition($5) + exprBrackets.GetNode().Position = position.NewTokenNodeListPosition($4, $5) _elseIf.GetNode().Position = position.NewTokenNodeListPosition($2, $5) // save comments yylex.(*Parser).setFreeFloating(_elseIf, token.Start, $2.Tokens) if len($3.GetNode().Tokens[token.OpenParenthesisToken]) > 0 { - yylex.(*Parser).setFreeFloatingTokens(_elseIf, token.ElseIf, $3.GetNode().Tokens[token.OpenParenthesisToken][:len($3.GetNode().Tokens[token.OpenParenthesisToken])-1]); delete($3.GetNode().Tokens, token.OpenParenthesisToken) + yylex.(*Parser).setFreeFloatingTokens(exprBrackets, token.Start, $3.GetNode().Tokens[token.OpenParenthesisToken]); delete($3.GetNode().Tokens, token.OpenParenthesisToken) } if len($3.GetNode().Tokens[token.CloseParenthesisToken]) > 0 { - yylex.(*Parser).setFreeFloatingTokens(_elseIf, token.Expr, $3.GetNode().Tokens[token.CloseParenthesisToken][:len($3.GetNode().Tokens[token.CloseParenthesisToken])-1]); delete($3.GetNode().Tokens, token.CloseParenthesisToken) + yylex.(*Parser).setFreeFloatingTokens(exprBrackets, token.End, $3.GetNode().Tokens[token.CloseParenthesisToken]); delete($3.GetNode().Tokens, token.CloseParenthesisToken) } - yylex.(*Parser).setFreeFloating(_elseIf, token.Cond, $4.Tokens) + yylex.(*Parser).setFreeFloatingTokens(stmtsBrackets, token.Start, $4.Tokens) yylex.(*Parser).returnTokenToPool(yyDollar, &yyVAL) } @@ -2230,15 +2243,17 @@ new_else_single: | T_ELSE ':' inner_statement_list { stmts := &ast.StmtStmtList{ast.Node{}, $3} - $$ = &ast.StmtAltElse{ast.Node{}, stmts} + stmtsBrackets := &ast.ParserBrackets{ast.Node{}, stmts} + $$ = &ast.StmtAltElse{ast.Node{}, stmtsBrackets} // save position stmts.GetNode().Position = position.NewNodeListPosition($3) + stmtsBrackets.GetNode().Position = position.NewTokenNodeListPosition($2, $3) $$.GetNode().Position = position.NewTokenNodeListPosition($1, $3) // save comments yylex.(*Parser).setFreeFloating($$, token.Start, $1.Tokens) - yylex.(*Parser).setFreeFloating($$, token.Else, $2.Tokens) + yylex.(*Parser).setFreeFloatingTokens(stmtsBrackets, token.Start, $2.Tokens) yylex.(*Parser).returnTokenToPool(yyDollar, &yyVAL) } diff --git a/internal/php7/php7.go b/internal/php7/php7.go index 1cf81e7..0c50734 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 4a2af09..e125503 100644 --- a/internal/php7/php7.y +++ b/internal/php7/php7.y @@ -2037,38 +2037,46 @@ if_stmt: alt_if_stmt_without_else: T_IF '(' expr ')' ':' inner_statement_list { + exprBrackets := &ast.ParserBrackets{ast.Node{}, $3} stmts := &ast.StmtStmtList{ast.Node{}, $6} - $$ = &ast.StmtAltIf{ast.Node{}, $3, stmts, nil, nil} + stmtsBrackets := &ast.ParserBrackets{ast.Node{}, stmts} + $$ = &ast.StmtAltIf{ast.Node{}, exprBrackets, stmtsBrackets, nil, nil} // save position + exprBrackets.GetNode().Position = position.NewTokensPosition($2, $4) stmts.GetNode().Position = position.NewNodeListPosition($6) + stmtsBrackets.GetNode().Position = position.NewTokenNodeListPosition($5, $6) $$.GetNode().Position = position.NewTokenNodeListPosition($1, $6) // save comments yylex.(*Parser).setFreeFloating($$, token.Start, $1.Tokens) - yylex.(*Parser).setFreeFloating($$, token.If, $2.Tokens) - yylex.(*Parser).setFreeFloating($$, token.Expr, $4.Tokens) - yylex.(*Parser).setFreeFloating($$, token.Cond, $5.Tokens) + yylex.(*Parser).setFreeFloatingTokens(exprBrackets, token.Start, $2.Tokens) + yylex.(*Parser).setFreeFloatingTokens(exprBrackets, token.End, $4.Tokens) + yylex.(*Parser).setFreeFloatingTokens(stmtsBrackets, token.Start, $5.Tokens) yylex.(*Parser).returnTokenToPool(yyDollar, &yyVAL) } | alt_if_stmt_without_else T_ELSEIF '(' expr ')' ':' inner_statement_list { + exprBrackets := &ast.ParserBrackets{ast.Node{}, $4} stmts := &ast.StmtStmtList{ast.Node{}, $7} - _elseIf := &ast.StmtAltElseIf{ast.Node{}, $4, stmts} + stmtsBrackets := &ast.ParserBrackets{ast.Node{}, stmts} + _elseIf := &ast.StmtAltElseIf{ast.Node{}, exprBrackets, stmtsBrackets} $1.(*ast.StmtAltIf).ElseIf = append($1.(*ast.StmtAltIf).ElseIf, _elseIf) $$ = $1 // save position + exprBrackets.GetNode().Position = position.NewTokensPosition($3, $5) stmts.GetNode().Position = position.NewNodeListPosition($7) + stmtsBrackets.GetNode().Position = position.NewTokenNodeListPosition($6, $7) _elseIf.GetNode().Position = position.NewTokenNodeListPosition($2, $7) // save comments yylex.(*Parser).setFreeFloating(_elseIf, token.Start, $2.Tokens) - yylex.(*Parser).setFreeFloating(_elseIf, token.ElseIf, $3.Tokens) - yylex.(*Parser).setFreeFloating(_elseIf, token.Expr, $5.Tokens) - yylex.(*Parser).setFreeFloating(_elseIf, token.Cond, $6.Tokens) + yylex.(*Parser).setFreeFloatingTokens(exprBrackets, token.Start, $3.Tokens) + yylex.(*Parser).setFreeFloatingTokens(exprBrackets, token.End, $5.Tokens) + yylex.(*Parser).setFreeFloatingTokens(stmtsBrackets, token.Start, $6.Tokens) yylex.(*Parser).returnTokenToPool(yyDollar, &yyVAL) } @@ -2083,8 +2091,12 @@ alt_if_stmt: $$.GetNode().Position = position.NewNodeTokenPosition($1, $3) // save comments - yylex.(*Parser).setFreeFloating($$, token.Stmts, $2.Tokens) - yylex.(*Parser).setFreeFloating($$, token.AltEnd, $3.Tokens) + altif := $$.(*ast.StmtAltIf) + if len(altif.ElseIf) > 0 { + yylex.(*Parser).setFreeFloating(altif.ElseIf[len(altif.ElseIf)-1], token.End, append($2.Tokens, $3.Tokens...)) + } else { + yylex.(*Parser).setFreeFloating(altif.Stmt, token.End, append($2.Tokens, $3.Tokens...)) + } yylex.(*Parser).setToken($$, token.SemiColon, $3.Tokens) yylex.(*Parser).returnTokenToPool(yyDollar, &yyVAL) @@ -2092,21 +2104,22 @@ alt_if_stmt: | alt_if_stmt_without_else T_ELSE ':' inner_statement_list T_ENDIF ';' { stmts := &ast.StmtStmtList{ast.Node{}, $4} - _else := &ast.StmtAltElse{ast.Node{}, stmts} + stmtsBrackets := &ast.ParserBrackets{ast.Node{}, stmts} + _else := &ast.StmtAltElse{ast.Node{}, stmtsBrackets} $1.(*ast.StmtAltIf).Else = _else $$ = $1 // save position stmts.GetNode().Position = position.NewNodeListPosition($4) + stmtsBrackets.GetNode().Position = position.NewTokensPosition($3, $5) _else.GetNode().Position = position.NewTokenNodeListPosition($2, $4) $$.GetNode().Position = position.NewNodeTokenPosition($1, $6) // save comments yylex.(*Parser).setFreeFloating(_else, token.Start, $2.Tokens) - yylex.(*Parser).setFreeFloating(_else, token.Else, $3.Tokens) - yylex.(*Parser).setFreeFloating($$, token.Stmts, $5.Tokens) - yylex.(*Parser).setFreeFloating($$, token.AltEnd, $6.Tokens) + yylex.(*Parser).setFreeFloatingTokens(stmtsBrackets, token.Start, $3.Tokens) + yylex.(*Parser).setFreeFloating(stmtsBrackets, token.End, append($5.Tokens, $6.Tokens...)) yylex.(*Parser).setToken($$, token.SemiColon, $6.Tokens) yylex.(*Parser).returnTokenToPool(yyDollar, &yyVAL) diff --git a/pkg/ast/visitor/filter_parser_nodes.go b/pkg/ast/visitor/filter_parser_nodes.go index c8eaabf..a7f5529 100644 --- a/pkg/ast/visitor/filter_parser_nodes.go +++ b/pkg/ast/visitor/filter_parser_nodes.go @@ -40,3 +40,29 @@ func (v *FilterParserNodes) StmtUseDeclaration(n *ast.StmtUseDeclaration) { n.Alias = nn.Child } } + +func (v *FilterParserNodes) StmtAltIf(n *ast.StmtAltIf) { + if nn, ok := n.Cond.(*ast.ParserBrackets); ok { + n.Cond = nn.Child + } + + if nn, ok := n.Stmt.(*ast.ParserBrackets); ok { + n.Stmt = nn.Child + } +} + +func (v *FilterParserNodes) StmtAltElseIf(n *ast.StmtAltElseIf) { + if nn, ok := n.Cond.(*ast.ParserBrackets); ok { + n.Cond = nn.Child + } + + if nn, ok := n.Stmt.(*ast.ParserBrackets); ok { + n.Stmt = nn.Child + } +} + +func (v *FilterParserNodes) StmtAltElse(n *ast.StmtAltElse) { + if nn, ok := n.Stmt.(*ast.ParserBrackets); ok { + n.Stmt = nn.Child + } +} diff --git a/pkg/printer/printer.go b/pkg/printer/printer.go index e269a6d..64a32c9 100644 --- a/pkg/printer/printer.go +++ b/pkg/printer/printer.go @@ -1967,16 +1967,32 @@ func (p *Printer) printStmtAltElseIf(n ast.Vertex) { p.printFreeFloating(nn, token.Start) io.WriteString(p.w, "elseif") - p.printFreeFloating(nn, token.ElseIf) - io.WriteString(p.w, "(") - p.Print(nn.Cond) - p.printFreeFloating(nn, token.Expr) - io.WriteString(p.w, ")") - p.printFreeFloating(nn, token.Cond) - io.WriteString(p.w, ":") - if s := nn.Stmt.(*ast.StmtStmtList).Stmts; len(s) > 0 { - p.printNodes(s) + 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, ")") + } + + stmtList, _ := nn.Stmt.(*ast.StmtStmtList) + brackets, ok := nn.Stmt.(*ast.ParserBrackets) + if ok { + p.printFreeFloating(brackets, token.Start) + stmtList = brackets.Child.(*ast.StmtStmtList) + } else { + io.WriteString(p.w, ":") + } + + p.printFreeFloating(stmtList, token.Stmts) + p.printNodes(stmtList.Stmts) + p.printFreeFloating(stmtList, token.End) + + if ok { + p.printFreeFloating(brackets, token.End) } p.printFreeFloating(nn, token.End) @@ -1987,11 +2003,22 @@ func (p *Printer) printStmtAltElse(n ast.Vertex) { p.printFreeFloating(nn, token.Start) io.WriteString(p.w, "else") - p.printFreeFloating(nn, token.Else) - io.WriteString(p.w, ":") - if s := nn.Stmt.(*ast.StmtStmtList).Stmts; len(s) > 0 { - p.printNodes(s) + stmtList, _ := nn.Stmt.(*ast.StmtStmtList) + brackets, ok := nn.Stmt.(*ast.ParserBrackets) + if ok { + p.printFreeFloating(brackets, token.Start) + stmtList = brackets.Child.(*ast.StmtStmtList) + } else { + io.WriteString(p.w, ":") + } + + p.printFreeFloating(stmtList, token.Stmts) + p.printNodes(stmtList.Stmts) + p.printFreeFloating(stmtList, token.End) + + if ok { + p.printFreeFloating(brackets, token.End) } p.printFreeFloating(nn, token.End) @@ -2083,16 +2110,33 @@ func (p *Printer) printStmtAltIf(n ast.Vertex) { p.printFreeFloating(nn, token.Start) io.WriteString(p.w, "if") - p.printFreeFloating(nn, token.If) - io.WriteString(p.w, "(") - p.Print(nn.Cond) - p.printFreeFloating(nn, token.Expr) - io.WriteString(p.w, ")") - p.printFreeFloating(nn, token.Cond) - io.WriteString(p.w, ":") - s := nn.Stmt.(*ast.StmtStmtList) - p.printNodes(s.Stmts) + 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, ")") + } + + stmtList, _ := nn.Stmt.(*ast.StmtStmtList) + brackets, ok := nn.Stmt.(*ast.ParserBrackets) + if ok { + p.printFreeFloating(brackets, token.Start) + stmtList = brackets.Child.(*ast.StmtStmtList) + } else { + io.WriteString(p.w, ":") + } + + p.printFreeFloating(stmtList, token.Stmts) + p.printNodes(stmtList.Stmts) + p.printFreeFloating(stmtList, token.End) + + if ok { + p.printFreeFloating(brackets, token.End) + } for _, elseif := range nn.ElseIf { p.Print(elseif) @@ -2102,9 +2146,10 @@ func (p *Printer) printStmtAltIf(n ast.Vertex) { p.Print(nn.Else) } - p.printFreeFloating(nn, token.Stmts) - io.WriteString(p.w, "endif") - p.printFreeFloating(nn, token.AltEnd) + if !ok { + io.WriteString(p.w, "endif") + } + p.printFreeFloating(nn, token.SemiColon) if nn.GetNode().Tokens.IsEmpty() { io.WriteString(p.w, ";")