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/cfg" "github.com/z7zmey/php-parser/pkg/errors" "github.com/z7zmey/php-parser/pkg/position" "github.com/z7zmey/php-parser/pkg/token" "github.com/z7zmey/php-parser/pkg/version" ) func TestIdentifier(t *testing.T) { src := `bar($a, ...$b); foo::bar($a, ...$b); $foo::bar($a, ...$b); new foo($a, ...$b);` expected := &ast.Root{ Position: &position.Position{ StartLine: 2, EndLine: 7, StartPos: 5, EndPos: 132, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 5, EndPos: 20, }, Expr: &ast.ExprFunctionCall{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 5, EndPos: 19, }, Function: &ast.Name{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 5, EndPos: 8, }, Parts: []ast.Vertex{ &ast.NamePart{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 5, EndPos: 8, }, StringTkn: &token.Token{ ID: token.T_STRING, Value: []byte("foo"), Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 5, EndPos: 8, }, FreeFloating: []*token.Token{ { ID: token.T_OPEN_TAG, Value: []byte(""), Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 46, EndPos: 48, }, }, Method: &ast.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 48, EndPos: 51, }, IdentifierTkn: &token.Token{ ID: token.T_STRING, Value: []byte("bar"), Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 48, EndPos: 51, }, }, Value: []byte("bar"), }, OpenParenthesisTkn: &token.Token{ ID: token.ID(40), Value: []byte("("), Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 51, EndPos: 52, }, }, Args: []ast.Vertex{ &ast.Argument{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 52, EndPos: 54, }, Expr: &ast.ExprVariable{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 52, EndPos: 54, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 52, EndPos: 54, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 52, EndPos: 54, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 56, EndPos: 61, }, VariadicTkn: &token.Token{ ID: token.T_ELLIPSIS, Value: []byte("..."), Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 56, EndPos: 59, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 55, EndPos: 56, }, }, }, }, Expr: &ast.ExprVariable{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 59, EndPos: 61, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 59, EndPos: 61, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 59, EndPos: 61, }, }, Value: []byte("$b"), }, }, }, }, SeparatorTkns: []*token.Token{ { ID: token.ID(44), Value: []byte(","), Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 54, EndPos: 55, }, }, }, CloseParenthesisTkn: &token.Token{ ID: token.ID(41), Value: []byte(")"), Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 61, EndPos: 62, }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 4, EndLine: 4, StartPos: 62, EndPos: 63, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 66, EndPos: 86, }, Expr: &ast.ExprStaticCall{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 66, EndPos: 85, }, Class: &ast.Name{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 66, EndPos: 69, }, Parts: []ast.Vertex{ &ast.NamePart{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 66, EndPos: 69, }, StringTkn: &token.Token{ ID: token.T_STRING, Value: []byte("foo"), Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 66, EndPos: 69, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 4, EndLine: 5, StartPos: 63, EndPos: 66, }, }, }, }, Value: []byte("foo"), }, }, }, DoubleColonTkn: &token.Token{ ID: token.T_PAAMAYIM_NEKUDOTAYIM, Value: []byte("::"), Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 69, EndPos: 71, }, }, Call: &ast.Identifier{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 71, EndPos: 74, }, IdentifierTkn: &token.Token{ ID: token.T_STRING, Value: []byte("bar"), Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 71, EndPos: 74, }, }, Value: []byte("bar"), }, OpenParenthesisTkn: &token.Token{ ID: token.ID(40), Value: []byte("("), Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 74, EndPos: 75, }, }, Args: []ast.Vertex{ &ast.Argument{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 75, EndPos: 77, }, Expr: &ast.ExprVariable{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 75, EndPos: 77, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 75, EndPos: 77, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 75, EndPos: 77, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 79, EndPos: 84, }, VariadicTkn: &token.Token{ ID: token.T_ELLIPSIS, Value: []byte("..."), Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 79, EndPos: 82, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 78, EndPos: 79, }, }, }, }, Expr: &ast.ExprVariable{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 82, EndPos: 84, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 82, EndPos: 84, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 82, EndPos: 84, }, }, Value: []byte("$b"), }, }, }, }, SeparatorTkns: []*token.Token{ { ID: token.ID(44), Value: []byte(","), Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 77, EndPos: 78, }, }, }, CloseParenthesisTkn: &token.Token{ ID: token.ID(41), Value: []byte(")"), Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 84, EndPos: 85, }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 5, EndLine: 5, StartPos: 85, EndPos: 86, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 89, EndPos: 110, }, Expr: &ast.ExprStaticCall{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 89, EndPos: 109, }, Class: &ast.ExprVariable{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 89, EndPos: 93, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 89, EndPos: 93, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$foo"), Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 89, EndPos: 93, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 5, EndLine: 6, StartPos: 86, EndPos: 89, }, }, }, }, Value: []byte("$foo"), }, }, DoubleColonTkn: &token.Token{ ID: token.T_PAAMAYIM_NEKUDOTAYIM, Value: []byte("::"), Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 93, EndPos: 95, }, }, Call: &ast.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 95, EndPos: 98, }, IdentifierTkn: &token.Token{ ID: token.T_STRING, Value: []byte("bar"), Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 95, EndPos: 98, }, }, Value: []byte("bar"), }, OpenParenthesisTkn: &token.Token{ ID: token.ID(40), Value: []byte("("), Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 98, EndPos: 99, }, }, Args: []ast.Vertex{ &ast.Argument{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 99, EndPos: 101, }, Expr: &ast.ExprVariable{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 99, EndPos: 101, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 99, EndPos: 101, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 99, EndPos: 101, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 103, EndPos: 108, }, VariadicTkn: &token.Token{ ID: token.T_ELLIPSIS, Value: []byte("..."), Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 103, EndPos: 106, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 102, EndPos: 103, }, }, }, }, Expr: &ast.ExprVariable{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 106, EndPos: 108, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 106, EndPos: 108, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 106, EndPos: 108, }, }, Value: []byte("$b"), }, }, }, }, SeparatorTkns: []*token.Token{ { ID: token.ID(44), Value: []byte(","), Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 101, EndPos: 102, }, }, }, CloseParenthesisTkn: &token.Token{ ID: token.ID(41), Value: []byte(")"), Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 108, EndPos: 109, }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 6, EndLine: 6, StartPos: 109, EndPos: 110, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 113, EndPos: 132, }, Expr: &ast.ExprNew{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 113, EndPos: 131, }, NewTkn: &token.Token{ ID: token.T_NEW, Value: []byte("new"), Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 113, EndPos: 116, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 6, EndLine: 7, StartPos: 110, EndPos: 113, }, }, }, }, Class: &ast.Name{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 117, EndPos: 120, }, Parts: []ast.Vertex{ &ast.NamePart{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 117, EndPos: 120, }, StringTkn: &token.Token{ ID: token.T_STRING, Value: []byte("foo"), Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 117, EndPos: 120, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 116, EndPos: 117, }, }, }, }, Value: []byte("foo"), }, }, }, OpenParenthesisTkn: &token.Token{ ID: token.ID(40), Value: []byte("("), Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 120, EndPos: 121, }, }, Args: []ast.Vertex{ &ast.Argument{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 121, EndPos: 123, }, Expr: &ast.ExprVariable{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 121, EndPos: 123, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 121, EndPos: 123, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 121, EndPos: 123, }, }, Value: []byte("$a"), }, }, }, &ast.Argument{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 125, EndPos: 130, }, VariadicTkn: &token.Token{ ID: token.T_ELLIPSIS, Value: []byte("..."), Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 125, EndPos: 128, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 124, EndPos: 125, }, }, }, }, Expr: &ast.ExprVariable{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 128, EndPos: 130, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 128, EndPos: 130, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 128, EndPos: 130, }, }, Value: []byte("$b"), }, }, }, }, SeparatorTkns: []*token.Token{ { ID: token.ID(44), Value: []byte(","), Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 123, EndPos: 124, }, }, }, CloseParenthesisTkn: &token.Token{ ID: token.ID(41), Value: []byte(")"), Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 130, EndPos: 131, }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 7, EndLine: 7, StartPos: 131, EndPos: 132, }, }, }, }, EndTkn: &token.Token{}, } config := cfg.Config{ Version: &version.Version{ Major: 5, Minor: 6, }, } lexer := scanner.NewLexer([]byte(src), config) php5parser := php5.NewParser(lexer, config) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestPhp5ParameterNode(t *testing.T) { src := `bar()";` expected := &ast.Root{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 22, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 22, }, Expr: &ast.ScalarEncapsed{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 21, }, OpenQuoteTkn: &token.Token{ ID: token.ID(34), Value: []byte("\""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 4, }, FreeFloating: []*token.Token{ { ID: token.T_OPEN_TAG, Value: []byte(""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 13, EndPos: 15, }, }, Prop: &ast.Identifier{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 18, }, IdentifierTkn: &token.Token{ ID: token.T_STRING, Value: []byte("bar"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 18, }, }, Value: []byte("bar"), }, }, &ast.ScalarEncapsedStringPart{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, EncapsedStrTkn: &token.Token{ ID: token.T_ENCAPSED_AND_WHITESPACE, Value: []byte("()"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 20, }, }, Value: []byte("()"), }, }, CloseQuoteTkn: &token.Token{ ID: token.ID(34), Value: []byte("\""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 20, EndPos: 21, }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 21, EndPos: 22, }, }, }, }, EndTkn: &token.Token{}, } config := cfg.Config{ Version: &version.Version{ Major: 5, Minor: 6, }, } lexer := scanner.NewLexer([]byte(src), config) php5parser := php5.NewParser(lexer, config) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestScalarEncapsed_DollarOpenCurlyBraces(t *testing.T) { src := `bar()}";` expected := &ast.Root{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 24, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 24, }, Expr: &ast.ScalarEncapsed{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 23, }, OpenQuoteTkn: &token.Token{ ID: token.ID(34), Value: []byte("\""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 4, }, FreeFloating: []*token.Token{ { ID: token.T_OPEN_TAG, Value: []byte(""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 14, EndPos: 16, }, }, Method: &ast.Identifier{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 16, EndPos: 19, }, IdentifierTkn: &token.Token{ ID: token.T_STRING, Value: []byte("bar"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 16, EndPos: 19, }, }, Value: []byte("bar"), }, OpenParenthesisTkn: &token.Token{ ID: token.ID(40), Value: []byte("("), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 19, EndPos: 20, }, }, CloseParenthesisTkn: &token.Token{ ID: token.ID(41), Value: []byte(")"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 20, EndPos: 21, }, }, }, CloseCurlyBracketTkn: &token.Token{ ID: token.ID(125), Value: []byte("}"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 21, EndPos: 22, }, }, }, }, CloseQuoteTkn: &token.Token{ ID: token.ID(34), Value: []byte("\""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 22, EndPos: 23, }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 23, EndPos: 24, }, }, }, }, EndTkn: &token.Token{}, } config := cfg.Config{ Version: &version.Version{ Major: 5, Minor: 6, }, } lexer := scanner.NewLexer([]byte(src), config) php5parser := php5.NewParser(lexer, config) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestScalarHeredoc_HeredocSimpleLabel(t *testing.T) { src := ` $v) {}` expected := &ast.Root{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 30, }, Stmts: []ast.Vertex{ &ast.StmtForeach{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 30, }, ForeachTkn: &token.Token{ ID: token.T_FOREACH, Value: []byte("foreach"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 10, }, FreeFloating: []*token.Token{ { ID: token.T_OPEN_TAG, Value: []byte(""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 21, EndPos: 23, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 20, EndPos: 21, }, }, }, }, Var: &ast.ExprVariable{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 26, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 26, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$v"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 26, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 23, EndPos: 24, }, }, }, }, Value: []byte("$v"), }, }, CloseParenthesisTkn: &token.Token{ ID: token.ID(41), Value: []byte(")"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 26, EndPos: 27, }, }, Stmt: &ast.StmtStmtList{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 28, EndPos: 30, }, OpenCurlyBracketTkn: &token.Token{ ID: token.ID(123), Value: []byte("{"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 28, EndPos: 29, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 27, EndPos: 28, }, }, }, }, Stmts: []ast.Vertex{}, CloseCurlyBracketTkn: &token.Token{ ID: token.ID(125), Value: []byte("}"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 30, }, }, }, }, }, EndTkn: &token.Token{}, } config := cfg.Config{ Version: &version.Version{ Major: 5, Minor: 6, }, } lexer := scanner.NewLexer([]byte(src), config) php5parser := php5.NewParser(lexer, config) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestStmtForeach_ExprWithKey(t *testing.T) { src := ` $v) {}` expected := &ast.Root{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 30, }, Stmts: []ast.Vertex{ &ast.StmtForeach{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 30, }, ForeachTkn: &token.Token{ ID: token.T_FOREACH, Value: []byte("foreach"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 10, }, FreeFloating: []*token.Token{ { ID: token.T_OPEN_TAG, Value: []byte(""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 21, EndPos: 23, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 20, EndPos: 21, }, }, }, }, Var: &ast.ExprVariable{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 26, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 26, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$v"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 26, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 23, EndPos: 24, }, }, }, }, Value: []byte("$v"), }, }, CloseParenthesisTkn: &token.Token{ ID: token.ID(41), Value: []byte(")"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 26, EndPos: 27, }, }, Stmt: &ast.StmtStmtList{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 28, EndPos: 30, }, OpenCurlyBracketTkn: &token.Token{ ID: token.ID(123), Value: []byte("{"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 28, EndPos: 29, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 27, EndPos: 28, }, }, }, }, Stmts: []ast.Vertex{}, CloseCurlyBracketTkn: &token.Token{ ID: token.ID(125), Value: []byte("}"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 30, }, }, }, }, }, EndTkn: &token.Token{}, } config := cfg.Config{ Version: &version.Version{ Major: 5, Minor: 6, }, } lexer := scanner.NewLexer([]byte(src), config) php5parser := php5.NewParser(lexer, config) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestStmtForeach_WithRef(t *testing.T) { src := ` &$v) {}` expected := &ast.Root{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 31, }, Stmts: []ast.Vertex{ &ast.StmtForeach{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 31, }, ForeachTkn: &token.Token{ ID: token.T_FOREACH, Value: []byte("foreach"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 10, }, FreeFloating: []*token.Token{ { ID: token.T_OPEN_TAG, Value: []byte(""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 21, EndPos: 23, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 20, EndPos: 21, }, }, }, }, AmpersandTkn: &token.Token{ ID: token.ID(38), Value: []byte("&"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 25, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 23, EndPos: 24, }, }, }, }, Var: &ast.ExprVariable{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 25, EndPos: 27, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 25, EndPos: 27, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$v"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 25, EndPos: 27, }, }, Value: []byte("$v"), }, }, CloseParenthesisTkn: &token.Token{ ID: token.ID(41), Value: []byte(")"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 27, EndPos: 28, }, }, Stmt: &ast.StmtStmtList{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 31, }, OpenCurlyBracketTkn: &token.Token{ ID: token.ID(123), Value: []byte("{"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 30, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 28, EndPos: 29, }, }, }, }, Stmts: []ast.Vertex{}, CloseCurlyBracketTkn: &token.Token{ ID: token.ID(125), Value: []byte("}"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 30, EndPos: 31, }, }, }, }, }, EndTkn: &token.Token{}, } config := cfg.Config{ Version: &version.Version{ Major: 5, Minor: 6, }, } lexer := scanner.NewLexer([]byte(src), config) php5parser := php5.NewParser(lexer, config) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestStmtForeach_WithList(t *testing.T) { src := ` list($v)) {}` expected := &ast.Root{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 36, }, Stmts: []ast.Vertex{ &ast.StmtForeach{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 36, }, ForeachTkn: &token.Token{ ID: token.T_FOREACH, Value: []byte("foreach"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 10, }, FreeFloating: []*token.Token{ { ID: token.T_OPEN_TAG, Value: []byte(""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 21, EndPos: 23, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 20, EndPos: 21, }, }, }, }, Var: &ast.ExprList{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 32, }, ListTkn: &token.Token{ ID: token.T_LIST, Value: []byte("list"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 24, EndPos: 28, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 23, EndPos: 24, }, }, }, }, OpenBracketTkn: &token.Token{ ID: token.ID(40), Value: []byte("("), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 28, EndPos: 29, }, }, Items: []ast.Vertex{ &ast.ExprArrayItem{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 31, }, Val: &ast.ExprVariable{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 31, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 31, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$v"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 29, EndPos: 31, }, }, Value: []byte("$v"), }, }, }, }, CloseBracketTkn: &token.Token{ ID: token.ID(41), Value: []byte(")"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 31, EndPos: 32, }, }, }, CloseParenthesisTkn: &token.Token{ ID: token.ID(41), Value: []byte(")"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 32, EndPos: 33, }, }, Stmt: &ast.StmtStmtList{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 34, EndPos: 36, }, OpenCurlyBracketTkn: &token.Token{ ID: token.ID(123), Value: []byte("{"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 34, EndPos: 35, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 33, EndPos: 34, }, }, }, }, Stmts: []ast.Vertex{}, CloseCurlyBracketTkn: &token.Token{ ID: token.ID(125), Value: []byte("}"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 35, EndPos: 36, }, }, }, }, }, EndTkn: &token.Token{}, } config := cfg.Config{ Version: &version.Version{ Major: 5, Minor: 6, }, } lexer := scanner.NewLexer([]byte(src), config) php5parser := php5.NewParser(lexer, config) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestStmtFunction(t *testing.T) { src := `
` expected := &ast.Root{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 17, }, Stmts: []ast.Vertex{ &ast.StmtNop{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte("?>"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, FreeFloating: []*token.Token{ { ID: token.T_OPEN_TAG, Value: []byte(""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 5, EndPos: 17, }, }, Value: []byte("
"), }, }, EndTkn: &token.Token{}, } config := cfg.Config{ Version: &version.Version{ Major: 5, Minor: 6, }, } lexer := scanner.NewLexer([]byte(src), config) php5parser := php5.NewParser(lexer, config) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestStmtInterface(t *testing.T) { src := `1, &$b,);` expected := &ast.Root{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 21, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 21, }, Expr: &ast.ExprArray{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 20, }, ArrayTkn: &token.Token{ ID: token.T_ARRAY, Value: []byte("array"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 8, }, FreeFloating: []*token.Token{ { ID: token.T_OPEN_TAG, Value: []byte(""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 12, }, }, Val: &ast.ScalarLnumber{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 13, }, NumberTkn: &token.Token{ ID: token.T_LNUMBER, Value: []byte("1"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 13, }, }, Value: []byte("1"), }, }, &ast.ExprArrayItem{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 18, }, AmpersandTkn: &token.Token{ ID: token.ID(38), Value: []byte("&"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 16, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 14, EndPos: 15, }, }, }, }, Val: &ast.ExprVariable{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 16, EndPos: 18, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 16, EndPos: 18, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 16, EndPos: 18, }, }, Value: []byte("$b"), }, }, }, &ast.ExprArrayItem{}, }, SeparatorTkns: []*token.Token{ { ID: token.ID(44), Value: []byte(","), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 13, EndPos: 14, }, }, { ID: token.ID(44), Value: []byte(","), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 18, EndPos: 19, }, }, }, CloseBracketTkn: &token.Token{ ID: token.ID(41), Value: []byte(")"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 19, EndPos: 20, }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 20, EndPos: 21, }, }, }, }, EndTkn: &token.Token{}, } config := cfg.Config{ Version: &version.Version{ Major: 5, Minor: 6, }, } lexer := scanner.NewLexer([]byte(src), config) php5parser := php5.NewParser(lexer, config) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestExprBitwiseNot(t *testing.T) { src := `foo();` expected := &ast.Root{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 13, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 13, }, Expr: &ast.ExprMethodCall{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 12, }, Var: &ast.ExprVariable{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, FreeFloating: []*token.Token{ { ID: token.T_OPEN_TAG, Value: []byte(""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 5, EndPos: 7, }, }, Method: &ast.Identifier{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 7, EndPos: 10, }, IdentifierTkn: &token.Token{ ID: token.T_STRING, Value: []byte("foo"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 7, EndPos: 10, }, }, Value: []byte("foo"), }, OpenParenthesisTkn: &token.Token{ ID: token.ID(40), Value: []byte("("), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 11, }, }, CloseParenthesisTkn: &token.Token{ ID: token.ID(41), Value: []byte(")"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 11, EndPos: 12, }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 13, }, }, }, }, EndTkn: &token.Token{}, } config := cfg.Config{ Version: &version.Version{ Major: 5, Minor: 6, }, } lexer := scanner.NewLexer([]byte(src), config) php5parser := php5.NewParser(lexer, config) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestExprNew(t *testing.T) { src := `b["c"]()->d["e"]();` func TestExprPropertyFetch(t *testing.T) { src := `foo;` expected := &ast.Root{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 11, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 11, }, Expr: &ast.ExprPropertyFetch{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 10, }, Var: &ast.ExprVariable{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 5, }, FreeFloating: []*token.Token{ { ID: token.T_OPEN_TAG, Value: []byte(""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 5, EndPos: 7, }, }, Prop: &ast.Identifier{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 7, EndPos: 10, }, IdentifierTkn: &token.Token{ ID: token.T_STRING, Value: []byte("foo"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 7, EndPos: 10, }, }, Value: []byte("foo"), }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 11, }, }, }, }, EndTkn: &token.Token{}, } config := cfg.Config{ Version: &version.Version{ Major: 5, Minor: 6, }, } lexer := scanner.NewLexer([]byte(src), config) php5parser := php5.NewParser(lexer, config) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestExprShellExec(t *testing.T) { src := "1, &$b,];` expected := &ast.Root{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 16, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 16, }, Expr: &ast.ExprArray{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 15, }, OpenBracketTkn: &token.Token{ ID: token.ID(91), Value: []byte("["), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 4, }, FreeFloating: []*token.Token{ { ID: token.T_OPEN_TAG, Value: []byte(""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 5, EndPos: 7, }, }, Val: &ast.ScalarLnumber{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 7, EndPos: 8, }, NumberTkn: &token.Token{ ID: token.T_LNUMBER, Value: []byte("1"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 7, EndPos: 8, }, }, Value: []byte("1"), }, }, &ast.ExprArrayItem{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 13, }, AmpersandTkn: &token.Token{ ID: token.ID(38), Value: []byte("&"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 10, EndPos: 11, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 9, EndPos: 10, }, }, }, }, Val: &ast.ExprVariable{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 11, EndPos: 13, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 11, EndPos: 13, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 11, EndPos: 13, }, }, Value: []byte("$b"), }, }, }, &ast.ExprArrayItem{}, }, SeparatorTkns: []*token.Token{ { ID: token.ID(44), Value: []byte(","), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 8, EndPos: 9, }, }, { ID: token.ID(44), Value: []byte(","), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 13, EndPos: 14, }, }, }, CloseBracketTkn: &token.Token{ ID: token.ID(93), Value: []byte("]"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 14, EndPos: 15, }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 16, }, }, }, }, EndTkn: &token.Token{}, } config := cfg.Config{ Version: &version.Version{ Major: 5, Minor: 6, }, } lexer := scanner.NewLexer([]byte(src), config) php5parser := php5.NewParser(lexer, config) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestExprStaticCall(t *testing.T) { src := ` $b;` expected := &ast.Root{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 18, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 18, }, Expr: &ast.ExprYield{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 17, }, YieldTkn: &token.Token{ ID: token.T_YIELD, Value: []byte("yield"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 8, }, FreeFloating: []*token.Token{ { ID: token.T_OPEN_TAG, Value: []byte(""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 11, EndPos: 12, }, }, }, }, Val: &ast.ExprVariable{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 17, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 17, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 17, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 14, EndPos: 15, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 17, EndPos: 18, }, }, }, }, EndTkn: &token.Token{}, } config := cfg.Config{ Version: &version.Version{ Major: 5, Minor: 6, }, } lexer := scanner.NewLexer([]byte(src), config) php5parser := php5.NewParser(lexer, config) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } func TestExprYield_Expr(t *testing.T) { src := ` 1;` expected := &ast.Root{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 17, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 17, }, Expr: &ast.ExprYield{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 16, }, YieldTkn: &token.Token{ ID: token.T_YIELD, Value: []byte("yield"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 3, EndPos: 8, }, FreeFloating: []*token.Token{ { ID: token.T_OPEN_TAG, Value: []byte(""), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 12, EndPos: 14, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 11, EndPos: 12, }, }, }, }, Val: &ast.ScalarLnumber{ Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 16, }, NumberTkn: &token.Token{ ID: token.T_LNUMBER, Value: []byte("1"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 15, EndPos: 16, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 14, EndPos: 15, }, }, }, }, Value: []byte("1"), }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 1, EndLine: 1, StartPos: 16, EndPos: 17, }, }, }, }, EndTkn: &token.Token{}, } config := cfg.Config{ Version: &version.Version{ Major: 5, Minor: 6, }, } lexer := scanner.NewLexer([]byte(src), config) php5parser := php5.NewParser(lexer, config) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } // expr assign func TestExprAssign(t *testing.T) { src := `>= $b;` expected := &ast.Root{ Position: &position.Position{ StartLine: 2, EndLine: 17, StartPos: 5, EndPos: 210, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 5, EndPos: 13, }, Expr: &ast.ExprAssign{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 5, EndPos: 12, }, Var: &ast.ExprVariable{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 5, EndPos: 7, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 5, EndPos: 7, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 5, EndPos: 7, }, FreeFloating: []*token.Token{ { ID: token.T_OPEN_TAG, Value: []byte(">="), Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 203, EndPos: 206, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 202, EndPos: 203, }, }, }, }, Expr: &ast.ExprVariable{ Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 207, EndPos: 209, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 207, EndPos: 209, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 207, EndPos: 209, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 206, EndPos: 207, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 209, EndPos: 210, }, }, }, }, EndTkn: &token.Token{}, } config := cfg.Config{ Version: &version.Version{ Major: 5, Minor: 6, }, } lexer := scanner.NewLexer([]byte(src), config) php5parser := php5.NewParser(lexer, config) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } // expr binary func TestExprBinary_BitwiseAnd(t *testing.T) { src := `= $b; $a > $b; $a === $b; $a and $b; $a or $b; $a xor $b; $a - $b; $a % $b; $a * $b; $a != $b; $a !== $b; $a + $b; $a ** $b; $a << $b; $a >> $b; $a <= $b; $a < $b;` expected := &ast.Root{ Position: &position.Position{ StartLine: 2, EndLine: 26, StartPos: 5, EndPos: 295, }, Stmts: []ast.Vertex{ &ast.StmtExpression{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 5, EndPos: 13, }, Expr: &ast.ExprBinaryBitwiseAnd{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 5, EndPos: 12, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 5, EndPos: 7, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 5, EndPos: 7, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 2, EndLine: 2, StartPos: 5, EndPos: 7, }, FreeFloating: []*token.Token{ { ID: token.T_OPEN_TAG, Value: []byte("="), Position: &position.Position{ StartLine: 10, EndLine: 10, StartPos: 99, EndPos: 101, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 10, EndLine: 10, StartPos: 98, EndPos: 99, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 10, EndLine: 10, StartPos: 102, EndPos: 104, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 10, EndLine: 10, StartPos: 102, EndPos: 104, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 10, EndLine: 10, StartPos: 102, EndPos: 104, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 10, EndLine: 10, StartPos: 101, EndPos: 102, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 10, EndLine: 10, StartPos: 104, EndPos: 105, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 11, EndLine: 11, StartPos: 108, EndPos: 116, }, Expr: &ast.ExprBinaryGreater{ Position: &position.Position{ StartLine: 11, EndLine: 11, StartPos: 108, EndPos: 115, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 11, EndLine: 11, StartPos: 108, EndPos: 110, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 11, EndLine: 11, StartPos: 108, EndPos: 110, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 11, EndLine: 11, StartPos: 108, EndPos: 110, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 10, EndLine: 11, StartPos: 105, EndPos: 108, }, }, }, }, Value: []byte("$a"), }, }, OpTkn: &token.Token{ ID: token.ID(62), Value: []byte(">"), Position: &position.Position{ StartLine: 11, EndLine: 11, StartPos: 111, EndPos: 112, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 11, EndLine: 11, StartPos: 110, EndPos: 111, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 11, EndLine: 11, StartPos: 113, EndPos: 115, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 11, EndLine: 11, StartPos: 113, EndPos: 115, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 11, EndLine: 11, StartPos: 113, EndPos: 115, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 11, EndLine: 11, StartPos: 112, EndPos: 113, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 11, EndLine: 11, StartPos: 115, EndPos: 116, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 12, EndLine: 12, StartPos: 119, EndPos: 129, }, Expr: &ast.ExprBinaryIdentical{ Position: &position.Position{ StartLine: 12, EndLine: 12, StartPos: 119, EndPos: 128, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 12, EndLine: 12, StartPos: 119, EndPos: 121, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 12, EndLine: 12, StartPos: 119, EndPos: 121, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 12, EndLine: 12, StartPos: 119, EndPos: 121, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 11, EndLine: 12, StartPos: 116, EndPos: 119, }, }, }, }, Value: []byte("$a"), }, }, OpTkn: &token.Token{ ID: token.T_IS_IDENTICAL, Value: []byte("==="), Position: &position.Position{ StartLine: 12, EndLine: 12, StartPos: 122, EndPos: 125, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 12, EndLine: 12, StartPos: 121, EndPos: 122, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 12, EndLine: 12, StartPos: 126, EndPos: 128, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 12, EndLine: 12, StartPos: 126, EndPos: 128, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 12, EndLine: 12, StartPos: 126, EndPos: 128, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 12, EndLine: 12, StartPos: 125, EndPos: 126, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 12, EndLine: 12, StartPos: 128, EndPos: 129, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 13, EndLine: 13, StartPos: 132, EndPos: 142, }, Expr: &ast.ExprBinaryLogicalAnd{ Position: &position.Position{ StartLine: 13, EndLine: 13, StartPos: 132, EndPos: 141, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 13, EndLine: 13, StartPos: 132, EndPos: 134, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 13, EndLine: 13, StartPos: 132, EndPos: 134, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 13, EndLine: 13, StartPos: 132, EndPos: 134, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 12, EndLine: 13, StartPos: 129, EndPos: 132, }, }, }, }, Value: []byte("$a"), }, }, OpTkn: &token.Token{ ID: token.T_LOGICAL_AND, Value: []byte("and"), Position: &position.Position{ StartLine: 13, EndLine: 13, StartPos: 135, EndPos: 138, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 13, EndLine: 13, StartPos: 134, EndPos: 135, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 13, EndLine: 13, StartPos: 139, EndPos: 141, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 13, EndLine: 13, StartPos: 139, EndPos: 141, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 13, EndLine: 13, StartPos: 139, EndPos: 141, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 13, EndLine: 13, StartPos: 138, EndPos: 139, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 13, EndLine: 13, StartPos: 141, EndPos: 142, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 14, EndLine: 14, StartPos: 145, EndPos: 154, }, Expr: &ast.ExprBinaryLogicalOr{ Position: &position.Position{ StartLine: 14, EndLine: 14, StartPos: 145, EndPos: 153, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 14, EndLine: 14, StartPos: 145, EndPos: 147, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 14, EndLine: 14, StartPos: 145, EndPos: 147, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 14, EndLine: 14, StartPos: 145, EndPos: 147, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 13, EndLine: 14, StartPos: 142, EndPos: 145, }, }, }, }, Value: []byte("$a"), }, }, OpTkn: &token.Token{ ID: token.T_LOGICAL_OR, Value: []byte("or"), Position: &position.Position{ StartLine: 14, EndLine: 14, StartPos: 148, EndPos: 150, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 14, EndLine: 14, StartPos: 147, EndPos: 148, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 14, EndLine: 14, StartPos: 151, EndPos: 153, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 14, EndLine: 14, StartPos: 151, EndPos: 153, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 14, EndLine: 14, StartPos: 151, EndPos: 153, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 14, EndLine: 14, StartPos: 150, EndPos: 151, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 14, EndLine: 14, StartPos: 153, EndPos: 154, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 15, EndLine: 15, StartPos: 157, EndPos: 167, }, Expr: &ast.ExprBinaryLogicalXor{ Position: &position.Position{ StartLine: 15, EndLine: 15, StartPos: 157, EndPos: 166, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 15, EndLine: 15, StartPos: 157, EndPos: 159, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 15, EndLine: 15, StartPos: 157, EndPos: 159, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 15, EndLine: 15, StartPos: 157, EndPos: 159, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 14, EndLine: 15, StartPos: 154, EndPos: 157, }, }, }, }, Value: []byte("$a"), }, }, OpTkn: &token.Token{ ID: token.T_LOGICAL_XOR, Value: []byte("xor"), Position: &position.Position{ StartLine: 15, EndLine: 15, StartPos: 160, EndPos: 163, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 15, EndLine: 15, StartPos: 159, EndPos: 160, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 15, EndLine: 15, StartPos: 164, EndPos: 166, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 15, EndLine: 15, StartPos: 164, EndPos: 166, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 15, EndLine: 15, StartPos: 164, EndPos: 166, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 15, EndLine: 15, StartPos: 163, EndPos: 164, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 15, EndLine: 15, StartPos: 166, EndPos: 167, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 16, EndLine: 16, StartPos: 170, EndPos: 178, }, Expr: &ast.ExprBinaryMinus{ Position: &position.Position{ StartLine: 16, EndLine: 16, StartPos: 170, EndPos: 177, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 16, EndLine: 16, StartPos: 170, EndPos: 172, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 16, EndLine: 16, StartPos: 170, EndPos: 172, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 16, EndLine: 16, StartPos: 170, EndPos: 172, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 15, EndLine: 16, StartPos: 167, EndPos: 170, }, }, }, }, Value: []byte("$a"), }, }, OpTkn: &token.Token{ ID: token.ID(45), Value: []byte("-"), Position: &position.Position{ StartLine: 16, EndLine: 16, StartPos: 173, EndPos: 174, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 16, EndLine: 16, StartPos: 172, EndPos: 173, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 16, EndLine: 16, StartPos: 175, EndPos: 177, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 16, EndLine: 16, StartPos: 175, EndPos: 177, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 16, EndLine: 16, StartPos: 175, EndPos: 177, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 16, EndLine: 16, StartPos: 174, EndPos: 175, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 16, EndLine: 16, StartPos: 177, EndPos: 178, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 181, EndPos: 189, }, Expr: &ast.ExprBinaryMod{ Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 181, EndPos: 188, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 181, EndPos: 183, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 181, EndPos: 183, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 181, EndPos: 183, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 16, EndLine: 17, StartPos: 178, EndPos: 181, }, }, }, }, Value: []byte("$a"), }, }, OpTkn: &token.Token{ ID: token.ID(37), Value: []byte("%"), Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 184, EndPos: 185, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 183, EndPos: 184, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 186, EndPos: 188, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 186, EndPos: 188, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 186, EndPos: 188, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 185, EndPos: 186, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 17, EndLine: 17, StartPos: 188, EndPos: 189, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 18, EndLine: 18, StartPos: 192, EndPos: 200, }, Expr: &ast.ExprBinaryMul{ Position: &position.Position{ StartLine: 18, EndLine: 18, StartPos: 192, EndPos: 199, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 18, EndLine: 18, StartPos: 192, EndPos: 194, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 18, EndLine: 18, StartPos: 192, EndPos: 194, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 18, EndLine: 18, StartPos: 192, EndPos: 194, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 17, EndLine: 18, StartPos: 189, EndPos: 192, }, }, }, }, Value: []byte("$a"), }, }, OpTkn: &token.Token{ ID: token.ID(42), Value: []byte("*"), Position: &position.Position{ StartLine: 18, EndLine: 18, StartPos: 195, EndPos: 196, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 18, EndLine: 18, StartPos: 194, EndPos: 195, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 18, EndLine: 18, StartPos: 197, EndPos: 199, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 18, EndLine: 18, StartPos: 197, EndPos: 199, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 18, EndLine: 18, StartPos: 197, EndPos: 199, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 18, EndLine: 18, StartPos: 196, EndPos: 197, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 18, EndLine: 18, StartPos: 199, EndPos: 200, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 19, EndLine: 19, StartPos: 203, EndPos: 212, }, Expr: &ast.ExprBinaryNotEqual{ Position: &position.Position{ StartLine: 19, EndLine: 19, StartPos: 203, EndPos: 211, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 19, EndLine: 19, StartPos: 203, EndPos: 205, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 19, EndLine: 19, StartPos: 203, EndPos: 205, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 19, EndLine: 19, StartPos: 203, EndPos: 205, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 18, EndLine: 19, StartPos: 200, EndPos: 203, }, }, }, }, Value: []byte("$a"), }, }, OpTkn: &token.Token{ ID: token.T_IS_NOT_EQUAL, Value: []byte("!="), Position: &position.Position{ StartLine: 19, EndLine: 19, StartPos: 206, EndPos: 208, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 19, EndLine: 19, StartPos: 205, EndPos: 206, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 19, EndLine: 19, StartPos: 209, EndPos: 211, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 19, EndLine: 19, StartPos: 209, EndPos: 211, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 19, EndLine: 19, StartPos: 209, EndPos: 211, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 19, EndLine: 19, StartPos: 208, EndPos: 209, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 19, EndLine: 19, StartPos: 211, EndPos: 212, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 20, EndLine: 20, StartPos: 215, EndPos: 225, }, Expr: &ast.ExprBinaryNotIdentical{ Position: &position.Position{ StartLine: 20, EndLine: 20, StartPos: 215, EndPos: 224, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 20, EndLine: 20, StartPos: 215, EndPos: 217, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 20, EndLine: 20, StartPos: 215, EndPos: 217, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 20, EndLine: 20, StartPos: 215, EndPos: 217, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 19, EndLine: 20, StartPos: 212, EndPos: 215, }, }, }, }, Value: []byte("$a"), }, }, OpTkn: &token.Token{ ID: token.T_IS_NOT_IDENTICAL, Value: []byte("!=="), Position: &position.Position{ StartLine: 20, EndLine: 20, StartPos: 218, EndPos: 221, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 20, EndLine: 20, StartPos: 217, EndPos: 218, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 20, EndLine: 20, StartPos: 222, EndPos: 224, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 20, EndLine: 20, StartPos: 222, EndPos: 224, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 20, EndLine: 20, StartPos: 222, EndPos: 224, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 20, EndLine: 20, StartPos: 221, EndPos: 222, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 20, EndLine: 20, StartPos: 224, EndPos: 225, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 21, EndLine: 21, StartPos: 228, EndPos: 236, }, Expr: &ast.ExprBinaryPlus{ Position: &position.Position{ StartLine: 21, EndLine: 21, StartPos: 228, EndPos: 235, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 21, EndLine: 21, StartPos: 228, EndPos: 230, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 21, EndLine: 21, StartPos: 228, EndPos: 230, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 21, EndLine: 21, StartPos: 228, EndPos: 230, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 20, EndLine: 21, StartPos: 225, EndPos: 228, }, }, }, }, Value: []byte("$a"), }, }, OpTkn: &token.Token{ ID: token.ID(43), Value: []byte("+"), Position: &position.Position{ StartLine: 21, EndLine: 21, StartPos: 231, EndPos: 232, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 21, EndLine: 21, StartPos: 230, EndPos: 231, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 21, EndLine: 21, StartPos: 233, EndPos: 235, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 21, EndLine: 21, StartPos: 233, EndPos: 235, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 21, EndLine: 21, StartPos: 233, EndPos: 235, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 21, EndLine: 21, StartPos: 232, EndPos: 233, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 21, EndLine: 21, StartPos: 235, EndPos: 236, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 22, EndLine: 22, StartPos: 239, EndPos: 248, }, Expr: &ast.ExprBinaryPow{ Position: &position.Position{ StartLine: 22, EndLine: 22, StartPos: 239, EndPos: 247, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 22, EndLine: 22, StartPos: 239, EndPos: 241, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 22, EndLine: 22, StartPos: 239, EndPos: 241, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 22, EndLine: 22, StartPos: 239, EndPos: 241, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 21, EndLine: 22, StartPos: 236, EndPos: 239, }, }, }, }, Value: []byte("$a"), }, }, OpTkn: &token.Token{ ID: token.T_POW, Value: []byte("**"), Position: &position.Position{ StartLine: 22, EndLine: 22, StartPos: 242, EndPos: 244, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 22, EndLine: 22, StartPos: 241, EndPos: 242, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 22, EndLine: 22, StartPos: 245, EndPos: 247, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 22, EndLine: 22, StartPos: 245, EndPos: 247, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 22, EndLine: 22, StartPos: 245, EndPos: 247, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 22, EndLine: 22, StartPos: 244, EndPos: 245, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 22, EndLine: 22, StartPos: 247, EndPos: 248, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 23, EndLine: 23, StartPos: 251, EndPos: 260, }, Expr: &ast.ExprBinaryShiftLeft{ Position: &position.Position{ StartLine: 23, EndLine: 23, StartPos: 251, EndPos: 259, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 23, EndLine: 23, StartPos: 251, EndPos: 253, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 23, EndLine: 23, StartPos: 251, EndPos: 253, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 23, EndLine: 23, StartPos: 251, EndPos: 253, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 22, EndLine: 23, StartPos: 248, EndPos: 251, }, }, }, }, Value: []byte("$a"), }, }, OpTkn: &token.Token{ ID: token.T_SL, Value: []byte("<<"), Position: &position.Position{ StartLine: 23, EndLine: 23, StartPos: 254, EndPos: 256, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 23, EndLine: 23, StartPos: 253, EndPos: 254, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 23, EndLine: 23, StartPos: 257, EndPos: 259, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 23, EndLine: 23, StartPos: 257, EndPos: 259, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 23, EndLine: 23, StartPos: 257, EndPos: 259, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 23, EndLine: 23, StartPos: 256, EndPos: 257, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 23, EndLine: 23, StartPos: 259, EndPos: 260, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 24, EndLine: 24, StartPos: 263, EndPos: 272, }, Expr: &ast.ExprBinaryShiftRight{ Position: &position.Position{ StartLine: 24, EndLine: 24, StartPos: 263, EndPos: 271, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 24, EndLine: 24, StartPos: 263, EndPos: 265, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 24, EndLine: 24, StartPos: 263, EndPos: 265, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 24, EndLine: 24, StartPos: 263, EndPos: 265, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 23, EndLine: 24, StartPos: 260, EndPos: 263, }, }, }, }, Value: []byte("$a"), }, }, OpTkn: &token.Token{ ID: token.T_SR, Value: []byte(">>"), Position: &position.Position{ StartLine: 24, EndLine: 24, StartPos: 266, EndPos: 268, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 24, EndLine: 24, StartPos: 265, EndPos: 266, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 24, EndLine: 24, StartPos: 269, EndPos: 271, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 24, EndLine: 24, StartPos: 269, EndPos: 271, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 24, EndLine: 24, StartPos: 269, EndPos: 271, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 24, EndLine: 24, StartPos: 268, EndPos: 269, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 24, EndLine: 24, StartPos: 271, EndPos: 272, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 25, EndLine: 25, StartPos: 275, EndPos: 284, }, Expr: &ast.ExprBinarySmallerOrEqual{ Position: &position.Position{ StartLine: 25, EndLine: 25, StartPos: 275, EndPos: 283, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 25, EndLine: 25, StartPos: 275, EndPos: 277, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 25, EndLine: 25, StartPos: 275, EndPos: 277, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 25, EndLine: 25, StartPos: 275, EndPos: 277, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 24, EndLine: 25, StartPos: 272, EndPos: 275, }, }, }, }, Value: []byte("$a"), }, }, OpTkn: &token.Token{ ID: token.T_IS_SMALLER_OR_EQUAL, Value: []byte("<="), Position: &position.Position{ StartLine: 25, EndLine: 25, StartPos: 278, EndPos: 280, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 25, EndLine: 25, StartPos: 277, EndPos: 278, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 25, EndLine: 25, StartPos: 281, EndPos: 283, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 25, EndLine: 25, StartPos: 281, EndPos: 283, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 25, EndLine: 25, StartPos: 281, EndPos: 283, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 25, EndLine: 25, StartPos: 280, EndPos: 281, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 25, EndLine: 25, StartPos: 283, EndPos: 284, }, }, }, &ast.StmtExpression{ Position: &position.Position{ StartLine: 26, EndLine: 26, StartPos: 287, EndPos: 295, }, Expr: &ast.ExprBinarySmaller{ Position: &position.Position{ StartLine: 26, EndLine: 26, StartPos: 287, EndPos: 294, }, Left: &ast.ExprVariable{ Position: &position.Position{ StartLine: 26, EndLine: 26, StartPos: 287, EndPos: 289, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 26, EndLine: 26, StartPos: 287, EndPos: 289, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$a"), Position: &position.Position{ StartLine: 26, EndLine: 26, StartPos: 287, EndPos: 289, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte("\n\t\t"), Position: &position.Position{ StartLine: 25, EndLine: 26, StartPos: 284, EndPos: 287, }, }, }, }, Value: []byte("$a"), }, }, OpTkn: &token.Token{ ID: token.ID(60), Value: []byte("<"), Position: &position.Position{ StartLine: 26, EndLine: 26, StartPos: 290, EndPos: 291, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 26, EndLine: 26, StartPos: 289, EndPos: 290, }, }, }, }, Right: &ast.ExprVariable{ Position: &position.Position{ StartLine: 26, EndLine: 26, StartPos: 292, EndPos: 294, }, Name: &ast.Identifier{ Position: &position.Position{ StartLine: 26, EndLine: 26, StartPos: 292, EndPos: 294, }, IdentifierTkn: &token.Token{ ID: token.T_VARIABLE, Value: []byte("$b"), Position: &position.Position{ StartLine: 26, EndLine: 26, StartPos: 292, EndPos: 294, }, FreeFloating: []*token.Token{ { ID: token.T_WHITESPACE, Value: []byte(" "), Position: &position.Position{ StartLine: 26, EndLine: 26, StartPos: 291, EndPos: 292, }, }, }, }, Value: []byte("$b"), }, }, }, SemiColonTkn: &token.Token{ ID: token.ID(59), Value: []byte(";"), Position: &position.Position{ StartLine: 26, EndLine: 26, StartPos: 294, EndPos: 295, }, }, }, }, EndTkn: &token.Token{}, } config := cfg.Config{ Version: &version.Version{ Major: 5, Minor: 6, }, } lexer := scanner.NewLexer([]byte(src), config) php5parser := php5.NewParser(lexer, config) php5parser.Parse() actual := php5parser.GetRootNode() assert.DeepEqual(t, expected, actual) } // expr cast func TestExprCast_Array(t *testing.T) { src := `