package php5_test import ( "testing" "gotest.tools/assert" "github.com/z7zmey/php-parser/internal/php5" "github.com/z7zmey/php-parser/internal/scanner" "github.com/z7zmey/php-parser/pkg/ast" "github.com/z7zmey/php-parser/pkg/position" ) func TestIdentifier(t *testing.T) { src := `bar($a, ...$b); foo::bar($a, ...$b); $foo::bar($a, ...$b); new foo($a, ...$b); ` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 7, StartPos: 6, EndPos: 133, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 6, EndPos: 21, }, }, Expr: &ast.ExprFunctionCall{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 6, EndPos: 20, }, }, Function: &ast.NameName{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 6, EndPos: 9, }, }, Parts: []ast.Vertex{ &ast.NameNamePart{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 6, EndPos: 9, }, }, Value: []byte("foo"), }, }, }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 9, EndPos: 20, }, }, Arguments: []ast.Vertex{ &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 10, EndPos: 12, }, }, Variadic: false, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 10, EndPos: 12, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 10, EndPos: 12, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 14, EndPos: 19, }, }, Variadic: true, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 17, EndPos: 19, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 17, EndPos: 19, }, }, Value: []byte("$b"), }, }, }, }, }, }, }, &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 24, EndPos: 40, }, }, Expr: &ast.ExprFunctionCall{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 24, EndPos: 39, }, }, Function: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 24, EndPos: 28, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 24, EndPos: 28, }, }, Value: []byte("$foo"), }, }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 28, EndPos: 39, }, }, Arguments: []ast.Vertex{ &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 29, EndPos: 31, }, }, Variadic: false, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 29, EndPos: 31, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 29, EndPos: 31, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 33, EndPos: 38, }, }, Variadic: true, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 36, EndPos: 38, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 3, EndLine: 3, StartPos: 36, EndPos: 38, }, }, Value: []byte("$b"), }, }, }, }, }, }, }, &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 43, EndPos: 64, }, }, Expr: &ast.ExprMethodCall{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 43, EndPos: 63, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 43, EndPos: 47, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 43, EndPos: 47, }, }, Value: []byte("$foo"), }, }, Method: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 49, EndPos: 52, }, }, Value: []byte("bar"), }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 52, EndPos: 63, }, }, Arguments: []ast.Vertex{ &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 53, EndPos: 55, }, }, Variadic: false, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 53, EndPos: 55, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 53, EndPos: 55, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 57, EndPos: 62, }, }, IsReference: false, Variadic: true, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 60, EndPos: 62, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 60, EndPos: 62, }, }, Value: []byte("$b"), }, }, }, }, }, }, }, &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 67, EndPos: 87, }, }, Expr: &ast.ExprStaticCall{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 67, EndPos: 86, }, }, Class: &ast.NameName{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 67, EndPos: 70, }, }, Parts: []ast.Vertex{ &ast.NameNamePart{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 67, EndPos: 70, }, }, Value: []byte("foo"), }, }, }, Call: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 72, EndPos: 75, }, }, Value: []byte("bar"), }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 75, EndPos: 86, }, }, Arguments: []ast.Vertex{ &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 76, EndPos: 78, }, }, Variadic: false, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 76, EndPos: 78, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 76, EndPos: 78, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 80, EndPos: 85, }, }, Variadic: true, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 83, EndPos: 85, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 83, EndPos: 85, }, }, Value: []byte("$b"), }, }, }, }, }, }, }, &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 90, EndPos: 111, }, }, Expr: &ast.ExprStaticCall{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 90, EndPos: 110, }, }, Class: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 90, EndPos: 94, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 90, EndPos: 94, }, }, Value: []byte("$foo"), }, }, Call: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 96, EndPos: 99, }, }, Value: []byte("bar"), }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 99, EndPos: 110, }, }, Arguments: []ast.Vertex{ &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 100, EndPos: 102, }, }, Variadic: false, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 100, EndPos: 102, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 100, EndPos: 102, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 104, EndPos: 109, }, }, Variadic: true, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 107, EndPos: 109, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 107, EndPos: 109, }, }, Value: []byte("$b"), }, }, }, }, }, }, }, &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 114, EndPos: 133, }, }, Expr: &ast.ExprNew{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 114, EndPos: 132, }, }, Class: &ast.NameName{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 118, EndPos: 121, }, }, Parts: []ast.Vertex{ &ast.NameNamePart{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 118, EndPos: 121, }, }, Value: []byte("foo"), }, }, }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 121, EndPos: 132, }, }, Arguments: []ast.Vertex{ &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 122, EndPos: 124, }, }, Variadic: false, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 122, EndPos: 124, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 122, EndPos: 124, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 126, EndPos: 131, }, }, Variadic: true, IsReference: false, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 129, EndPos: 131, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 129, EndPos: 131, }, }, Value: []byte("$b"), }, }, }, }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestPhp5ParameterNode(t *testing.T) { src := `bar()";` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 22, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 22, }, }, Expr: &ast.ScalarEncapsed{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 21, }, }, Parts: []ast.Vertex{ &ast.ScalarEncapsedStringPart{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 4, EndPos: 9, }, }, Value: []byte("test "), }, &ast.ExprPropertyFetch{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 18, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 13, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 13, }, }, Value: []byte("$foo"), }, }, Property: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 18, }, }, Value: []byte("bar"), }, }, &ast.ScalarEncapsedStringPart{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, Value: []byte("()"), }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestScalarEncapsed_DollarOpenCurlyBraces(t *testing.T) { src := `bar()}";` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 24, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 24, }, }, Expr: &ast.ScalarEncapsed{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 23, }, }, Parts: []ast.Vertex{ &ast.ScalarEncapsedStringPart{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 4, EndPos: 9, }, }, Value: []byte("test "), }, &ast.ExprMethodCall{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 21, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 14, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 14, }, }, Value: []byte("$foo"), }, }, Method: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 16, EndPos: 19, }, }, Value: []byte("bar"), }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 19, EndPos: 21, }, }, }, }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestScalarHeredoc_HeredocSimpleLabel(t *testing.T) { src := ` $v) {}` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 30, }, }, Stmts: []ast.Vertex{ &ast.StmtForeach{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 30, }, }, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, Value: []byte("$a"), }, }, Key: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, Value: []byte("$k"), }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 26, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 26, }, }, Value: []byte("$v"), }, }, Stmt: &ast.StmtStmtList{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 28, EndPos: 30, }, }, Stmts: []ast.Vertex{}, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestStmtForeach_ExprWithKey(t *testing.T) { src := ` $v) {}` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 30, }, }, Stmts: []ast.Vertex{ &ast.StmtForeach{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 30, }, }, Expr: &ast.ExprShortArray{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, Items: []ast.Vertex{}, }, Key: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, Value: []byte("$k"), }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 26, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 26, }, }, Value: []byte("$v"), }, }, Stmt: &ast.StmtStmtList{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 28, EndPos: 30, }, }, Stmts: []ast.Vertex{}, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestStmtForeach_WithRef(t *testing.T) { src := ` &$v) {}` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 31, }, }, Stmts: []ast.Vertex{ &ast.StmtForeach{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 31, }, }, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, Value: []byte("$a"), }, }, Key: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, Value: []byte("$k"), }, }, Var: &ast.ExprReference{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 27, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 25, EndPos: 27, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 25, EndPos: 27, }, }, Value: []byte("$v"), }, }, }, Stmt: &ast.StmtStmtList{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 31, }, }, Stmts: []ast.Vertex{}, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestStmtForeach_WithList(t *testing.T) { src := ` list($v)) {}` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 36, }, }, Stmts: []ast.Vertex{ &ast.StmtForeach{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 36, }, }, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, Value: []byte("$a"), }, }, Key: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, Value: []byte("$k"), }, }, Var: &ast.ExprList{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 32, }, }, Items: []ast.Vertex{ &ast.ExprArrayItem{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 31, }, }, Val: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 31, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 31, }, }, Value: []byte("$v"), }, }, }, }, }, Stmt: &ast.StmtStmtList{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 34, EndPos: 36, }, }, Stmts: []ast.Vertex{}, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestStmtFunction(t *testing.T) { src := `
` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 17, }, }, Stmts: []ast.Vertex{ &ast.StmtNop{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, }, &ast.StmtInlineHtml{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 5, EndPos: 17, }, }, Value: []byte("
"), }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestStmtInterface(t *testing.T) { src := `1, &$b,);` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 21, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 21, }, }, Expr: &ast.ExprArray{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 20, }, }, Items: []ast.Vertex{ &ast.ExprArrayItem{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 13, }, }, Key: &ast.ScalarLnumber{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 10, }, }, Value: []byte("1"), }, Val: &ast.ScalarLnumber{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 13, }, }, Value: []byte("1"), }, }, &ast.ExprArrayItem{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 18, }, }, Val: &ast.ExprReference{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 18, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 16, EndPos: 18, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 16, EndPos: 18, }, }, Value: []byte("$b"), }, }, }, }, &ast.ExprArrayItem{}, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestExprBitwiseNot(t *testing.T) { src := `foo();` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 13, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 13, }, }, Expr: &ast.ExprMethodCall{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 12, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, Value: []byte("$a"), }, }, Method: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 7, EndPos: 10, }, }, Value: []byte("foo"), }, ArgumentList: &ast.ArgumentList{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 12, }, }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestExprNew(t *testing.T) { src := `foo;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 11, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 11, }, }, Expr: &ast.ExprPropertyFetch{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 10, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, Value: []byte("$a"), }, }, Property: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 7, EndPos: 10, }, }, Value: []byte("foo"), }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestExprReference_ForeachWithRef(t *testing.T) { t.Helper() src := ` &$v) {}` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 31, }, }, Stmts: []ast.Vertex{ &ast.StmtForeach{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 31, }, }, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, }, Value: []byte("$a"), }, }, Key: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, Value: []byte("$k"), }, }, Var: &ast.ExprReference{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 27, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 25, EndPos: 27, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 25, EndPos: 27, }, }, Value: []byte("$v"), }, }, }, Stmt: &ast.StmtStmtList{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 31, }, }, Stmts: []ast.Vertex{}, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestExprShellExec(t *testing.T) { src := "1, &$b,];` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 16, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 16, }, }, Expr: &ast.ExprShortArray{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 15, }, }, Items: []ast.Vertex{ &ast.ExprArrayItem{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 4, EndPos: 8, }, }, Key: &ast.ScalarLnumber{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 4, EndPos: 5, }, }, Value: []byte("1"), }, Val: &ast.ScalarLnumber{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 7, EndPos: 8, }, }, Value: []byte("1"), }, }, &ast.ExprArrayItem{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 13, }, }, Val: &ast.ExprReference{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 13, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 11, EndPos: 13, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 11, EndPos: 13, }, }, Value: []byte("$b"), }, }, }, }, &ast.ExprArrayItem{}, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestExprStaticCall(t *testing.T) { src := ` $b;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 18, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 18, }, }, Expr: &ast.ExprYield{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 17, }, }, Key: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 11, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 11, }, }, Value: []byte("$a"), }, }, Value: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 17, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 17, }, }, Value: []byte("$b"), }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestExprYield_Expr(t *testing.T) { src := ` 1;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 17, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 17, }, }, Expr: &ast.ExprYield{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 16, }, }, Key: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 11, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 11, }, }, Value: []byte("$a"), }, }, Value: &ast.ScalarLnumber{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 16, }, }, Value: []byte("1"), }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } // expr assign func TestExprAssign_Assign(t *testing.T) { src := `>= $b;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 13, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 13, }, }, Expr: &ast.ExprAssignShiftRight{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 12, }, }, Var: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, Value: []byte("$a"), }, }, Expr: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 12, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 12, }, }, Value: []byte("$b"), }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } // expr binary func TestExprBinary_BitwiseAnd(t *testing.T) { src := `= $b;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 12, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 12, }, }, Expr: &ast.ExprBinaryGreaterOrEqual{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 11, }, }, Left: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, Value: []byte("$a"), }, }, Right: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 11, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 11, }, }, Value: []byte("$b"), }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestExprBinary_Greater(t *testing.T) { src := ` $b;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 11, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 11, }, }, Expr: &ast.ExprBinaryGreater{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 10, }, }, Left: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, Value: []byte("$a"), }, }, Right: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 8, EndPos: 10, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 8, EndPos: 10, }, }, Value: []byte("$b"), }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestExprBinary_Identical(t *testing.T) { src := `> $b;` expected := &ast.Root{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 12, }, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 12, }, }, Expr: &ast.ExprBinaryShiftRight{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 11, }, }, Left: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, }, Value: []byte("$a"), }, }, Right: &ast.ExprVariable{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 11, }, }, VarName: &ast.Identifier{ Node: ast.Node{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 11, }, }, Value: []byte("$b"), }, }, }, }, }, } lexer := scanner.NewLexer([]byte(src), "5.6", false, nil) php5parser := php5.NewParser(lexer, nil) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestExprBinary_SmallerOrEqual(t *testing.T) { src := `