php-parser/internal/php8/parser_test.go
2023-03-31 16:50:08 +02:00

56143 lines
1.2 MiB

package php8_test
import (
"testing"
"github.com/laytan/php-parser/internal/php8"
"gotest.tools/assert"
"github.com/laytan/php-parser/pkg/ast"
"github.com/laytan/php-parser/pkg/conf"
"github.com/laytan/php-parser/pkg/errors"
"github.com/laytan/php-parser/pkg/position"
"github.com/laytan/php-parser/pkg/token"
"github.com/laytan/php-parser/pkg/version"
)
func TestMain(m *testing.M) {
// Ignore StartCol and EndCol in equality checks, these tests were written before they were added.
position.CheckColEquality = false
}
func TestIdentifier(t *testing.T) {
src := `<? $foo;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$foo"),
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestPhp8ArgumentNode(t *testing.T) {
src := `<?
foo($a, ...$b);
$foo($a, ...$b);
$foo->bar($a, ...$b);
foo::bar($a, ...$b);
$foo::bar($a, ...$b);
new foo($a, ...$b);
/** anonymous class */
new class ($a, ...$b) {};`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 9,
StartPos: 5,
EndPos: 185,
},
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: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
Value: []byte("foo"),
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 8,
EndPos: 9,
},
},
Args: []ast.Vertex{
&ast.Argument{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 11,
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 11,
},
},
Value: []byte("$a"),
},
},
},
&ast.Argument{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 13,
EndPos: 18,
},
VariadicTkn: &token.Token{
ID: token.T_ELLIPSIS,
Value: []byte("..."),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 13,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 13,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 16,
EndPos: 18,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 16,
EndPos: 18,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 16,
EndPos: 18,
},
},
Value: []byte("$b"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 11,
EndPos: 12,
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 18,
EndPos: 19,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 20,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 23,
EndPos: 39,
},
Expr: &ast.ExprFunctionCall{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 23,
EndPos: 38,
},
Function: &ast.ExprVariable{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 23,
EndPos: 27,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 23,
EndPos: 27,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$foo"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 23,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 20,
EndPos: 23,
},
},
},
},
Value: []byte("$foo"),
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 27,
EndPos: 28,
},
},
Args: []ast.Vertex{
&ast.Argument{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 28,
EndPos: 30,
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 28,
EndPos: 30,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 28,
EndPos: 30,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 28,
EndPos: 30,
},
},
Value: []byte("$a"),
},
},
},
&ast.Argument{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 32,
EndPos: 37,
},
VariadicTkn: &token.Token{
ID: token.T_ELLIPSIS,
Value: []byte("..."),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 32,
EndPos: 35,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 31,
EndPos: 32,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 35,
EndPos: 37,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 35,
EndPos: 37,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 35,
EndPos: 37,
},
},
Value: []byte("$b"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 30,
EndPos: 31,
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 37,
EndPos: 38,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 38,
EndPos: 39,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 42,
EndPos: 63,
},
Expr: &ast.ExprMethodCall{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 42,
EndPos: 62,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 42,
EndPos: 46,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 42,
EndPos: 46,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$foo"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 42,
EndPos: 46,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 3,
EndLine: 4,
StartPos: 39,
EndPos: 42,
},
},
},
},
Value: []byte("$foo"),
},
},
ObjectOperatorTkn: &token.Token{
ID: token.T_OBJECT_OPERATOR,
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,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 160,
EndPos: 185,
},
Expr: &ast.ExprNew{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 160,
EndPos: 184,
},
NewTkn: &token.Token{
ID: token.T_NEW,
Value: []byte("new"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 160,
EndPos: 163,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 7,
EndLine: 8,
StartPos: 132,
EndPos: 135,
},
},
{
ID: token.T_DOC_COMMENT,
Value: []byte("/** anonymous class */"),
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 135,
EndPos: 157,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 8,
EndLine: 9,
StartPos: 157,
EndPos: 160,
},
},
},
},
Class: &ast.StmtClass{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 164,
EndPos: 184,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 164,
EndPos: 169,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 163,
EndPos: 164,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 170,
EndPos: 171,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 169,
EndPos: 170,
},
},
},
},
Args: []ast.Vertex{
&ast.Argument{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 171,
EndPos: 173,
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 171,
EndPos: 173,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 171,
EndPos: 173,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 171,
EndPos: 173,
},
},
Value: []byte("$a"),
},
},
},
&ast.Argument{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 175,
EndPos: 180,
},
VariadicTkn: &token.Token{
ID: token.T_ELLIPSIS,
Value: []byte("..."),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 175,
EndPos: 178,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 174,
EndPos: 175,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 178,
EndPos: 180,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 178,
EndPos: 180,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 178,
EndPos: 180,
},
},
Value: []byte("$b"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 173,
EndPos: 174,
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 180,
EndPos: 181,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 182,
EndPos: 183,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 181,
EndPos: 182,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 183,
EndPos: 184,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 184,
EndPos: 185,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestPhp8ParameterNode(t *testing.T) {
src := `<?
function foo(?bar $bar=null, baz &...$baz) {}
class foo {public function foo(?bar $bar=null, baz &...$baz) {}}
function(?bar $bar=null, baz &...$baz) {};
static function(?bar $bar=null, baz &...$baz) {};
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 5,
StartPos: 5,
EndPos: 214,
},
Stmts: []ast.Vertex{
&ast.StmtFunction{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 50,
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 13,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 14,
EndPos: 17,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 14,
EndPos: 17,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 13,
EndPos: 14,
},
},
},
},
Value: []byte("foo"),
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 17,
EndPos: 18,
},
},
Params: []ast.Vertex{
&ast.Parameter{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 18,
EndPos: 32,
},
Type: &ast.Nullable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 18,
EndPos: 22,
},
QuestionTkn: &token.Token{
ID: token.ID(63),
Value: []byte("?"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 18,
EndPos: 19,
},
},
Expr: &ast.Name{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 22,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 22,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 22,
},
},
Value: []byte("bar"),
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 23,
EndPos: 27,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 23,
EndPos: 27,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$bar"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 23,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 22,
EndPos: 23,
},
},
},
},
Value: []byte("$bar"),
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 27,
EndPos: 28,
},
},
DefaultValue: &ast.ExprConstFetch{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 28,
EndPos: 32,
},
Const: &ast.Name{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 28,
EndPos: 32,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 28,
EndPos: 32,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("null"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 28,
EndPos: 32,
},
},
Value: []byte("null"),
},
},
},
},
},
&ast.Parameter{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 34,
EndPos: 46,
},
Type: &ast.Name{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 34,
EndPos: 37,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 34,
EndPos: 37,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("baz"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 34,
EndPos: 37,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 33,
EndPos: 34,
},
},
},
},
Value: []byte("baz"),
},
},
},
AmpersandTkn: &token.Token{
ID: token.T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG,
Value: []byte("&"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 38,
EndPos: 39,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 37,
EndPos: 38,
},
},
},
},
VariadicTkn: &token.Token{
ID: token.T_ELLIPSIS,
Value: []byte("..."),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 39,
EndPos: 42,
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 42,
EndPos: 46,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 42,
EndPos: 46,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$baz"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 42,
EndPos: 46,
},
},
Value: []byte("$baz"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 32,
EndPos: 33,
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 46,
EndPos: 47,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 48,
EndPos: 49,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 47,
EndPos: 48,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 49,
EndPos: 50,
},
},
},
&ast.StmtClass{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 53,
EndPos: 117,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 53,
EndPos: 58,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 50,
EndPos: 53,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 59,
EndPos: 62,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 59,
EndPos: 62,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 58,
EndPos: 59,
},
},
},
},
Value: []byte("foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 63,
EndPos: 64,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 62,
EndPos: 63,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtClassMethod{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 64,
EndPos: 116,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 64,
EndPos: 70,
},
IdentifierTkn: &token.Token{
ID: token.T_PUBLIC,
Value: []byte("public"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 64,
EndPos: 70,
},
},
Value: []byte("public"),
},
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 71,
EndPos: 79,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 70,
EndPos: 71,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 80,
EndPos: 83,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 80,
EndPos: 83,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 79,
EndPos: 80,
},
},
},
},
Value: []byte("foo"),
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 83,
EndPos: 84,
},
},
Params: []ast.Vertex{
&ast.Parameter{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 84,
EndPos: 98,
},
Type: &ast.Nullable{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 84,
EndPos: 88,
},
QuestionTkn: &token.Token{
ID: token.ID(63),
Value: []byte("?"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 84,
EndPos: 85,
},
},
Expr: &ast.Name{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 85,
EndPos: 88,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 85,
EndPos: 88,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 85,
EndPos: 88,
},
},
Value: []byte("bar"),
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 89,
EndPos: 93,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 89,
EndPos: 93,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$bar"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 89,
EndPos: 93,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 88,
EndPos: 89,
},
},
},
},
Value: []byte("$bar"),
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 93,
EndPos: 94,
},
},
DefaultValue: &ast.ExprConstFetch{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 94,
EndPos: 98,
},
Const: &ast.Name{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 94,
EndPos: 98,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 94,
EndPos: 98,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("null"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 94,
EndPos: 98,
},
},
Value: []byte("null"),
},
},
},
},
},
&ast.Parameter{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 100,
EndPos: 112,
},
Type: &ast.Name{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 100,
EndPos: 103,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 100,
EndPos: 103,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("baz"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 100,
EndPos: 103,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 99,
EndPos: 100,
},
},
},
},
Value: []byte("baz"),
},
},
},
AmpersandTkn: &token.Token{
ID: token.T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG,
Value: []byte("&"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 104,
EndPos: 105,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 103,
EndPos: 104,
},
},
},
},
VariadicTkn: &token.Token{
ID: token.T_ELLIPSIS,
Value: []byte("..."),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 105,
EndPos: 108,
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 108,
EndPos: 112,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 108,
EndPos: 112,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$baz"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 108,
EndPos: 112,
},
},
Value: []byte("$baz"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 98,
EndPos: 99,
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 112,
EndPos: 113,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 114,
EndPos: 116,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 114,
EndPos: 115,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 113,
EndPos: 114,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 115,
EndPos: 116,
},
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 116,
EndPos: 117,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 120,
EndPos: 162,
},
Expr: &ast.ExprClosure{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 120,
EndPos: 161,
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 120,
EndPos: 128,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 3,
EndLine: 4,
StartPos: 117,
EndPos: 120,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 128,
EndPos: 129,
},
},
Params: []ast.Vertex{
&ast.Parameter{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 129,
EndPos: 143,
},
Type: &ast.Nullable{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 129,
EndPos: 133,
},
QuestionTkn: &token.Token{
ID: token.ID(63),
Value: []byte("?"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 129,
EndPos: 130,
},
},
Expr: &ast.Name{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 130,
EndPos: 133,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 130,
EndPos: 133,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 130,
EndPos: 133,
},
},
Value: []byte("bar"),
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 134,
EndPos: 138,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 134,
EndPos: 138,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$bar"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 134,
EndPos: 138,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 133,
EndPos: 134,
},
},
},
},
Value: []byte("$bar"),
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 138,
EndPos: 139,
},
},
DefaultValue: &ast.ExprConstFetch{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 139,
EndPos: 143,
},
Const: &ast.Name{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 139,
EndPos: 143,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 139,
EndPos: 143,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("null"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 139,
EndPos: 143,
},
},
Value: []byte("null"),
},
},
},
},
},
&ast.Parameter{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 145,
EndPos: 157,
},
Type: &ast.Name{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 145,
EndPos: 148,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 145,
EndPos: 148,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("baz"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 145,
EndPos: 148,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 144,
EndPos: 145,
},
},
},
},
Value: []byte("baz"),
},
},
},
AmpersandTkn: &token.Token{
ID: token.T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG,
Value: []byte("&"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 149,
EndPos: 150,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 148,
EndPos: 149,
},
},
},
},
VariadicTkn: &token.Token{
ID: token.T_ELLIPSIS,
Value: []byte("..."),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 150,
EndPos: 153,
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 153,
EndPos: 157,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 153,
EndPos: 157,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$baz"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 153,
EndPos: 157,
},
},
Value: []byte("$baz"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 143,
EndPos: 144,
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 157,
EndPos: 158,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 159,
EndPos: 160,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 158,
EndPos: 159,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 160,
EndPos: 161,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 161,
EndPos: 162,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 165,
EndPos: 214,
},
Expr: &ast.ExprClosure{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 165,
EndPos: 213,
},
StaticTkn: &token.Token{
ID: token.T_STATIC,
Value: []byte("static"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 165,
EndPos: 171,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 4,
EndLine: 5,
StartPos: 162,
EndPos: 165,
},
},
},
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 172,
EndPos: 180,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 171,
EndPos: 172,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 180,
EndPos: 181,
},
},
Params: []ast.Vertex{
&ast.Parameter{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 181,
EndPos: 195,
},
Type: &ast.Nullable{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 181,
EndPos: 185,
},
QuestionTkn: &token.Token{
ID: token.ID(63),
Value: []byte("?"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 181,
EndPos: 182,
},
},
Expr: &ast.Name{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 182,
EndPos: 185,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 182,
EndPos: 185,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 182,
EndPos: 185,
},
},
Value: []byte("bar"),
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 186,
EndPos: 190,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 186,
EndPos: 190,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$bar"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 186,
EndPos: 190,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 185,
EndPos: 186,
},
},
},
},
Value: []byte("$bar"),
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 190,
EndPos: 191,
},
},
DefaultValue: &ast.ExprConstFetch{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 191,
EndPos: 195,
},
Const: &ast.Name{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 191,
EndPos: 195,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 191,
EndPos: 195,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("null"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 191,
EndPos: 195,
},
},
Value: []byte("null"),
},
},
},
},
},
&ast.Parameter{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 197,
EndPos: 209,
},
Type: &ast.Name{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 197,
EndPos: 200,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 197,
EndPos: 200,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("baz"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 197,
EndPos: 200,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 196,
EndPos: 197,
},
},
},
},
Value: []byte("baz"),
},
},
},
AmpersandTkn: &token.Token{
ID: token.T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG,
Value: []byte("&"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 201,
EndPos: 202,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 200,
EndPos: 201,
},
},
},
},
VariadicTkn: &token.Token{
ID: token.T_ELLIPSIS,
Value: []byte("..."),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 202,
EndPos: 205,
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 205,
EndPos: 209,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 205,
EndPos: 209,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$baz"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 205,
EndPos: 209,
},
},
Value: []byte("$baz"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 195,
EndPos: 196,
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 209,
EndPos: 210,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 211,
EndPos: 212,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 210,
EndPos: 211,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 212,
EndPos: 213,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 213,
EndPos: 214,
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t"),
Position: &position.Position{
StartLine: 5,
EndLine: 6,
StartPos: 214,
EndPos: 216,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestCommentEndFile(t *testing.T) {
src := `<? //comment at the end)`
expected := &ast.Root{
Position: &position.Position{
StartLine: -1,
EndLine: -1,
StartPos: -1,
EndPos: -1,
},
Stmts: []ast.Vertex{},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
{
ID: token.T_COMMENT,
Value: []byte("//comment at the end)"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 24,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
// name
func TestName(t *testing.T) {
src := `<? foo();`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
Expr: &ast.ExprFunctionCall{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
Function: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("foo"),
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestFullyQualified(t *testing.T) {
src := `<? \foo();`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 10,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 10,
},
Expr: &ast.ExprFunctionCall{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
Function: &ast.NameFullyQualified{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 7,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 7,
},
},
Value: []byte("foo"),
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestRelative(t *testing.T) {
src := `<? namespace\foo();`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Expr: &ast.ExprFunctionCall{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 18,
},
Function: &ast.NameRelative{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 16,
},
NsTkn: &token.Token{
ID: token.T_NAMESPACE,
Value: []byte("namespace"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
},
Value: []byte("foo"),
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
// scalar
func TestScalarEncapsed_SimpleVar(t *testing.T) {
src := `<? "test $var";`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Expr: &ast.ScalarEncapsed{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 9,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("test "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 9,
},
},
Value: []byte("test "),
},
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 13,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 13,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$var"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 13,
},
},
Value: []byte("$var"),
},
},
},
CloseQuoteTkn: &token.Token{
ID: token.ID(34),
Value: []byte("\""),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarEncapsed_SimpleVarOneChar(t *testing.T) {
src := `<? "test $a";`
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.ScalarEncapsed{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 9,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("test "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 9,
},
},
Value: []byte("test "),
},
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
},
Value: []byte("$a"),
},
},
},
CloseQuoteTkn: &token.Token{
ID: token.ID(34),
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarEncapsed_SimpleVarEndsEcapsed(t *testing.T) {
src := `<? "test $var\"";`
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.ScalarEncapsed{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 16,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 9,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("test "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 9,
},
},
Value: []byte("test "),
},
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 13,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 13,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$var"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 13,
},
},
Value: []byte("$var"),
},
},
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("\\\""),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
},
Value: []byte("\\\""),
},
},
CloseQuoteTkn: &token.Token{
ID: token.ID(34),
Value: []byte("\""),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarEncapsed_StringVarCurveOpen(t *testing.T) {
src := `<? "=$a{$b}";`
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.ScalarEncapsed{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 5,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 5,
},
},
Value: []byte("="),
},
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 7,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 7,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 7,
},
},
Value: []byte("$a"),
},
},
&ast.ScalarEncapsedStringBrackets{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 11,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.T_CURLY_OPEN,
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
},
Value: []byte("$b"),
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
CloseQuoteTkn: &token.Token{
ID: token.ID(34),
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarEncapsed_SimpleVarPropertyFetch(t *testing.T) {
src := `<? "test $foo->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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 9,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("test "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 9,
},
},
Value: []byte("test "),
},
&ast.ExprPropertyFetch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 18,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 13,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 13,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 13,
},
},
Value: []byte("$foo"),
},
},
ObjectOperatorTkn: &token.Token{
ID: token.T_OBJECT_OPERATOR,
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarEncapsed_DollarOpenCurlyBraces(t *testing.T) {
src := `<? "test ${foo}";`
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.ScalarEncapsed{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 16,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 9,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("test "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 9,
},
},
Value: []byte("test "),
},
&ast.ScalarEncapsedStringVar{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 15,
},
DollarOpenCurlyBracketTkn: &token.Token{
ID: token.T_DOLLAR_OPEN_CURLY_BRACES,
Value: []byte("${"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 14,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING_VARNAME,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 14,
},
},
Value: []byte("foo"),
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
CloseQuoteTkn: &token.Token{
ID: token.ID(34),
Value: []byte("\""),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarEncapsed_DollarOpenCurlyBracesDimNumber(t *testing.T) {
src := `<? "test ${foo[0]}";`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 20,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 20,
},
Expr: &ast.ScalarEncapsed{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 9,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("test "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 9,
},
},
Value: []byte("test "),
},
&ast.ScalarEncapsedStringVar{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 15,
},
DollarOpenCurlyBracketTkn: &token.Token{
ID: token.T_DOLLAR_OPEN_CURLY_BRACES,
Value: []byte("${"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 14,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING_VARNAME,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 14,
},
},
Value: []byte("foo"),
},
OpenSquareBracketTkn: &token.Token{
ID: token.ID(91),
Value: []byte("["),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
Dim: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("0"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
Value: []byte("0"),
},
CloseSquareBracketTkn: &token.Token{
ID: token.ID(93),
Value: []byte("]"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
CloseQuoteTkn: &token.Token{
ID: token.ID(34),
Value: []byte("\""),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarEncapsed_CurlyOpenMethodCall(t *testing.T) {
src := `<? "test {$foo->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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 9,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("test "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 9,
},
},
Value: []byte("test "),
},
&ast.ScalarEncapsedStringBrackets{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 22,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.T_CURLY_OPEN,
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
Var: &ast.ExprMethodCall{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 21,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 14,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 14,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 14,
},
},
Value: []byte("$foo"),
},
},
ObjectOperatorTkn: &token.Token{
ID: token.T_OBJECT_OPERATOR,
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarHeredoc_HeredocSimpleLabel(t *testing.T) {
src := `<? <<<LBL
test $var
LBL;
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 24,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 24,
},
Expr: &ast.ScalarHeredoc{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 23,
},
OpenHeredocTkn: &token.Token{
ID: token.T_START_HEREDOC,
Value: []byte("<<<LBL\n"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 10,
EndPos: 15,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("test "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 10,
EndPos: 15,
},
},
Value: []byte("test "),
},
&ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 15,
EndPos: 19,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 15,
EndPos: 19,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$var"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 15,
EndPos: 19,
},
},
Value: []byte("$var"),
},
},
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 20,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("\n"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 20,
},
},
Value: []byte("\n"),
},
},
CloseHeredocTkn: &token.Token{
ID: token.T_END_HEREDOC,
Value: []byte("LBL"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 20,
EndPos: 23,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 23,
EndPos: 24,
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 24,
EndPos: 25,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarHeredoc_SimpleHeredocLabel(t *testing.T) {
src := `<? <<<"LBL"
test $var
LBL;
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 26,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 26,
},
Expr: &ast.ScalarHeredoc{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 25,
},
OpenHeredocTkn: &token.Token{
ID: token.T_START_HEREDOC,
Value: []byte("<<<\"LBL\"\n"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 17,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("test "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 17,
},
},
Value: []byte("test "),
},
&ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 17,
EndPos: 21,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 17,
EndPos: 21,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$var"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 17,
EndPos: 21,
},
},
Value: []byte("$var"),
},
},
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 21,
EndPos: 22,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("\n"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 21,
EndPos: 22,
},
},
Value: []byte("\n"),
},
},
CloseHeredocTkn: &token.Token{
ID: token.T_END_HEREDOC,
Value: []byte("LBL"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 22,
EndPos: 25,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 25,
EndPos: 26,
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 26,
EndPos: 27,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarHeredoc_SimpleNowdocLabel(t *testing.T) {
src := `<? <<<'LBL'
test $var
LBL;
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 26,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 26,
},
Expr: &ast.ScalarHeredoc{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 25,
},
OpenHeredocTkn: &token.Token{
ID: token.T_START_HEREDOC,
Value: []byte("<<<'LBL'\n"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 22,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("test $var\n"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 22,
},
},
Value: []byte("test $var\n"),
},
},
CloseHeredocTkn: &token.Token{
ID: token.T_END_HEREDOC,
Value: []byte("LBL"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 22,
EndPos: 25,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 25,
EndPos: 26,
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 26,
EndPos: 27,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarHeredoc_EmptyHeredoc(t *testing.T) {
src := `<? <<<CAD
CAD;
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 3,
EndPos: 14,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 3,
EndPos: 14,
},
Expr: &ast.ScalarHeredoc{
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 3,
EndPos: 13,
},
OpenHeredocTkn: &token.Token{
ID: token.T_START_HEREDOC,
Value: []byte("<<<CAD\n"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
CloseHeredocTkn: &token.Token{
ID: token.T_END_HEREDOC,
Value: []byte("AD"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 11,
EndPos: 13,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 13,
EndPos: 14,
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 14,
EndPos: 15,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarHeredoc_HeredocScalarString(t *testing.T) {
src := `<? <<<CAD
hello
CAD;
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 21,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 21,
},
Expr: &ast.ScalarHeredoc{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 20,
},
OpenHeredocTkn: &token.Token{
ID: token.T_START_HEREDOC,
Value: []byte("<<<CAD\n"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 10,
EndPos: 17,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("\thello\n"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 10,
EndPos: 17,
},
},
Value: []byte("\thello\n"),
},
},
CloseHeredocTkn: &token.Token{
ID: token.T_END_HEREDOC,
Value: []byte("CAD"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 17,
EndPos: 20,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 20,
EndPos: 21,
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 21,
EndPos: 22,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarMagicConstant(t *testing.T) {
// TODO: test all magic constants
src := `<? __DIR__;`
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.ScalarMagicConstant{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 10,
},
MagicConstTkn: &token.Token{
ID: token.T_DIR,
Value: []byte("__DIR__"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("__DIR__"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarNumber_LNumber(t *testing.T) {
src := `<? 1234567890123456789;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 22,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1234567890123456789"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("1234567890123456789"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarNumber_DNumber(t *testing.T) {
src := `<? 12345678901234567890;`
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.ScalarDnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
NumberTkn: &token.Token{
ID: token.T_DNUMBER,
Value: []byte("12345678901234567890"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("12345678901234567890"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 24,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarNumber_Float(t *testing.T) {
src := `<? 0.;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
Expr: &ast.ScalarDnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 5,
},
NumberTkn: &token.Token{
ID: token.T_DNUMBER,
Value: []byte("0."),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("0."),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarNumber_BinaryLNumber(t *testing.T) {
src := `<? 0b0111111111111111111111111111111111111111111111111111111111111111;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 70,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 70,
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 69,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("0b0111111111111111111111111111111111111111111111111111111111111111"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 69,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("0b0111111111111111111111111111111111111111111111111111111111111111"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 69,
EndPos: 70,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarNumber_BinaryDNumber(t *testing.T) {
src := `<? 0b1111111111111111111111111111111111111111111111111111111111111111;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 70,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 70,
},
Expr: &ast.ScalarDnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 69,
},
NumberTkn: &token.Token{
ID: token.T_DNUMBER,
Value: []byte("0b1111111111111111111111111111111111111111111111111111111111111111"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 69,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("0b1111111111111111111111111111111111111111111111111111111111111111"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 69,
EndPos: 70,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarNumber_HLNumber(t *testing.T) {
src := `<? 0x007111111111111111;`
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.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("0x007111111111111111"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("0x007111111111111111"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 24,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarNumber_HDNumber(t *testing.T) {
src := `<? 0x8111111111111111;`
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.ScalarDnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 21,
},
NumberTkn: &token.Token{
ID: token.T_DNUMBER,
Value: []byte("0x8111111111111111"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 21,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("0x8111111111111111"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarString_DoubleQuotedScalarString(t *testing.T) {
src := `<? "test";`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 10,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 10,
},
Expr: &ast.ScalarString{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
StringTkn: &token.Token{
ID: token.T_CONSTANT_ENCAPSED_STRING,
Value: []byte("\"test\""),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("\"test\""),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarString_DoubleQuotedScalarStringWithEscapedVar(t *testing.T) {
src := `<? "\$test";`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Expr: &ast.ScalarString{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
StringTkn: &token.Token{
ID: token.T_CONSTANT_ENCAPSED_STRING,
Value: []byte("\"\\$test\""),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("\"\\$test\""),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarString_MultilineDoubleQuotedScalarString(t *testing.T) {
src := `<? "
test
";`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 14,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 14,
},
Expr: &ast.ScalarString{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 13,
},
StringTkn: &token.Token{
ID: token.T_CONSTANT_ENCAPSED_STRING,
Value: []byte("\"\n\ttest\n\t\""),
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 13,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("\"\n\ttest\n\t\""),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 13,
EndPos: 14,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarString_SingleQuotedScalarString(t *testing.T) {
src := `<? '$test';`
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.ScalarString{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 10,
},
StringTkn: &token.Token{
ID: token.T_CONSTANT_ENCAPSED_STRING,
Value: []byte("'$test'"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("'$test'"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestScalarString_MultilineSingleQuotedScalarString(t *testing.T) {
src := `<? '
$test
';`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 15,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 15,
},
Expr: &ast.ScalarString{
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 14,
},
StringTkn: &token.Token{
ID: token.T_CONSTANT_ENCAPSED_STRING,
Value: []byte("'\n\t$test\n\t'"),
Position: &position.Position{
StartLine: 1,
EndLine: 3,
StartPos: 3,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("'\n\t$test\n\t'"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 14,
EndPos: 15,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
// stmt
func TestStmtAltIf_AltIf(t *testing.T) {
src := `<?
if ($a) :
endif;
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 5,
EndPos: 23,
},
Stmts: []ast.Vertex{
&ast.StmtIf{
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 5,
EndPos: 23,
},
IfTkn: &token.Token{
ID: token.T_IF,
Value: []byte("if"),
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: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 8,
EndPos: 9,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 7,
EndPos: 8,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 11,
},
},
Value: []byte("$a"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 11,
EndPos: 12,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: -1,
EndLine: -1,
StartPos: -1,
EndPos: -1,
},
Stmts: []ast.Vertex{},
},
EndIfTkn: &token.Token{
ID: token.T_ENDIF,
Value: []byte("endif"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 17,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 14,
EndPos: 17,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 22,
EndPos: 23,
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t"),
Position: &position.Position{
StartLine: 3,
EndLine: 4,
StartPos: 23,
EndPos: 25,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtAltIf_AltElseIf(t *testing.T) {
src := `<?
if ($a) :
elseif ($b):
endif;
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 4,
StartPos: 5,
EndPos: 38,
},
Stmts: []ast.Vertex{
&ast.StmtIf{
Position: &position.Position{
StartLine: 2,
EndLine: 4,
StartPos: 5,
EndPos: 38,
},
IfTkn: &token.Token{
ID: token.T_IF,
Value: []byte("if"),
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: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 8,
EndPos: 9,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 7,
EndPos: 8,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 11,
},
},
Value: []byte("$a"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 11,
EndPos: 12,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: -1,
EndLine: -1,
StartPos: -1,
EndPos: -1,
},
Stmts: []ast.Vertex{},
},
ElseIf: []ast.Vertex{
&ast.StmtElseIf{
Position: &position.Position{
StartLine: 3,
EndLine: -1,
StartPos: 17,
EndPos: -1,
},
ElseIfTkn: &token.Token{
ID: token.T_ELSEIF,
Value: []byte("elseif"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 17,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 14,
EndPos: 17,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 24,
EndPos: 25,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 23,
EndPos: 24,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 25,
EndPos: 27,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 25,
EndPos: 27,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 25,
EndPos: 27,
},
},
Value: []byte("$b"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 27,
EndPos: 28,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 28,
EndPos: 29,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: -1,
EndLine: -1,
StartPos: -1,
EndPos: -1,
},
Stmts: []ast.Vertex{},
},
},
},
EndIfTkn: &token.Token{
ID: token.T_ENDIF,
Value: []byte("endif"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 32,
EndPos: 37,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 3,
EndLine: 4,
StartPos: 29,
EndPos: 32,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 37,
EndPos: 38,
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t"),
Position: &position.Position{
StartLine: 4,
EndLine: 5,
StartPos: 38,
EndPos: 40,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtAltIf_AltElse(t *testing.T) {
src := `<?
if ($a) :
else:
endif;
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 4,
StartPos: 5,
EndPos: 31,
},
Stmts: []ast.Vertex{
&ast.StmtIf{
Position: &position.Position{
StartLine: 2,
EndLine: 4,
StartPos: 5,
EndPos: 31,
},
IfTkn: &token.Token{
ID: token.T_IF,
Value: []byte("if"),
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: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 8,
EndPos: 9,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 7,
EndPos: 8,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 11,
},
},
Value: []byte("$a"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 11,
EndPos: 12,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: -1,
EndLine: -1,
StartPos: -1,
EndPos: -1,
},
Stmts: []ast.Vertex{},
},
Else: &ast.StmtElse{
Position: &position.Position{
StartLine: 3,
EndLine: -1,
StartPos: 17,
EndPos: -1,
},
ElseTkn: &token.Token{
ID: token.T_ELSE,
Value: []byte("else"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 17,
EndPos: 21,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 14,
EndPos: 17,
},
},
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 21,
EndPos: 22,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: -1,
EndLine: -1,
StartPos: -1,
EndPos: -1,
},
Stmts: []ast.Vertex{},
},
},
EndIfTkn: &token.Token{
ID: token.T_ENDIF,
Value: []byte("endif"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 25,
EndPos: 30,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 3,
EndLine: 4,
StartPos: 22,
EndPos: 25,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 30,
EndPos: 31,
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t"),
Position: &position.Position{
StartLine: 4,
EndLine: 5,
StartPos: 31,
EndPos: 33,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtAltIf_AltElseElseIf(t *testing.T) {
src := `<?
if ($a) :
elseif ($b):
elseif ($c):
else:
endif;
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 6,
StartPos: 5,
EndPos: 61,
},
Stmts: []ast.Vertex{
&ast.StmtIf{
Position: &position.Position{
StartLine: 2,
EndLine: 6,
StartPos: 5,
EndPos: 61,
},
IfTkn: &token.Token{
ID: token.T_IF,
Value: []byte("if"),
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: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 8,
EndPos: 9,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 7,
EndPos: 8,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 11,
},
},
Value: []byte("$a"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 11,
EndPos: 12,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: -1,
EndLine: -1,
StartPos: -1,
EndPos: -1,
},
Stmts: []ast.Vertex{},
},
ElseIf: []ast.Vertex{
&ast.StmtElseIf{
Position: &position.Position{
StartLine: 3,
EndLine: -1,
StartPos: 17,
EndPos: -1,
},
ElseIfTkn: &token.Token{
ID: token.T_ELSEIF,
Value: []byte("elseif"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 17,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 14,
EndPos: 17,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 24,
EndPos: 25,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 23,
EndPos: 24,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 25,
EndPos: 27,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 25,
EndPos: 27,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 25,
EndPos: 27,
},
},
Value: []byte("$b"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 27,
EndPos: 28,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 28,
EndPos: 29,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: -1,
EndLine: -1,
StartPos: -1,
EndPos: -1,
},
Stmts: []ast.Vertex{},
},
},
&ast.StmtElseIf{
Position: &position.Position{
StartLine: 4,
EndLine: -1,
StartPos: 32,
EndPos: -1,
},
ElseIfTkn: &token.Token{
ID: token.T_ELSEIF,
Value: []byte("elseif"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 32,
EndPos: 38,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 3,
EndLine: 4,
StartPos: 29,
EndPos: 32,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 39,
EndPos: 40,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 38,
EndPos: 39,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 40,
EndPos: 42,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 40,
EndPos: 42,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$c"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 40,
EndPos: 42,
},
},
Value: []byte("$c"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 42,
EndPos: 43,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 43,
EndPos: 44,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: -1,
EndLine: -1,
StartPos: -1,
EndPos: -1,
},
Stmts: []ast.Vertex{},
},
},
},
Else: &ast.StmtElse{
Position: &position.Position{
StartLine: 5,
EndLine: -1,
StartPos: 47,
EndPos: -1,
},
ElseTkn: &token.Token{
ID: token.T_ELSE,
Value: []byte("else"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 47,
EndPos: 51,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 4,
EndLine: 5,
StartPos: 44,
EndPos: 47,
},
},
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 51,
EndPos: 52,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: -1,
EndLine: -1,
StartPos: -1,
EndPos: -1,
},
Stmts: []ast.Vertex{},
},
},
EndIfTkn: &token.Token{
ID: token.T_ENDIF,
Value: []byte("endif"),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 55,
EndPos: 60,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 5,
EndLine: 6,
StartPos: 52,
EndPos: 55,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 60,
EndPos: 61,
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t"),
Position: &position.Position{
StartLine: 6,
EndLine: 7,
StartPos: 61,
EndPos: 63,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtClassConstList(t *testing.T) {
src := `<? class foo{ public const FOO = 1, BAR = 2; }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 46,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 46,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
Stmts: []ast.Vertex{
&ast.StmtClassConstList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 44,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 20,
},
IdentifierTkn: &token.Token{
ID: token.T_PUBLIC,
Value: []byte("public"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
Value: []byte("public"),
},
},
ConstTkn: &token.Token{
ID: token.T_CONST,
Value: []byte("const"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 26,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
},
},
Consts: []ast.Vertex{
&ast.StmtConstant{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 34,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 30,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("FOO"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 30,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
},
},
},
Value: []byte("FOO"),
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 31,
EndPos: 32,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 31,
},
},
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 34,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 34,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 33,
},
},
},
},
Value: []byte("1"),
},
},
&ast.StmtConstant{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 43,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 39,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("BAR"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 39,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 36,
},
},
},
},
Value: []byte("BAR"),
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 40,
EndPos: 41,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 39,
EndPos: 40,
},
},
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 42,
EndPos: 43,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("2"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 42,
EndPos: 43,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 41,
EndPos: 42,
},
},
},
},
Value: []byte("2"),
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 34,
EndPos: 35,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 43,
EndPos: 44,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 45,
EndPos: 46,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 44,
EndPos: 45,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtClassConstList_WithoutModifiers(t *testing.T) {
src := `<? class foo{ const FOO = 1, BAR = 2; }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 39,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 39,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
Stmts: []ast.Vertex{
&ast.StmtClassConstList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 37,
},
ConstTkn: &token.Token{
ID: token.T_CONST,
Value: []byte("const"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
Consts: []ast.Vertex{
&ast.StmtConstant{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 27,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 23,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("FOO"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
},
},
Value: []byte("FOO"),
},
EqualTkn: &token.Token{
ID: token.ID(61),
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,
},
},
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
},
},
},
Value: []byte("1"),
},
},
&ast.StmtConstant{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 36,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 32,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("BAR"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 32,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 29,
},
},
},
},
Value: []byte("BAR"),
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 34,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 33,
},
},
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 36,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("2"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 36,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 34,
EndPos: 35,
},
},
},
},
Value: []byte("2"),
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 28,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 37,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 38,
EndPos: 39,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 38,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtClassMethod_SimpleClassMethod(t *testing.T) {
src := `<? class foo{ function bar() {} }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 33,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 33,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
Stmts: []ast.Vertex{
&ast.StmtClassMethod{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 31,
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 26,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 26,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
Value: []byte("bar"),
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
},
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,
},
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 33,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 31,
EndPos: 32,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtClassMethod_PrivateProtectedClassMethod(t *testing.T) {
src := `<? class foo{ final private function bar() {} protected function baz() {} }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 75,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 75,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
Stmts: []ast.Vertex{
&ast.StmtClassMethod{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 45,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 19,
},
IdentifierTkn: &token.Token{
ID: token.T_FINAL,
Value: []byte("final"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
Value: []byte("final"),
},
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 27,
},
IdentifierTkn: &token.Token{
ID: token.T_PRIVATE,
Value: []byte("private"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
},
},
Value: []byte("private"),
},
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 36,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 28,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 40,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 40,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 37,
},
},
},
},
Value: []byte("bar"),
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 40,
EndPos: 41,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 41,
EndPos: 42,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 43,
EndPos: 45,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 43,
EndPos: 44,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 42,
EndPos: 43,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 44,
EndPos: 45,
},
},
},
},
&ast.StmtClassMethod{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 46,
EndPos: 73,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 46,
EndPos: 55,
},
IdentifierTkn: &token.Token{
ID: token.T_PROTECTED,
Value: []byte("protected"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 46,
EndPos: 55,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 45,
EndPos: 46,
},
},
},
},
Value: []byte("protected"),
},
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 56,
EndPos: 64,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 55,
EndPos: 56,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 65,
EndPos: 68,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 65,
EndPos: 68,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 64,
EndPos: 65,
},
},
},
},
Value: []byte("baz"),
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 68,
EndPos: 69,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 69,
EndPos: 70,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 71,
EndPos: 73,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 71,
EndPos: 72,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 70,
EndPos: 71,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 72,
EndPos: 73,
},
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 74,
EndPos: 75,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 73,
EndPos: 74,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtClassMethod_Php8ClassMethod(t *testing.T) {
src := `<? class foo{ public static function &bar(): void {} }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 54,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 54,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
Stmts: []ast.Vertex{
&ast.StmtClassMethod{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 52,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 20,
},
IdentifierTkn: &token.Token{
ID: token.T_PUBLIC,
Value: []byte("public"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
Value: []byte("public"),
},
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 27,
},
IdentifierTkn: &token.Token{
ID: token.T_STATIC,
Value: []byte("static"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
},
},
Value: []byte("static"),
},
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 36,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 28,
},
},
},
},
AmpersandTkn: &token.Token{
ID: token.T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG,
Value: []byte("&"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 38,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 37,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 38,
EndPos: 41,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 38,
EndPos: 41,
},
},
Value: []byte("bar"),
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 41,
EndPos: 42,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 42,
EndPos: 43,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 43,
EndPos: 44,
},
},
ReturnType: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 45,
EndPos: 49,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 45,
EndPos: 49,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("void"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 45,
EndPos: 49,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 44,
EndPos: 45,
},
},
},
},
Value: []byte("void"),
},
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 50,
EndPos: 52,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 50,
EndPos: 51,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 49,
EndPos: 50,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 51,
EndPos: 52,
},
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 53,
EndPos: 54,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 52,
EndPos: 53,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtClassMethod_AbstractClassMethod(t *testing.T) {
src := `<? abstract class Foo{ abstract public function bar(); }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 56,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 56,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_ABSTRACT,
Value: []byte("abstract"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("abstract"),
},
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 17,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("Foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
Stmts: []ast.Vertex{
&ast.StmtClassMethod{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 54,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 31,
},
IdentifierTkn: &token.Token{
ID: token.T_ABSTRACT,
Value: []byte("abstract"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 31,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
Value: []byte("abstract"),
},
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 38,
},
IdentifierTkn: &token.Token{
ID: token.T_PUBLIC,
Value: []byte("public"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 38,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 31,
EndPos: 32,
},
},
},
},
Value: []byte("public"),
},
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 39,
EndPos: 47,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 38,
EndPos: 39,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 48,
EndPos: 51,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 48,
EndPos: 51,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 47,
EndPos: 48,
},
},
},
},
Value: []byte("bar"),
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 51,
EndPos: 52,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 52,
EndPos: 53,
},
},
Stmt: &ast.StmtNop{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 53,
EndPos: 54,
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 53,
EndPos: 54,
},
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 55,
EndPos: 56,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 54,
EndPos: 55,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtClassMethod_Php8AbstractClassMethod(t *testing.T) {
src := `<? abstract class Foo{ public function bar(): void; }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 53,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 53,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_ABSTRACT,
Value: []byte("abstract"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("abstract"),
},
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 17,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("Foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
Stmts: []ast.Vertex{
&ast.StmtClassMethod{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 51,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 29,
},
IdentifierTkn: &token.Token{
ID: token.T_PUBLIC,
Value: []byte("public"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 29,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
Value: []byte("public"),
},
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 38,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 30,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 39,
EndPos: 42,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 39,
EndPos: 42,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 38,
EndPos: 39,
},
},
},
},
Value: []byte("bar"),
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 42,
EndPos: 43,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 43,
EndPos: 44,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 44,
EndPos: 45,
},
},
ReturnType: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 46,
EndPos: 50,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 46,
EndPos: 50,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("void"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 46,
EndPos: 50,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 45,
EndPos: 46,
},
},
},
},
Value: []byte("void"),
},
},
},
Stmt: &ast.StmtNop{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 50,
EndPos: 51,
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 50,
EndPos: 51,
},
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 52,
EndPos: 53,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 51,
EndPos: 52,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtClass_SimpleClass(t *testing.T) {
src := `<? class foo{ }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtClass_AbstractClass(t *testing.T) {
src := `<? abstract class foo{ }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 24,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 24,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_ABSTRACT,
Value: []byte("abstract"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("abstract"),
},
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 17,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 24,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtClass_ClassExtends(t *testing.T) {
src := `<? final class foo extends bar { }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 34,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 34,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
IdentifierTkn: &token.Token{
ID: token.T_FINAL,
Value: []byte("final"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("final"),
},
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 18,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
Value: []byte("foo"),
},
ExtendsTkn: &token.Token{
ID: token.T_EXTENDS,
Value: []byte("extends"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 26,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
Extends: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 30,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 30,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 30,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
},
},
},
Value: []byte("bar"),
},
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 31,
EndPos: 32,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 31,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 34,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 33,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtClass_ClassImplement(t *testing.T) {
src := `<? final class foo implements bar { }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 37,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 37,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
IdentifierTkn: &token.Token{
ID: token.T_FINAL,
Value: []byte("final"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("final"),
},
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 18,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
Value: []byte("foo"),
},
ImplementsTkn: &token.Token{
ID: token.T_IMPLEMENTS,
Value: []byte("implements"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 29,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
Implements: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 33,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 33,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 33,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 30,
},
},
},
},
Value: []byte("bar"),
},
},
},
},
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: 36,
EndPos: 37,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 36,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtClass_ClassImplements(t *testing.T) {
src := `<? final class foo implements bar, baz { }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 42,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 42,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
IdentifierTkn: &token.Token{
ID: token.T_FINAL,
Value: []byte("final"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("final"),
},
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 18,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
Value: []byte("foo"),
},
ImplementsTkn: &token.Token{
ID: token.T_IMPLEMENTS,
Value: []byte("implements"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 29,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
Implements: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 33,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 33,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 33,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 30,
},
},
},
},
Value: []byte("bar"),
},
},
},
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 38,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 38,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 38,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 34,
EndPos: 35,
},
},
},
},
Value: []byte("baz"),
},
},
},
},
ImplementsSeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 34,
},
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 39,
EndPos: 40,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 38,
EndPos: 39,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 41,
EndPos: 42,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 40,
EndPos: 41,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtClass_AnonimousClass(t *testing.T) {
src := `<? new class() extends foo implements bar, baz { };`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 51,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 51,
},
Expr: &ast.ExprNew{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 50,
},
NewTkn: &token.Token{
ID: token.T_NEW,
Value: []byte("new"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Class: &ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 50,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
ExtendsTkn: &token.Token{
ID: token.T_EXTENDS,
Value: []byte("extends"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
Extends: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 26,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 26,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 26,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
Value: []byte("foo"),
},
},
},
ImplementsTkn: &token.Token{
ID: token.T_IMPLEMENTS,
Value: []byte("implements"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 37,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
},
},
},
Implements: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 38,
EndPos: 41,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 38,
EndPos: 41,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 38,
EndPos: 41,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 38,
},
},
},
},
Value: []byte("bar"),
},
},
},
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 43,
EndPos: 46,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 43,
EndPos: 46,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 43,
EndPos: 46,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 42,
EndPos: 43,
},
},
},
},
Value: []byte("baz"),
},
},
},
},
ImplementsSeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 41,
EndPos: 42,
},
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 47,
EndPos: 48,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 46,
EndPos: 47,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 49,
EndPos: 50,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 48,
EndPos: 49,
},
},
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 50,
EndPos: 51,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtConstList(t *testing.T) {
src := `<? const FOO = 1, BAR = 2;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 26,
},
Stmts: []ast.Vertex{
&ast.StmtConstList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 26,
},
ConstTkn: &token.Token{
ID: token.T_CONST,
Value: []byte("const"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Consts: []ast.Vertex{
&ast.StmtConstant{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 16,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("FOO"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("FOO"),
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Expr: &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"),
},
},
&ast.StmtConstant{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 25,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("BAR"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("BAR"),
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("2"),
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,
},
},
},
},
Value: []byte("2"),
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtContinue_Empty(t *testing.T) {
src := `<? while (1) { continue; }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 26,
},
Stmts: []ast.Vertex{
&ast.StmtWhile{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 26,
},
WhileTkn: &token.Token{
ID: token.T_WHILE,
Value: []byte("while"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
Value: []byte("1"),
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 26,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtContinue{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 24,
},
ContinueTkn: &token.Token{
ID: token.T_CONTINUE,
Value: []byte("continue"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
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: 23,
EndPos: 24,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtContinue_Light(t *testing.T) {
src := `<? while (1) { continue 2; }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 28,
},
Stmts: []ast.Vertex{
&ast.StmtWhile{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 28,
},
WhileTkn: &token.Token{
ID: token.T_WHILE,
Value: []byte("while"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
Value: []byte("1"),
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 28,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtContinue{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 26,
},
ContinueTkn: &token.Token{
ID: token.T_CONTINUE,
Value: []byte("continue"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("2"),
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,
},
},
},
},
Value: []byte("2"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 28,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtContinue(t *testing.T) {
src := `<? while (1) { continue(3); }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 29,
},
Stmts: []ast.Vertex{
&ast.StmtWhile{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 29,
},
WhileTkn: &token.Token{
ID: token.T_WHILE,
Value: []byte("while"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
Value: []byte("1"),
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 29,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtContinue{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 27,
},
ContinueTkn: &token.Token{
ID: token.T_CONTINUE,
Value: []byte("continue"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
Expr: &ast.ExprBrackets{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 26,
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 24,
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("3"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
},
Value: []byte("3"),
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
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,
},
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtDeclare(t *testing.T) {
src := `<? declare(ticks=1);`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 20,
},
Stmts: []ast.Vertex{
&ast.StmtDeclare{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 20,
},
DeclareTkn: &token.Token{
ID: token.T_DECLARE,
Value: []byte("declare"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
Consts: []ast.Vertex{
&ast.StmtConstant{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 18,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 16,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("ticks"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 16,
},
},
Value: []byte("ticks"),
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
Value: []byte("1"),
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
Stmt: &ast.StmtNop{
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: 19,
EndPos: 20,
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtDeclare_Stmts(t *testing.T) {
src := `<? declare(ticks=1, strict_types=1) {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 38,
},
Stmts: []ast.Vertex{
&ast.StmtDeclare{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 38,
},
DeclareTkn: &token.Token{
ID: token.T_DECLARE,
Value: []byte("declare"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
Consts: []ast.Vertex{
&ast.StmtConstant{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 18,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 16,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("ticks"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 16,
},
},
Value: []byte("ticks"),
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
Value: []byte("1"),
},
},
&ast.StmtConstant{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 34,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 32,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("strict_types"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 32,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
},
},
Value: []byte("strict_types"),
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 33,
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 34,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 34,
},
},
Value: []byte("1"),
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 34,
EndPos: 35,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 38,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 37,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 36,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 38,
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtDeclare_Alt(t *testing.T) {
src := `<? declare(ticks=1): enddeclare;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 32,
},
Stmts: []ast.Vertex{
&ast.StmtDeclare{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 32,
},
DeclareTkn: &token.Token{
ID: token.T_DECLARE,
Value: []byte("declare"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
Consts: []ast.Vertex{
&ast.StmtConstant{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 18,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 16,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("ticks"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 16,
},
},
Value: []byte("ticks"),
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
Value: []byte("1"),
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: -1,
EndLine: -1,
StartPos: -1,
EndPos: -1,
},
Stmts: []ast.Vertex{},
},
EndDeclareTkn: &token.Token{
ID: token.T_ENDDECLARE,
Value: []byte("enddeclare"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 31,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
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: 31,
EndPos: 32,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtDo(t *testing.T) {
src := `<? do {} while(1);`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 18,
},
Stmts: []ast.Vertex{
&ast.StmtDo{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 18,
},
DoTkn: &token.Token{
ID: token.T_DO,
Value: []byte("do"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 8,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
WhileTkn: &token.Token{
ID: token.T_WHILE,
Value: []byte("while"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
Cond: &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,
},
},
Value: []byte("1"),
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtEcho(t *testing.T) {
src := `<? echo $a, 1;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Stmts: []ast.Vertex{
&ast.StmtEcho{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
EchoTkn: &token.Token{
ID: token.T_ECHO,
Value: []byte("echo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Exprs: []ast.Vertex{
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
},
Value: []byte("$a"),
},
},
&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,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
Value: []byte("1"),
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtEcho_Parenthesis(t *testing.T) {
src := `<? echo($a);`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Stmts: []ast.Vertex{
&ast.StmtEcho{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
EchoTkn: &token.Token{
ID: token.T_ECHO,
Value: []byte("echo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Exprs: []ast.Vertex{
&ast.ExprBrackets{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 11,
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
},
Value: []byte("$a"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtExpression(t *testing.T) {
src := `<? 1;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 5,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 5,
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 4,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("1"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 5,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtFor(t *testing.T) {
src := `<? for($i = 0; $i < 10; $i++, $i++) {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 38,
},
Stmts: []ast.Vertex{
&ast.StmtFor{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 38,
},
ForTkn: &token.Token{
ID: token.T_FOR,
Value: []byte("for"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
Init: []ast.Vertex{
&ast.ExprAssign{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 13,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$i"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
},
Value: []byte("$i"),
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
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,
},
},
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("0"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
Value: []byte("0"),
},
},
},
InitSemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
Cond: []ast.Vertex{
&ast.ExprBinarySmaller{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 22,
},
Left: &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("$i"),
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("$i"),
},
},
OpTkn: &token.Token{
ID: token.ID(60),
Value: []byte("<"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Right: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 22,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("10"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
},
},
Value: []byte("10"),
},
},
},
CondSemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
Loop: []ast.Vertex{
&ast.ExprPostInc{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 28,
},
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("$i"),
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("$i"),
},
},
IncTkn: &token.Token{
ID: token.T_INC,
Value: []byte("++"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 28,
},
},
},
&ast.ExprPostInc{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 34,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 32,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 32,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$i"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 32,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 30,
},
},
},
},
Value: []byte("$i"),
},
},
IncTkn: &token.Token{
ID: token.T_INC,
Value: []byte("++"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 34,
},
},
},
},
LoopSeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 29,
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 34,
EndPos: 35,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 38,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 37,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 36,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 38,
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtFor_Alt(t *testing.T) {
src := `<? for(; $i < 10; $i++) : endfor;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 33,
},
Stmts: []ast.Vertex{
&ast.StmtFor{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 33,
},
ForTkn: &token.Token{
ID: token.T_FOR,
Value: []byte("for"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
InitSemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
Cond: []ast.Vertex{
&ast.ExprBinarySmaller{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 16,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$i"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("$i"),
},
},
OpTkn: &token.Token{
ID: token.ID(60),
Value: []byte("<"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
Right: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("10"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
Value: []byte("10"),
},
},
},
CondSemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
Loop: []ast.Vertex{
&ast.ExprPostInc{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 22,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$i"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("$i"),
},
},
IncTkn: &token.Token{
ID: token.T_INC,
Value: []byte("++"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 22,
},
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
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,
},
},
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: -1,
EndLine: -1,
StartPos: -1,
EndPos: -1,
},
Stmts: []ast.Vertex{},
},
EndForTkn: &token.Token{
ID: token.T_ENDFOR,
Value: []byte("endfor"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 32,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 33,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtForeach(t *testing.T) {
src := `<? foreach ($a as $v) {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 24,
},
Stmts: []ast.Vertex{
&ast.StmtForeach{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 24,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
},
Value: []byte("$a"),
},
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
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,
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$v"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("$v"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 24,
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtForeach_Expr(t *testing.T) {
src := `<? foreach ([] as $v) {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 24,
},
Stmts: []ast.Vertex{
&ast.StmtForeach{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 24,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
Expr: &ast.ExprArray{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
OpenBracketTkn: &token.Token{
ID: token.ID(91),
Value: []byte("["),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(93),
Value: []byte("]"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
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,
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$v"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("$v"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 24,
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtForeach_Alt(t *testing.T) {
src := `<? foreach ($a as $v) : endforeach;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 35,
},
Stmts: []ast.Vertex{
&ast.StmtForeach{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 35,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
},
Value: []byte("$a"),
},
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
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,
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$v"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("$v"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: -1,
EndLine: -1,
StartPos: -1,
EndPos: -1,
},
Stmts: []ast.Vertex{},
},
EndForeachTkn: &token.Token{
ID: token.T_ENDFOREACH,
Value: []byte("endforeach"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 34,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 24,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 34,
EndPos: 35,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtForeach_WithKey(t *testing.T) {
src := `<? foreach ($a as $k => $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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
},
Value: []byte("$a"),
},
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
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,
},
},
},
},
Key: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$k"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("$k"),
},
},
DoubleArrowTkn: &token.Token{
ID: token.T_DOUBLE_ARROW,
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtForeach_ExprWithKey(t *testing.T) {
src := `<? foreach ([] as $k => $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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
Expr: &ast.ExprArray{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
OpenBracketTkn: &token.Token{
ID: token.ID(91),
Value: []byte("["),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(93),
Value: []byte("]"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
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,
},
},
},
},
Key: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$k"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("$k"),
},
},
DoubleArrowTkn: &token.Token{
ID: token.T_DOUBLE_ARROW,
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtForeach_WithRef(t *testing.T) {
src := `<? foreach ($a as $k => &$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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
},
Value: []byte("$a"),
},
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
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,
},
},
},
},
Key: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$k"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("$k"),
},
},
DoubleArrowTkn: &token.Token{
ID: token.T_DOUBLE_ARROW,
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.T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG,
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtForeach_WithList(t *testing.T) {
src := `<? foreach ($a as $k => 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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
},
Value: []byte("$a"),
},
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
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,
},
},
},
},
Key: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$k"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("$k"),
},
},
DoubleArrowTkn: &token.Token{
ID: token.T_DOUBLE_ARROW,
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtFunction(t *testing.T) {
src := `<? function foo() {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 20,
},
Stmts: []ast.Vertex{
&ast.StmtFunction{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 20,
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
Value: []byte("foo"),
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtFunction_Return(t *testing.T) {
src := `<? function foo() {return;}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 27,
},
Stmts: []ast.Vertex{
&ast.StmtFunction{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 27,
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
Value: []byte("foo"),
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtReturn{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 26,
},
ReturnTkn: &token.Token{
ID: token.T_RETURN,
Value: []byte("return"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 25,
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtFunction_ReturnVar(t *testing.T) {
src := `<? function foo(array $a, callable $b) {return $a;}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 51,
},
Stmts: []ast.Vertex{
&ast.StmtFunction{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 51,
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
Value: []byte("foo"),
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
Params: []ast.Vertex{
&ast.Parameter{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 24,
},
Type: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 21,
},
IdentifierTkn: &token.Token{
ID: token.T_ARRAY,
Value: []byte("array"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 21,
},
},
Value: []byte("array"),
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
},
},
Value: []byte("$a"),
},
},
},
&ast.Parameter{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 37,
},
Type: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 34,
},
IdentifierTkn: &token.Token{
ID: token.T_CALLABLE,
Value: []byte("callable"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 34,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
},
},
},
Value: []byte("callable"),
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 37,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 37,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 37,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 34,
EndPos: 35,
},
},
},
},
Value: []byte("$b"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 38,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 39,
EndPos: 40,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 38,
EndPos: 39,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtReturn{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 40,
EndPos: 50,
},
ReturnTkn: &token.Token{
ID: token.T_RETURN,
Value: []byte("return"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 40,
EndPos: 46,
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 47,
EndPos: 49,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 47,
EndPos: 49,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 47,
EndPos: 49,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 46,
EndPos: 47,
},
},
},
},
Value: []byte("$a"),
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 49,
EndPos: 50,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 50,
EndPos: 51,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtFunction_Ref(t *testing.T) {
src := `<? function &foo() {return 1;}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 30,
},
Stmts: []ast.Vertex{
&ast.StmtFunction{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 30,
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
AmpersandTkn: &token.Token{
ID: token.T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG,
Value: []byte("&"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
},
Value: []byte("foo"),
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtReturn{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 29,
},
ReturnTkn: &token.Token{
ID: token.T_RETURN,
Value: []byte("return"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 26,
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 28,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 28,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
},
},
},
Value: []byte("1"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 29,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 30,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtFunction_ReturnType(t *testing.T) {
src := `<? function &foo(): void {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 27,
},
Stmts: []ast.Vertex{
&ast.StmtFunction{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 27,
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
AmpersandTkn: &token.Token{
ID: token.T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG,
Value: []byte("&"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
},
Value: []byte("foo"),
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
ReturnType: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 24,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 24,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("void"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 24,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
},
},
Value: []byte("void"),
},
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtGlobal(t *testing.T) {
src := `<? global $a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
Stmts: []ast.Vertex{
&ast.StmtGlobal{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
GlobalTkn: &token.Token{
ID: token.T_GLOBAL,
Value: []byte("global"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Vars: []ast.Vertex{
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtGlobal_Vars(t *testing.T) {
src := `<? global $a, $b, $$c, ${foo()};`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 32,
},
Stmts: []ast.Vertex{
&ast.StmtGlobal{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 32,
},
GlobalTkn: &token.Token{
ID: token.T_GLOBAL,
Value: []byte("global"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Vars: []ast.Vertex{
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
},
},
Value: []byte("$a"),
},
},
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
Value: []byte("$b"),
},
},
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
DollarTkn: &token.Token{
ID: token.ID(36),
Value: []byte("$"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Name: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 21,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 21,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$c"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 21,
},
},
Value: []byte("$c"),
},
},
},
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 31,
},
DollarTkn: &token.Token{
ID: token.ID(36),
Value: []byte("$"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 24,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
},
Name: &ast.ExprFunctionCall{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 30,
},
Function: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 28,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 28,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 28,
},
},
Value: []byte("foo"),
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 29,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 30,
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 31,
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 31,
EndPos: 32,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtGotoLabel(t *testing.T) {
src := `<? a: goto a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
Stmts: []ast.Vertex{
&ast.StmtLabel{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 5,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 4,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("a"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("a"),
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 5,
},
},
},
&ast.StmtGoto{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 13,
},
GotoTkn: &token.Token{
ID: token.T_GOTO,
Value: []byte("goto"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
Label: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
Value: []byte("a"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtHaltCompiler(t *testing.T) {
src := `<? __halt_compiler();`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 21,
},
Stmts: []ast.Vertex{
&ast.StmtHaltCompiler{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 21,
},
HaltCompilerTkn: &token.Token{
ID: token.T_HALT_COMPILER,
Value: []byte("__halt_compiler"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
CloseParenthesisTkn: &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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtIf(t *testing.T) {
src := `<? if ($a) {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
Stmts: []ast.Vertex{
&ast.StmtIf{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
IfTkn: &token.Token{
ID: token.T_IF,
Value: []byte("if"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
},
Value: []byte("$a"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 13,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtIf_ElseIf(t *testing.T) {
src := `<? if ($a) {} elseif ($b) {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 28,
},
Stmts: []ast.Vertex{
&ast.StmtIf{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 28,
},
IfTkn: &token.Token{
ID: token.T_IF,
Value: []byte("if"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
},
Value: []byte("$a"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 13,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
ElseIf: []ast.Vertex{
&ast.StmtElseIf{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 28,
},
ElseIfTkn: &token.Token{
ID: token.T_ELSEIF,
Value: []byte("elseif"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
},
Value: []byte("$b"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 28,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 28,
},
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtIf_Else(t *testing.T) {
src := `<? if ($a) {} else {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 21,
},
Stmts: []ast.Vertex{
&ast.StmtIf{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 21,
},
IfTkn: &token.Token{
ID: token.T_IF,
Value: []byte("if"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
},
Value: []byte("$a"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 13,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
Else: &ast.StmtElse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 21,
},
ElseTkn: &token.Token{
ID: token.T_ELSE,
Value: []byte("else"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 21,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtIf_ElseElseIf(t *testing.T) {
src := `<? if ($a) {} elseif ($b) {} elseif ($c) {} else {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 51,
},
Stmts: []ast.Vertex{
&ast.StmtIf{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 51,
},
IfTkn: &token.Token{
ID: token.T_IF,
Value: []byte("if"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
},
Value: []byte("$a"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 13,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
ElseIf: []ast.Vertex{
&ast.StmtElseIf{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 28,
},
ElseIfTkn: &token.Token{
ID: token.T_ELSEIF,
Value: []byte("elseif"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
},
Value: []byte("$b"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 28,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 28,
},
},
},
},
&ast.StmtElseIf{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 43,
},
ElseIfTkn: &token.Token{
ID: token.T_ELSEIF,
Value: []byte("elseif"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 35,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 29,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 37,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 36,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 39,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 39,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$c"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 39,
},
},
Value: []byte("$c"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 39,
EndPos: 40,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 41,
EndPos: 43,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 41,
EndPos: 42,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 40,
EndPos: 41,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 42,
EndPos: 43,
},
},
},
},
},
Else: &ast.StmtElse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 44,
EndPos: 51,
},
ElseTkn: &token.Token{
ID: token.T_ELSE,
Value: []byte("else"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 44,
EndPos: 48,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 43,
EndPos: 44,
},
},
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 49,
EndPos: 51,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 49,
EndPos: 50,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 48,
EndPos: 49,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 50,
EndPos: 51,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtIf_ElseIfElseIfElse(t *testing.T) {
src := `<? if ($a) {} elseif ($b) {} else if ($c) {} else {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 52,
},
Stmts: []ast.Vertex{
&ast.StmtIf{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 52,
},
IfTkn: &token.Token{
ID: token.T_IF,
Value: []byte("if"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
},
Value: []byte("$a"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 13,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
ElseIf: []ast.Vertex{
&ast.StmtElseIf{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 28,
},
ElseIfTkn: &token.Token{
ID: token.T_ELSEIF,
Value: []byte("elseif"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
},
Value: []byte("$b"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 28,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 28,
},
},
},
},
},
Else: &ast.StmtElse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 52,
},
ElseTkn: &token.Token{
ID: token.T_ELSE,
Value: []byte("else"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 33,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 29,
},
},
},
},
Stmt: &ast.StmtIf{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 34,
EndPos: 52,
},
IfTkn: &token.Token{
ID: token.T_IF,
Value: []byte("if"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 34,
EndPos: 36,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 34,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 38,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 37,
},
},
},
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 38,
EndPos: 40,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 38,
EndPos: 40,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$c"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 38,
EndPos: 40,
},
},
Value: []byte("$c"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 40,
EndPos: 41,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 42,
EndPos: 44,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 42,
EndPos: 43,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 41,
EndPos: 42,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 43,
EndPos: 44,
},
},
},
Else: &ast.StmtElse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 45,
EndPos: 52,
},
ElseTkn: &token.Token{
ID: token.T_ELSE,
Value: []byte("else"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 45,
EndPos: 49,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 44,
EndPos: 45,
},
},
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 50,
EndPos: 52,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 50,
EndPos: 51,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 49,
EndPos: 50,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 51,
EndPos: 52,
},
},
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtInlineHtml(t *testing.T) {
src := `<? ?> <div></div>`
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
},
&ast.StmtInlineHtml{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 17,
},
InlineHtmlTkn: &token.Token{
ID: token.T_INLINE_HTML,
Value: []byte(" <div></div>"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 17,
},
},
Value: []byte(" <div></div>"),
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtInterface(t *testing.T) {
src := `<? interface Foo {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Stmts: []ast.Vertex{
&ast.StmtInterface{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
InterfaceTkn: &token.Token{
ID: token.T_INTERFACE,
Value: []byte("interface"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Value: []byte("Foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtInterface_Extend(t *testing.T) {
src := `<? interface Foo extends Bar {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 31,
},
Stmts: []ast.Vertex{
&ast.StmtInterface{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 31,
},
InterfaceTkn: &token.Token{
ID: token.T_INTERFACE,
Value: []byte("interface"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Value: []byte("Foo"),
},
ExtendsTkn: &token.Token{
ID: token.T_EXTENDS,
Value: []byte("extends"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 24,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
Extends: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 28,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 28,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 28,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
},
},
},
Value: []byte("Bar"),
},
},
},
},
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtInterface_Extends(t *testing.T) {
src := `<? interface Foo extends Bar, Baz {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 36,
},
Stmts: []ast.Vertex{
&ast.StmtInterface{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 36,
},
InterfaceTkn: &token.Token{
ID: token.T_INTERFACE,
Value: []byte("interface"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Value: []byte("Foo"),
},
ExtendsTkn: &token.Token{
ID: token.T_EXTENDS,
Value: []byte("extends"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 24,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
Extends: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 28,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 28,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 28,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
},
},
},
Value: []byte("Bar"),
},
},
},
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 33,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 33,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 33,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 30,
},
},
},
},
Value: []byte("Baz"),
},
},
},
},
ExtendsSeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 29,
},
},
},
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtNamespace(t *testing.T) {
src := `<? namespace Foo;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 17,
},
Stmts: []ast.Vertex{
&ast.StmtNamespace{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 17,
},
NsTkn: &token.Token{
ID: token.T_NAMESPACE,
Value: []byte("namespace"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Value: []byte("Foo"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtNamespace_Stmts(t *testing.T) {
src := `<? namespace Foo {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Stmts: []ast.Vertex{
&ast.StmtNamespace{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
NsTkn: &token.Token{
ID: token.T_NAMESPACE,
Value: []byte("namespace"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Value: []byte("Foo"),
},
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtNamespace_Anonymous(t *testing.T) {
src := `<? namespace {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Stmts: []ast.Vertex{
&ast.StmtNamespace{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
NsTkn: &token.Token{
ID: token.T_NAMESPACE,
Value: []byte("namespace"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtProperty(t *testing.T) {
src := `<? class foo {var $a;}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 22,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 22,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtPropertyList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 21,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 17,
},
IdentifierTkn: &token.Token{
ID: token.T_VAR,
Value: []byte("var"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 17,
},
},
Value: []byte("var"),
},
},
Props: []ast.Vertex{
&ast.StmtProperty{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("$a"),
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
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,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtProperty_Properties(t *testing.T) {
src := `<? class foo {public static $a, $b = 1;}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 40,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 40,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtPropertyList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 39,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 20,
},
IdentifierTkn: &token.Token{
ID: token.T_PUBLIC,
Value: []byte("public"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 20,
},
},
Value: []byte("public"),
},
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 27,
},
IdentifierTkn: &token.Token{
ID: token.T_STATIC,
Value: []byte("static"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
},
},
Value: []byte("static"),
},
},
Props: []ast.Vertex{
&ast.StmtProperty{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 30,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 30,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 30,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 30,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 28,
},
},
},
},
Value: []byte("$a"),
},
},
},
&ast.StmtProperty{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 38,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 34,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 34,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 34,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 31,
EndPos: 32,
},
},
},
},
Value: []byte("$b"),
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 36,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 34,
EndPos: 35,
},
},
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 38,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 38,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 37,
},
},
},
},
Value: []byte("1"),
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 31,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 38,
EndPos: 39,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 39,
EndPos: 40,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtProperty_Properties2(t *testing.T) {
src := `<? class foo {public static $a = 1, $b;}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 40,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 40,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtPropertyList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 39,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 20,
},
IdentifierTkn: &token.Token{
ID: token.T_PUBLIC,
Value: []byte("public"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 20,
},
},
Value: []byte("public"),
},
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 27,
},
IdentifierTkn: &token.Token{
ID: token.T_STATIC,
Value: []byte("static"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
},
},
Value: []byte("static"),
},
},
Props: []ast.Vertex{
&ast.StmtProperty{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 34,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 30,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 30,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 30,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 28,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 31,
EndPos: 32,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 31,
},
},
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 34,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 34,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 33,
},
},
},
},
Value: []byte("1"),
},
},
&ast.StmtProperty{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 38,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 38,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 38,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 38,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 36,
},
},
},
},
Value: []byte("$b"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 34,
EndPos: 35,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 38,
EndPos: 39,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 39,
EndPos: 40,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtProperty_PropertyType(t *testing.T) {
src := `<? class foo {var bar $a;}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 26,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 26,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtPropertyList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 25,
},
Modifiers: []ast.Vertex{
&ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 17,
},
IdentifierTkn: &token.Token{
ID: token.T_VAR,
Value: []byte("var"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 17,
},
},
Value: []byte("var"),
},
},
Type: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("bar"),
},
},
},
Props: []ast.Vertex{
&ast.StmtProperty{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 24,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
},
},
Value: []byte("$a"),
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtStaticVar(t *testing.T) {
src := `<? static $a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
Stmts: []ast.Vertex{
&ast.StmtStatic{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
StaticTkn: &token.Token{
ID: token.T_STATIC,
Value: []byte("static"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Vars: []ast.Vertex{
&ast.StmtStaticVar{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
},
},
Value: []byte("$a"),
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtStaticVar_Vars(t *testing.T) {
src := `<? static $a, $b = 1;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 21,
},
Stmts: []ast.Vertex{
&ast.StmtStatic{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 21,
},
StaticTkn: &token.Token{
ID: token.T_STATIC,
Value: []byte("static"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Vars: []ast.Vertex{
&ast.StmtStaticVar{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
},
},
Value: []byte("$a"),
},
},
},
&ast.StmtStaticVar{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 20,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
Value: []byte("$b"),
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
Value: []byte("1"),
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtStaticVar_Vars2(t *testing.T) {
src := `<? static $a = 1, $b;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 21,
},
Stmts: []ast.Vertex{
&ast.StmtStatic{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 21,
},
StaticTkn: &token.Token{
ID: token.T_STATIC,
Value: []byte("static"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Vars: []ast.Vertex{
&ast.StmtStaticVar{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 16,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Expr: &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"),
},
},
&ast.StmtStaticVar{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("$b"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtSwitch(t *testing.T) {
src := `<?
switch (1) {
case 1: break;
case 2: break;
}
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 5,
StartPos: 5,
EndPos: 57,
},
Stmts: []ast.Vertex{
&ast.StmtSwitch{
Position: &position.Position{
StartLine: 2,
EndLine: 5,
StartPos: 5,
EndPos: 57,
},
SwitchTkn: &token.Token{
ID: token.T_SWITCH,
Value: []byte("switch"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 13,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 11,
EndPos: 12,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 13,
EndPos: 14,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 13,
EndPos: 14,
},
},
Value: []byte("1"),
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 14,
EndPos: 15,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 16,
EndPos: 17,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 15,
EndPos: 16,
},
},
},
},
Cases: []ast.Vertex{
&ast.StmtCase{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 21,
EndPos: 35,
},
CaseTkn: &token.Token{
ID: token.T_CASE,
Value: []byte("case"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 21,
EndPos: 25,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 17,
EndPos: 21,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 26,
EndPos: 27,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 26,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 25,
EndPos: 26,
},
},
},
},
Value: []byte("1"),
},
CaseSeparatorTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 27,
EndPos: 28,
},
},
Stmts: []ast.Vertex{
&ast.StmtBreak{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 29,
EndPos: 35,
},
BreakTkn: &token.Token{
ID: token.T_BREAK,
Value: []byte("break"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 29,
EndPos: 34,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 28,
EndPos: 29,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 34,
EndPos: 35,
},
},
},
},
},
&ast.StmtCase{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 39,
EndPos: 53,
},
CaseTkn: &token.Token{
ID: token.T_CASE,
Value: []byte("case"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 39,
EndPos: 43,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t\t"),
Position: &position.Position{
StartLine: 3,
EndLine: 4,
StartPos: 35,
EndPos: 39,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 44,
EndPos: 45,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("2"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 44,
EndPos: 45,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 43,
EndPos: 44,
},
},
},
},
Value: []byte("2"),
},
CaseSeparatorTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 45,
EndPos: 46,
},
},
Stmts: []ast.Vertex{
&ast.StmtBreak{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 47,
EndPos: 53,
},
BreakTkn: &token.Token{
ID: token.T_BREAK,
Value: []byte("break"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 47,
EndPos: 52,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 46,
EndPos: 47,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 52,
EndPos: 53,
},
},
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 56,
EndPos: 57,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 4,
EndLine: 5,
StartPos: 53,
EndPos: 56,
},
},
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t"),
Position: &position.Position{
StartLine: 5,
EndLine: 6,
StartPos: 57,
EndPos: 59,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtSwitch_Semicolon(t *testing.T) {
src := `<?
switch (1) {;
case 1; break;
case 2; break;
}
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 5,
StartPos: 5,
EndPos: 58,
},
Stmts: []ast.Vertex{
&ast.StmtSwitch{
Position: &position.Position{
StartLine: 2,
EndLine: 5,
StartPos: 5,
EndPos: 58,
},
SwitchTkn: &token.Token{
ID: token.T_SWITCH,
Value: []byte("switch"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 13,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 11,
EndPos: 12,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 13,
EndPos: 14,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 13,
EndPos: 14,
},
},
Value: []byte("1"),
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 14,
EndPos: 15,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 16,
EndPos: 17,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 15,
EndPos: 16,
},
},
},
},
CaseSeparatorTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 17,
EndPos: 18,
},
},
Cases: []ast.Vertex{
&ast.StmtCase{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 22,
EndPos: 36,
},
CaseTkn: &token.Token{
ID: token.T_CASE,
Value: []byte("case"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 22,
EndPos: 26,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 18,
EndPos: 22,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 27,
EndPos: 28,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 27,
EndPos: 28,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 26,
EndPos: 27,
},
},
},
},
Value: []byte("1"),
},
CaseSeparatorTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 28,
EndPos: 29,
},
},
Stmts: []ast.Vertex{
&ast.StmtBreak{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 30,
EndPos: 36,
},
BreakTkn: &token.Token{
ID: token.T_BREAK,
Value: []byte("break"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 30,
EndPos: 35,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 29,
EndPos: 30,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 35,
EndPos: 36,
},
},
},
},
},
&ast.StmtCase{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 40,
EndPos: 54,
},
CaseTkn: &token.Token{
ID: token.T_CASE,
Value: []byte("case"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 40,
EndPos: 44,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t\t"),
Position: &position.Position{
StartLine: 3,
EndLine: 4,
StartPos: 36,
EndPos: 40,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 45,
EndPos: 46,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("2"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 45,
EndPos: 46,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 44,
EndPos: 45,
},
},
},
},
Value: []byte("2"),
},
CaseSeparatorTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 46,
EndPos: 47,
},
},
Stmts: []ast.Vertex{
&ast.StmtBreak{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 48,
EndPos: 54,
},
BreakTkn: &token.Token{
ID: token.T_BREAK,
Value: []byte("break"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 48,
EndPos: 53,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 47,
EndPos: 48,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 53,
EndPos: 54,
},
},
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 57,
EndPos: 58,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 4,
EndLine: 5,
StartPos: 54,
EndPos: 57,
},
},
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t"),
Position: &position.Position{
StartLine: 5,
EndLine: 6,
StartPos: 58,
EndPos: 60,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtSwitch_Alt(t *testing.T) {
src := `<?
switch (1) :
case 1:
default:
case 2;
endswitch;
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 6,
StartPos: 5,
EndPos: 64,
},
Stmts: []ast.Vertex{
&ast.StmtSwitch{
Position: &position.Position{
StartLine: 2,
EndLine: 6,
StartPos: 5,
EndPos: 64,
},
SwitchTkn: &token.Token{
ID: token.T_SWITCH,
Value: []byte("switch"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 13,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 11,
EndPos: 12,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 13,
EndPos: 14,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 13,
EndPos: 14,
},
},
Value: []byte("1"),
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 14,
EndPos: 15,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 16,
EndPos: 17,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 15,
EndPos: 16,
},
},
},
},
Cases: []ast.Vertex{
&ast.StmtCase{
Position: &position.Position{
StartLine: 3,
EndLine: -1,
StartPos: 21,
EndPos: -1,
},
CaseTkn: &token.Token{
ID: token.T_CASE,
Value: []byte("case"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 21,
EndPos: 25,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 17,
EndPos: 21,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 26,
EndPos: 27,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 26,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 25,
EndPos: 26,
},
},
},
},
Value: []byte("1"),
},
CaseSeparatorTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 27,
EndPos: 28,
},
},
Stmts: []ast.Vertex{},
},
&ast.StmtDefault{
Position: &position.Position{
StartLine: 4,
EndLine: -1,
StartPos: 32,
EndPos: -1,
},
DefaultTkn: &token.Token{
ID: token.T_DEFAULT,
Value: []byte("default"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 32,
EndPos: 39,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t\t"),
Position: &position.Position{
StartLine: 3,
EndLine: 4,
StartPos: 28,
EndPos: 32,
},
},
},
},
CaseSeparatorTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 39,
EndPos: 40,
},
},
Stmts: []ast.Vertex{},
},
&ast.StmtCase{
Position: &position.Position{
StartLine: 5,
EndLine: -1,
StartPos: 44,
EndPos: -1,
},
CaseTkn: &token.Token{
ID: token.T_CASE,
Value: []byte("case"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 44,
EndPos: 48,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t\t"),
Position: &position.Position{
StartLine: 4,
EndLine: 5,
StartPos: 40,
EndPos: 44,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 49,
EndPos: 50,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("2"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 49,
EndPos: 50,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 48,
EndPos: 49,
},
},
},
},
Value: []byte("2"),
},
CaseSeparatorTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 50,
EndPos: 51,
},
},
Stmts: []ast.Vertex{},
},
},
EndSwitchTkn: &token.Token{
ID: token.T_ENDSWITCH,
Value: []byte("endswitch"),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 54,
EndPos: 63,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 5,
EndLine: 6,
StartPos: 51,
EndPos: 54,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 63,
EndPos: 64,
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t"),
Position: &position.Position{
StartLine: 6,
EndLine: 7,
StartPos: 64,
EndPos: 66,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtSwitch_AltSemicolon(t *testing.T) {
src := `<?
switch (1) :;
case 1;
case 2;
endswitch;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 5,
StartPos: 5,
EndPos: 53,
},
Stmts: []ast.Vertex{
&ast.StmtSwitch{
Position: &position.Position{
StartLine: 2,
EndLine: 5,
StartPos: 5,
EndPos: 53,
},
SwitchTkn: &token.Token{
ID: token.T_SWITCH,
Value: []byte("switch"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 13,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 11,
EndPos: 12,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 13,
EndPos: 14,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 13,
EndPos: 14,
},
},
Value: []byte("1"),
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 14,
EndPos: 15,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 16,
EndPos: 17,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 15,
EndPos: 16,
},
},
},
},
CaseSeparatorTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 17,
EndPos: 18,
},
},
Cases: []ast.Vertex{
&ast.StmtCase{
Position: &position.Position{
StartLine: 3,
EndLine: -1,
StartPos: 22,
EndPos: -1,
},
CaseTkn: &token.Token{
ID: token.T_CASE,
Value: []byte("case"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 22,
EndPos: 26,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 18,
EndPos: 22,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 27,
EndPos: 28,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 27,
EndPos: 28,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 26,
EndPos: 27,
},
},
},
},
Value: []byte("1"),
},
CaseSeparatorTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 28,
EndPos: 29,
},
},
Stmts: []ast.Vertex{},
},
&ast.StmtCase{
Position: &position.Position{
StartLine: 4,
EndLine: -1,
StartPos: 33,
EndPos: -1,
},
CaseTkn: &token.Token{
ID: token.T_CASE,
Value: []byte("case"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 33,
EndPos: 37,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t\t"),
Position: &position.Position{
StartLine: 3,
EndLine: 4,
StartPos: 29,
EndPos: 33,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 38,
EndPos: 39,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("2"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 38,
EndPos: 39,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 37,
EndPos: 38,
},
},
},
},
Value: []byte("2"),
},
CaseSeparatorTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 39,
EndPos: 40,
},
},
Stmts: []ast.Vertex{},
},
},
EndSwitchTkn: &token.Token{
ID: token.T_ENDSWITCH,
Value: []byte("endswitch"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 43,
EndPos: 52,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 4,
EndLine: 5,
StartPos: 40,
EndPos: 43,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 52,
EndPos: 53,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtThrow(t *testing.T) {
src := `<? throw $e;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Stmts: []ast.Vertex{
&ast.StmtThrow{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
ThrowTkn: &token.Token{
ID: token.T_THROW,
Value: []byte("throw"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$e"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("$e"),
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtTrait(t *testing.T) {
src := `<? trait Foo {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Stmts: []ast.Vertex{
&ast.StmtTrait{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
TraitTkn: &token.Token{
ID: token.T_TRAIT,
Value: []byte("trait"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("Foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtTraitUse(t *testing.T) {
src := `<? class Foo { use Bar; }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 25,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 25,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("Foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtTraitUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 23,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
Traits: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
Value: []byte("Bar"),
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
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,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtTraitUse_Uses(t *testing.T) {
src := `<? class Foo { use Bar, Baz; }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 30,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 30,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("Foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtTraitUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 28,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
Traits: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
Value: []byte("Bar"),
},
},
},
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 27,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 27,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 24,
},
},
},
},
Value: []byte("Baz"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
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: 27,
EndPos: 28,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
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,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtTraitUse_EmptyAdaptations(t *testing.T) {
src := `<? class Foo { use Bar, Baz {} }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 32,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 32,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("Foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtTraitUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 30,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
Traits: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
Value: []byte("Bar"),
},
},
},
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 27,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 27,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 24,
},
},
},
},
Value: []byte("Baz"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
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,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 30,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 31,
EndPos: 32,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 31,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtTraitUse_Modifier(t *testing.T) {
src := `<? class Foo { use Bar, Baz { one as public; } }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 48,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 48,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("Foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtTraitUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 46,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
Traits: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
Value: []byte("Bar"),
},
},
},
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 27,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 27,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 24,
},
},
},
},
Value: []byte("Baz"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
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,
},
},
},
},
Adaptations: []ast.Vertex{
&ast.StmtTraitUseAlias{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 43,
},
Method: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 33,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("one"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 33,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 30,
},
},
},
},
Value: []byte("one"),
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 34,
EndPos: 36,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 34,
},
},
},
},
Modifier: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 43,
},
IdentifierTkn: &token.Token{
ID: token.T_PUBLIC,
Value: []byte("public"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 43,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 37,
},
},
},
},
Value: []byte("public"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 43,
EndPos: 44,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 45,
EndPos: 46,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 44,
EndPos: 45,
},
},
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 47,
EndPos: 48,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 46,
EndPos: 47,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtTraitUse_AliasModifier(t *testing.T) {
src := `<? class Foo { use Bar, Baz { one as public two; } }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 52,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 52,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("Foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtTraitUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 50,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
Traits: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
Value: []byte("Bar"),
},
},
},
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 27,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 27,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 24,
},
},
},
},
Value: []byte("Baz"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
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,
},
},
},
},
Adaptations: []ast.Vertex{
&ast.StmtTraitUseAlias{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 47,
},
Method: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 33,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("one"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 33,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 30,
},
},
},
},
Value: []byte("one"),
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 34,
EndPos: 36,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 34,
},
},
},
},
Modifier: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 43,
},
IdentifierTkn: &token.Token{
ID: token.T_PUBLIC,
Value: []byte("public"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 37,
EndPos: 43,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 37,
},
},
},
},
Value: []byte("public"),
},
Alias: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 44,
EndPos: 47,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("two"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 44,
EndPos: 47,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 43,
EndPos: 44,
},
},
},
},
Value: []byte("two"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 47,
EndPos: 48,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 49,
EndPos: 50,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 48,
EndPos: 49,
},
},
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 51,
EndPos: 52,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 50,
EndPos: 51,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtTraitUse_Adaptions(t *testing.T) {
src := `<? class Foo { use Bar, Baz { Bar::one insteadof Baz, Quux; Baz::one as two; } }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 80,
},
Stmts: []ast.Vertex{
&ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 80,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("Foo"),
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtTraitUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 78,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
Traits: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
Value: []byte("Bar"),
},
},
},
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 27,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 27,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 27,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 24,
},
},
},
},
Value: []byte("Baz"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
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,
},
},
},
},
Adaptations: []ast.Vertex{
&ast.StmtTraitUsePrecedence{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 58,
},
Trait: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 33,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 33,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 33,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 30,
},
},
},
},
Value: []byte("Bar"),
},
},
},
DoubleColonTkn: &token.Token{
ID: token.T_PAAMAYIM_NEKUDOTAYIM,
Value: []byte("::"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 35,
},
},
Method: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 38,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("one"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 38,
},
},
Value: []byte("one"),
},
InsteadofTkn: &token.Token{
ID: token.T_INSTEADOF,
Value: []byte("insteadof"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 39,
EndPos: 48,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 38,
EndPos: 39,
},
},
},
},
Insteadof: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 49,
EndPos: 52,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 49,
EndPos: 52,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 49,
EndPos: 52,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 48,
EndPos: 49,
},
},
},
},
Value: []byte("Baz"),
},
},
},
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 54,
EndPos: 58,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 54,
EndPos: 58,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Quux"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 54,
EndPos: 58,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 53,
EndPos: 54,
},
},
},
},
Value: []byte("Quux"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 52,
EndPos: 53,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 58,
EndPos: 59,
},
},
},
&ast.StmtTraitUseAlias{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 60,
EndPos: 75,
},
Trait: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 60,
EndPos: 63,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 60,
EndPos: 63,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 60,
EndPos: 63,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 59,
EndPos: 60,
},
},
},
},
Value: []byte("Baz"),
},
},
},
DoubleColonTkn: &token.Token{
ID: token.T_PAAMAYIM_NEKUDOTAYIM,
Value: []byte("::"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 63,
EndPos: 65,
},
},
Method: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 65,
EndPos: 68,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("one"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 65,
EndPos: 68,
},
},
Value: []byte("one"),
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 69,
EndPos: 71,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 68,
EndPos: 69,
},
},
},
},
Alias: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 72,
EndPos: 75,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("two"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 72,
EndPos: 75,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 71,
EndPos: 72,
},
},
},
},
Value: []byte("two"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 75,
EndPos: 76,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 77,
EndPos: 78,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 76,
EndPos: 77,
},
},
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 79,
EndPos: 80,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 78,
EndPos: 79,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtTry_Try(t *testing.T) {
src := `<?
try {}
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: -1,
StartPos: 5,
EndPos: -1,
},
Stmts: []ast.Vertex{
&ast.StmtTry{
Position: &position.Position{
StartLine: 2,
EndLine: -1,
StartPos: 5,
EndPos: -1,
},
TryTkn: &token.Token{
ID: token.T_TRY,
Value: []byte("try"),
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: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 8,
EndPos: 9,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 10,
EndPos: 11,
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 11,
EndPos: 13,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtTry_TryCatch(t *testing.T) {
src := `<?
try {} catch (Exception $e) {}
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 35,
},
Stmts: []ast.Vertex{
&ast.StmtTry{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 35,
},
TryTkn: &token.Token{
ID: token.T_TRY,
Value: []byte("try"),
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: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 8,
EndPos: 9,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 10,
EndPos: 11,
},
},
Catches: []ast.Vertex{
&ast.StmtCatch{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 35,
},
CatchTkn: &token.Token{
ID: token.T_CATCH,
Value: []byte("catch"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 17,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 11,
EndPos: 12,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 18,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 17,
EndPos: 18,
},
},
},
},
Types: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 28,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 28,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Exception"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 28,
},
},
Value: []byte("Exception"),
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 29,
EndPos: 31,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 29,
EndPos: 31,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$e"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 29,
EndPos: 31,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 28,
EndPos: 29,
},
},
},
},
Value: []byte("$e"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 31,
EndPos: 32,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 33,
EndPos: 34,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 32,
EndPos: 33,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 34,
EndPos: 35,
},
},
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 35,
EndPos: 37,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtTry_Php8TryCatch(t *testing.T) {
src := `<?
try {} catch (Exception|RuntimeException $e) {}
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 52,
},
Stmts: []ast.Vertex{
&ast.StmtTry{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 52,
},
TryTkn: &token.Token{
ID: token.T_TRY,
Value: []byte("try"),
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: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 8,
EndPos: 9,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 10,
EndPos: 11,
},
},
Catches: []ast.Vertex{
&ast.StmtCatch{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 52,
},
CatchTkn: &token.Token{
ID: token.T_CATCH,
Value: []byte("catch"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 17,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 11,
EndPos: 12,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 18,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 17,
EndPos: 18,
},
},
},
},
Types: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 28,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 28,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Exception"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 28,
},
},
Value: []byte("Exception"),
},
},
},
&ast.Name{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 29,
EndPos: 45,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 29,
EndPos: 45,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("RuntimeException"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 29,
EndPos: 45,
},
},
Value: []byte("RuntimeException"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(124),
Value: []byte("|"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 28,
EndPos: 29,
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 46,
EndPos: 48,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 46,
EndPos: 48,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$e"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 46,
EndPos: 48,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 45,
EndPos: 46,
},
},
},
},
Value: []byte("$e"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 48,
EndPos: 49,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 50,
EndPos: 51,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 49,
EndPos: 50,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 51,
EndPos: 52,
},
},
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 52,
EndPos: 54,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtTry_TryCatchCatch(t *testing.T) {
src := `<?
try {} catch (Exception $e) {} catch (RuntimeException $e) {}
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 66,
},
Stmts: []ast.Vertex{
&ast.StmtTry{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 66,
},
TryTkn: &token.Token{
ID: token.T_TRY,
Value: []byte("try"),
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: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 8,
EndPos: 9,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 10,
EndPos: 11,
},
},
Catches: []ast.Vertex{
&ast.StmtCatch{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 35,
},
CatchTkn: &token.Token{
ID: token.T_CATCH,
Value: []byte("catch"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 17,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 11,
EndPos: 12,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 18,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 17,
EndPos: 18,
},
},
},
},
Types: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 28,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 28,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Exception"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 28,
},
},
Value: []byte("Exception"),
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 29,
EndPos: 31,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 29,
EndPos: 31,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$e"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 29,
EndPos: 31,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 28,
EndPos: 29,
},
},
},
},
Value: []byte("$e"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 31,
EndPos: 32,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 33,
EndPos: 34,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 32,
EndPos: 33,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 34,
EndPos: 35,
},
},
},
&ast.StmtCatch{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 36,
EndPos: 66,
},
CatchTkn: &token.Token{
ID: token.T_CATCH,
Value: []byte("catch"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 36,
EndPos: 41,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 35,
EndPos: 36,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 42,
EndPos: 43,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 41,
EndPos: 42,
},
},
},
},
Types: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 43,
EndPos: 59,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 43,
EndPos: 59,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("RuntimeException"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 43,
EndPos: 59,
},
},
Value: []byte("RuntimeException"),
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 60,
EndPos: 62,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 60,
EndPos: 62,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$e"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 60,
EndPos: 62,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 59,
EndPos: 60,
},
},
},
},
Value: []byte("$e"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 62,
EndPos: 63,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 64,
EndPos: 65,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 63,
EndPos: 64,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 65,
EndPos: 66,
},
},
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 66,
EndPos: 68,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtTry_TryCatchFinally(t *testing.T) {
src := `<?
try {} catch (Exception $e) {} finally {}
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 46,
},
Stmts: []ast.Vertex{
&ast.StmtTry{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 46,
},
TryTkn: &token.Token{
ID: token.T_TRY,
Value: []byte("try"),
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: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 8,
EndPos: 9,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 10,
EndPos: 11,
},
},
Catches: []ast.Vertex{
&ast.StmtCatch{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 35,
},
CatchTkn: &token.Token{
ID: token.T_CATCH,
Value: []byte("catch"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 17,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 11,
EndPos: 12,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 18,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 17,
EndPos: 18,
},
},
},
},
Types: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 28,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 28,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Exception"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 19,
EndPos: 28,
},
},
Value: []byte("Exception"),
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 29,
EndPos: 31,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 29,
EndPos: 31,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$e"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 29,
EndPos: 31,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 28,
EndPos: 29,
},
},
},
},
Value: []byte("$e"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 31,
EndPos: 32,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 33,
EndPos: 34,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 32,
EndPos: 33,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 34,
EndPos: 35,
},
},
},
},
Finally: &ast.StmtFinally{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 36,
EndPos: 46,
},
FinallyTkn: &token.Token{
ID: token.T_FINALLY,
Value: []byte("finally"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 36,
EndPos: 43,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 35,
EndPos: 36,
},
},
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 44,
EndPos: 45,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 43,
EndPos: 44,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 45,
EndPos: 46,
},
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 46,
EndPos: 48,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtTry_TryCatchCatchCatch(t *testing.T) {
src := `<? try {} catch (Exception $e) {} catch (\RuntimeException $e) {} catch (namespace\AdditionException $e) {}`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 107,
},
Stmts: []ast.Vertex{
&ast.StmtTry{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 107,
},
TryTkn: &token.Token{
ID: token.T_TRY,
Value: []byte("try"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
Catches: []ast.Vertex{
&ast.StmtCatch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 33,
},
CatchTkn: &token.Token{
ID: token.T_CATCH,
Value: []byte("catch"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
Types: []ast.Vertex{
&ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 26,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 26,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Exception"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 26,
},
},
Value: []byte("Exception"),
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 29,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 29,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$e"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 29,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
},
},
},
Value: []byte("$e"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 30,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 31,
EndPos: 32,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 31,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 33,
},
},
},
&ast.StmtCatch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 34,
EndPos: 65,
},
CatchTkn: &token.Token{
ID: token.T_CATCH,
Value: []byte("catch"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 34,
EndPos: 39,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 34,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 40,
EndPos: 41,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 39,
EndPos: 40,
},
},
},
},
Types: []ast.Vertex{
&ast.NameFullyQualified{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 41,
EndPos: 58,
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 41,
EndPos: 42,
},
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 42,
EndPos: 58,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("RuntimeException"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 42,
EndPos: 58,
},
},
Value: []byte("RuntimeException"),
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 59,
EndPos: 61,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 59,
EndPos: 61,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$e"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 59,
EndPos: 61,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 58,
EndPos: 59,
},
},
},
},
Value: []byte("$e"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 61,
EndPos: 62,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 63,
EndPos: 64,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 62,
EndPos: 63,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 64,
EndPos: 65,
},
},
},
&ast.StmtCatch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 66,
EndPos: 107,
},
CatchTkn: &token.Token{
ID: token.T_CATCH,
Value: []byte("catch"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 66,
EndPos: 71,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 65,
EndPos: 66,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 72,
EndPos: 73,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 71,
EndPos: 72,
},
},
},
},
Types: []ast.Vertex{
&ast.NameRelative{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 73,
EndPos: 100,
},
NsTkn: &token.Token{
ID: token.T_NAMESPACE,
Value: []byte("namespace"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 73,
EndPos: 82,
},
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 82,
EndPos: 83,
},
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 83,
EndPos: 100,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("AdditionException"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 83,
EndPos: 100,
},
},
Value: []byte("AdditionException"),
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 101,
EndPos: 103,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 101,
EndPos: 103,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$e"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 101,
EndPos: 103,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 100,
EndPos: 101,
},
},
},
},
Value: []byte("$e"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 103,
EndPos: 104,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 105,
EndPos: 106,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 104,
EndPos: 105,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 106,
EndPos: 107,
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUnset(t *testing.T) {
src := `<? unset($a);`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
Stmts: []ast.Vertex{
&ast.StmtUnset{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
UnsetTkn: &token.Token{
ID: token.T_UNSET,
Value: []byte("unset"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
Vars: []ast.Vertex{
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
},
Value: []byte("$a"),
},
},
},
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUnset_Vars(t *testing.T) {
src := `<? unset($a, $b);`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 17,
},
Stmts: []ast.Vertex{
&ast.StmtUnset{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 17,
},
UnsetTkn: &token.Token{
ID: token.T_UNSET,
Value: []byte("unset"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
Vars: []ast.Vertex{
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
},
Value: []byte("$a"),
},
},
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Value: []byte("$b"),
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUnset_TrailingComma(t *testing.T) {
src := `<? unset($a, $b,);`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 18,
},
Stmts: []ast.Vertex{
&ast.StmtUnset{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 18,
},
UnsetTkn: &token.Token{
ID: token.T_UNSET,
Value: []byte("unset"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
Vars: []ast.Vertex{
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
},
Value: []byte("$a"),
},
},
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Value: []byte("$b"),
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUse(t *testing.T) {
src := `<? use Foo;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
Stmts: []ast.Vertex{
&ast.StmtUseList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Uses: []ast.Vertex{
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUse_FullyQualified(t *testing.T) {
src := `<? use \Foo;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Stmts: []ast.Vertex{
&ast.StmtUseList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Uses: []ast.Vertex{
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 11,
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 11,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 11,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 11,
},
},
Value: []byte("Foo"),
},
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUse_FullyQualifiedAlias(t *testing.T) {
src := `<? use \Foo as Bar;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Stmts: []ast.Vertex{
&ast.StmtUseList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Uses: []ast.Vertex{
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 18,
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 11,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 11,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 11,
},
},
Value: []byte("Foo"),
},
},
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
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,
},
},
},
},
Alias: &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,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
Value: []byte("Bar"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUse_List(t *testing.T) {
src := `<? use Foo, Bar;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 16,
},
Stmts: []ast.Vertex{
&ast.StmtUseList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 16,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Uses: []ast.Vertex{
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
Value: []byte("Foo"),
},
},
},
},
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
Value: []byte("Bar"),
},
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUse_ListAlias(t *testing.T) {
src := `<? use Foo, Bar as Baz;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Stmts: []ast.Vertex{
&ast.StmtUseList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Uses: []ast.Vertex{
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
Value: []byte("Foo"),
},
},
},
},
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 22,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
Value: []byte("Bar"),
},
},
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
Alias: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
Value: []byte("Baz"),
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUse_ListFunctionType(t *testing.T) {
src := `<? use function Foo, \Bar;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 26,
},
Stmts: []ast.Vertex{
&ast.StmtUseList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 26,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Type: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 15,
},
IdentifierTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
Value: []byte("function"),
},
Uses: []ast.Vertex{
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 19,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 19,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 19,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
Value: []byte("Foo"),
},
},
},
},
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 25,
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
},
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 25,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 25,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 25,
},
},
Value: []byte("Bar"),
},
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
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: 25,
EndPos: 26,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUse_ListFunctionTypeAliases(t *testing.T) {
src := `<? use function Foo as foo, \Bar as bar;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 40,
},
Stmts: []ast.Vertex{
&ast.StmtUseList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 40,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Type: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 15,
},
IdentifierTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
Value: []byte("function"),
},
Uses: []ast.Vertex{
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 26,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 19,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 19,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
Value: []byte("Foo"),
},
},
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
},
},
Alias: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 26,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 26,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
Value: []byte("foo"),
},
},
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 39,
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
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,
},
},
},
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 32,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 32,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 32,
},
},
Value: []byte("Bar"),
},
},
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 35,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 33,
},
},
},
},
Alias: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 39,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 39,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 36,
},
},
},
},
Value: []byte("bar"),
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 39,
EndPos: 40,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUse_ListConstType(t *testing.T) {
src := `<? use const Foo, \Bar;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Stmts: []ast.Vertex{
&ast.StmtUseList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Type: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_CONST,
Value: []byte("const"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
Value: []byte("const"),
},
Uses: []ast.Vertex{
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Value: []byte("Foo"),
},
},
},
},
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 22,
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 22,
},
},
Value: []byte("Bar"),
},
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUse_ListConstTypeAliases(t *testing.T) {
src := `<? use const Foo as foo, \Bar as bar;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 37,
},
Stmts: []ast.Vertex{
&ast.StmtUseList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 37,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Type: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_CONST,
Value: []byte("const"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
Value: []byte("const"),
},
Uses: []ast.Vertex{
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 23,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Value: []byte("Foo"),
},
},
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
Alias: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 23,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
},
},
Value: []byte("foo"),
},
},
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 36,
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
},
},
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 29,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 29,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 29,
},
},
Value: []byte("Bar"),
},
},
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 32,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 30,
},
},
},
},
Alias: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 36,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 36,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 33,
},
},
},
},
Value: []byte("bar"),
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 24,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 37,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUse_GroupUse(t *testing.T) {
src := `<? use Foo\{Bar, Baz};`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 22,
},
Stmts: []ast.Vertex{
&ast.StmtGroupUseList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 22,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Prefix: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
Value: []byte("Foo"),
},
},
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
Uses: []ast.Vertex{
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
},
Value: []byte("Bar"),
},
},
},
},
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 20,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 20,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 20,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
Value: []byte("Baz"),
},
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUse_GroupUseAlias(t *testing.T) {
src := `<? use Foo\{Bar, Baz as quux};`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 30,
},
Stmts: []ast.Vertex{
&ast.StmtGroupUseList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 30,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Prefix: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
Value: []byte("Foo"),
},
},
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
Uses: []ast.Vertex{
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 15,
},
},
Value: []byte("Bar"),
},
},
},
},
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 28,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 20,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 20,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
Value: []byte("Baz"),
},
},
},
AsTkn: &token.Token{
ID: token.T_AS,
Value: []byte("as"),
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,
},
},
},
},
Alias: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 28,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("quux"),
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,
},
},
},
},
Value: []byte("quux"),
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 29,
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 30,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUse_FunctionGroupUse(t *testing.T) {
src := `<? use function Foo\{Bar, Baz};`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 31,
},
Stmts: []ast.Vertex{
&ast.StmtGroupUseList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 31,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Type: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 15,
},
IdentifierTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
Value: []byte("function"),
},
Prefix: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 19,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 19,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
Value: []byte("Foo"),
},
},
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
Uses: []ast.Vertex{
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 24,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 24,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 24,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 24,
},
},
Value: []byte("Bar"),
},
},
},
},
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 29,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 29,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 29,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 29,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
},
},
},
Value: []byte("Baz"),
},
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 30,
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 31,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUse_ConstGroupUse(t *testing.T) {
src := `<? use const Foo\{Bar, Baz};`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 28,
},
Stmts: []ast.Vertex{
&ast.StmtGroupUseList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 28,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Type: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_CONST,
Value: []byte("const"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
Value: []byte("const"),
},
Prefix: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Value: []byte("Foo"),
},
},
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
Uses: []ast.Vertex{
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
},
Value: []byte("Bar"),
},
},
},
},
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 26,
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 26,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 26,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 26,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
Value: []byte("Baz"),
},
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 28,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtUse_MixedGroupUse(t *testing.T) {
src := `<? use Foo\{const Bar, function Baz};`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 37,
},
Stmts: []ast.Vertex{
&ast.StmtGroupUseList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 37,
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Prefix: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
Value: []byte("Foo"),
},
},
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
Uses: []ast.Vertex{
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 21,
},
Type: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 17,
},
IdentifierTkn: &token.Token{
ID: token.T_CONST,
Value: []byte("const"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 17,
},
},
Value: []byte("const"),
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("Bar"),
},
},
},
},
&ast.StmtUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 35,
},
Type: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 31,
},
IdentifierTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 31,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
Value: []byte("function"),
},
Use: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 35,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 35,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Baz"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 35,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 31,
EndPos: 32,
},
},
},
},
Value: []byte("Baz"),
},
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 35,
EndPos: 36,
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 37,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtBreak_Empty(t *testing.T) {
src := `<? while (1) { break; }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Stmts: []ast.Vertex{
&ast.StmtWhile{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
WhileTkn: &token.Token{
ID: token.T_WHILE,
Value: []byte("while"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
Value: []byte("1"),
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 23,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtBreak{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 21,
},
BreakTkn: &token.Token{
ID: token.T_BREAK,
Value: []byte("break"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
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: 20,
EndPos: 21,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtBreak_Light(t *testing.T) {
src := `<? while (1) { break 2; }`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 25,
},
Stmts: []ast.Vertex{
&ast.StmtWhile{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 25,
},
WhileTkn: &token.Token{
ID: token.T_WHILE,
Value: []byte("while"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
Value: []byte("1"),
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 25,
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmts: []ast.Vertex{
&ast.StmtBreak{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 23,
},
BreakTkn: &token.Token{
ID: token.T_BREAK,
Value: []byte("break"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("2"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
},
},
Value: []byte("2"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
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,
},
},
},
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestStmtBreak(t *testing.T) {
src := `<? while (1) : break(3); endwhile;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 34,
},
Stmts: []ast.Vertex{
&ast.StmtWhile{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 34,
},
WhileTkn: &token.Token{
ID: token.T_WHILE,
Value: []byte("while"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Cond: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
Value: []byte("1"),
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Stmt: &ast.StmtStmtList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 24,
},
Stmts: []ast.Vertex{
&ast.StmtBreak{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 24,
},
BreakTkn: &token.Token{
ID: token.T_BREAK,
Value: []byte("break"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
Expr: &ast.ExprBrackets{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 23,
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
Expr: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("3"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
Value: []byte("3"),
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
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,
},
},
},
},
},
EndWhileTkn: &token.Token{
ID: token.T_ENDWHILE,
Value: []byte("endwhile"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 33,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 33,
EndPos: 34,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
// expr
func TestExprArrayDimFetch(t *testing.T) {
src := `<? $a[1];`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
Expr: &ast.ExprArrayDimFetch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$a"),
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(91),
Value: []byte("["),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
Dim: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
Value: []byte("1"),
},
CloseBracketTkn: &token.Token{
ID: token.ID(93),
Value: []byte("]"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprArrayDimFetch_Nested(t *testing.T) {
src := `<? $a[1][2];`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Expr: &ast.ExprArrayDimFetch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
Var: &ast.ExprArrayDimFetch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$a"),
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(91),
Value: []byte("["),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
Dim: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
Value: []byte("1"),
},
CloseBracketTkn: &token.Token{
ID: token.ID(93),
Value: []byte("]"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(91),
Value: []byte("["),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
Dim: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("2"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
Value: []byte("2"),
},
CloseBracketTkn: &token.Token{
ID: token.ID(93),
Value: []byte("]"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprArray(t *testing.T) {
src := `<? array();`
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.ExprArray{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 10,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprArray_Item(t *testing.T) {
src := `<? array(1);`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Expr: &ast.ExprArray{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
Items: []ast.Vertex{
&ast.ExprArrayItem{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
Val: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
Value: []byte("1"),
},
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprArray_Items(t *testing.T) {
src := `<? array(1=>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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
Items: []ast.Vertex{
&ast.ExprArrayItem{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 13,
},
Key: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
Value: []byte("1"),
},
DoubleArrowTkn: &token.Token{
ID: token.T_DOUBLE_ARROW,
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.T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG,
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprArray_ItemUnpack(t *testing.T) {
src := `<? array(...$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,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
Items: []ast.Vertex{
&ast.ExprArrayItem{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 14,
},
EllipsisTkn: &token.Token{
ID: token.T_ELLIPSIS,
Value: []byte("..."),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
},
Val: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
},
Value: []byte("$b"),
},
},
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(41),
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprArrowFunction(t *testing.T) {
src := `<? fn() => $a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Expr: &ast.ExprArrowFunction{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
FnTkn: &token.Token{
ID: token.T_FN,
Value: []byte("fn"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
DoubleArrowTkn: &token.Token{
ID: token.T_DOUBLE_ARROW,
Value: []byte("=>"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
},
Expr: &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("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 13,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprArrowFunction_ReturnType(t *testing.T) {
src := `<? fn & () : foo => $a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Expr: &ast.ExprArrowFunction{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 22,
},
FnTkn: &token.Token{
ID: token.T_FN,
Value: []byte("fn"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
AmpersandTkn: &token.Token{
ID: token.T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG,
Value: []byte("&"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
ReturnType: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Value: []byte("foo"),
},
},
},
DoubleArrowTkn: &token.Token{
ID: token.T_DOUBLE_ARROW,
Value: []byte("=>"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 22,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 22,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprBitwiseNot(t *testing.T) {
src := `<? ~$a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Expr: &ast.ExprBitwiseNot{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
TildaTkn: &token.Token{
ID: token.ID(126),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprBooleanNot(t *testing.T) {
src := `<? !$a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Expr: &ast.ExprBooleanNot{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
ExclamationTkn: &token.Token{
ID: token.ID(33),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprClassConstFetch(t *testing.T) {
src := `<? Foo::Bar;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Expr: &ast.ExprClassConstFetch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
Class: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("Foo"),
},
},
},
DoubleColonTkn: &token.Token{
ID: token.T_PAAMAYIM_NEKUDOTAYIM,
Value: []byte("::"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 8,
},
},
Const: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 11,
},
},
Value: []byte("Bar"),
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprClassConstFetch_Static(t *testing.T) {
src := `<? static::bar;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Expr: &ast.ExprClassConstFetch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Class: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
IdentifierTkn: &token.Token{
ID: token.T_STATIC,
Value: []byte("static"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("static"),
},
DoubleColonTkn: &token.Token{
ID: token.T_PAAMAYIM_NEKUDOTAYIM,
Value: []byte("::"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
},
Const: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 14,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 14,
},
},
Value: []byte("bar"),
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprClone_Brackets(t *testing.T) {
src := `<? clone($a);`
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.ExprClone{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
CloneTkn: &token.Token{
ID: token.T_CLONE,
Value: []byte("clone"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Expr: &ast.ExprBrackets{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 12,
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
},
Value: []byte("$a"),
},
},
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprClone(t *testing.T) {
src := `<? clone $a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Expr: &ast.ExprClone{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
CloneTkn: &token.Token{
ID: token.T_CLONE,
Value: []byte("clone"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprClosure(t *testing.T) {
src := `<? function(){};`
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.ExprClosure{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprClosure_Use(t *testing.T) {
src := `<? function($a, $b) use ($c, &$d) {};`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 37,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 37,
},
Expr: &ast.ExprClosure{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 36,
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
Params: []ast.Vertex{
&ast.Parameter{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
},
Value: []byte("$a"),
},
},
},
&ast.Parameter{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 18,
},
Var: &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,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
Value: []byte("$b"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
},
},
UseOpenParenthesisTkn: &token.Token{
ID: token.ID(40),
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,
},
},
},
},
Uses: []ast.Vertex{
&ast.ExprClosureUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 27,
},
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("$c"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 27,
},
},
Value: []byte("$c"),
},
},
},
&ast.ExprClosureUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 32,
},
AmpersandTkn: &token.Token{
ID: token.T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG,
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,
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 32,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 32,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$d"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 32,
},
},
Value: []byte("$d"),
},
},
},
},
UseSeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 28,
},
},
},
UseCloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 33,
},
},
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,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 37,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprClosure_Use2(t *testing.T) {
src := `<? function($a, $b) use (&$c, $d) {};`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 37,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 37,
},
Expr: &ast.ExprClosure{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 36,
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
Params: []ast.Vertex{
&ast.Parameter{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
},
Value: []byte("$a"),
},
},
},
&ast.Parameter{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 18,
},
Var: &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,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
Value: []byte("$b"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
UseTkn: &token.Token{
ID: token.T_USE,
Value: []byte("use"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
},
},
UseOpenParenthesisTkn: &token.Token{
ID: token.ID(40),
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,
},
},
},
},
Uses: []ast.Vertex{
&ast.ExprClosureUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 28,
},
AmpersandTkn: &token.Token{
ID: token.T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG,
Value: []byte("&"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 28,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 28,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$c"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 28,
},
},
Value: []byte("$c"),
},
},
},
&ast.ExprClosureUse{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 32,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 32,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 32,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$d"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 32,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 29,
EndPos: 30,
},
},
},
},
Value: []byte("$d"),
},
},
},
},
UseSeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 28,
EndPos: 29,
},
},
},
UseCloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 32,
EndPos: 33,
},
},
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,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 36,
EndPos: 37,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprClosure_ReturnType(t *testing.T) {
src := `<? function(): void {};`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Expr: &ast.ExprClosure{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 22,
},
FunctionTkn: &token.Token{
ID: token.T_FUNCTION,
Value: []byte("function"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
ReturnType: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 19,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 19,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("void"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
Value: []byte("void"),
},
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprConstFetch(t *testing.T) {
src := `<? foo;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Expr: &ast.ExprConstFetch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
Const: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("foo"),
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprConstFetch_Relative(t *testing.T) {
src := `<? namespace\foo;`
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.ExprConstFetch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 16,
},
Const: &ast.NameRelative{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 16,
},
NsTkn: &token.Token{
ID: token.T_NAMESPACE,
Value: []byte("namespace"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
},
Value: []byte("foo"),
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprConstFetch_FullyQualified(t *testing.T) {
src := `<? \foo;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
Expr: &ast.ExprConstFetch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Const: &ast.NameFullyQualified{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 7,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 7,
},
},
Value: []byte("foo"),
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprEmpty(t *testing.T) {
src := `<? empty($a);`
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.ExprEmpty{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
EmptyTkn: &token.Token{
ID: token.T_EMPTY,
Value: []byte("empty"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
},
Value: []byte("$a"),
},
},
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprErrorSuppress(t *testing.T) {
src := `<? @$a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Expr: &ast.ExprErrorSuppress{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
AtTkn: &token.Token{
ID: token.ID(64),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprEval(t *testing.T) {
src := `<? eval($a);`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Expr: &ast.ExprEval{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
EvalTkn: &token.Token{
ID: token.T_EVAL,
Value: []byte("eval"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
},
Value: []byte("$a"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprExit(t *testing.T) {
src := `<? exit;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
Expr: &ast.ExprExit{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
ExitTkn: &token.Token{
ID: token.T_EXIT,
Value: []byte("exit"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprExit_Empty(t *testing.T) {
src := `<? exit();`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 10,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 10,
},
Expr: &ast.ExprExit{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
ExitTkn: &token.Token{
ID: token.T_EXIT,
Value: []byte("exit"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprExit_Expr(t *testing.T) {
src := `<? exit($a);`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Expr: &ast.ExprExit{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
ExitTkn: &token.Token{
ID: token.T_EXIT,
Value: []byte("exit"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
},
Value: []byte("$a"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprDie(t *testing.T) {
src := `<? die;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Expr: &ast.ExprExit{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
ExitTkn: &token.Token{
ID: token.T_EXIT,
Value: []byte("die"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprDie_Empty(t *testing.T) {
src := `<? die();`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
Expr: &ast.ExprExit{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
ExitTkn: &token.Token{
ID: token.T_EXIT,
Value: []byte("die"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprDie_Expr(t *testing.T) {
src := `<? die($a);`
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.ExprExit{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 10,
},
ExitTkn: &token.Token{
ID: token.T_EXIT,
Value: []byte("die"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
},
Value: []byte("$a"),
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprFunctionCall(t *testing.T) {
src := `<? foo();`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
Expr: &ast.ExprFunctionCall{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
Function: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("foo"),
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprFunctionCall_Relative(t *testing.T) {
src := `<? namespace\foo();`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Expr: &ast.ExprFunctionCall{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 18,
},
Function: &ast.NameRelative{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 16,
},
NsTkn: &token.Token{
ID: token.T_NAMESPACE,
Value: []byte("namespace"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
},
Value: []byte("foo"),
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprFunctionCall_FullyQualified(t *testing.T) {
src := `<? \foo([]);`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Expr: &ast.ExprFunctionCall{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
Function: &ast.NameFullyQualified{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 7,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 7,
},
},
Value: []byte("foo"),
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
Args: []ast.Vertex{
&ast.Argument{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
Expr: &ast.ExprArray{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
OpenBracketTkn: &token.Token{
ID: token.ID(91),
Value: []byte("["),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(93),
Value: []byte("]"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprFunctionCall_Var(t *testing.T) {
src := `<? $foo(yield $a);`
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.ExprFunctionCall{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 17,
},
Function: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$foo"),
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
Args: []ast.Vertex{
&ast.Argument{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 16,
},
Expr: &ast.ExprYield{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 16,
},
YieldTkn: &token.Token{
ID: token.T_YIELD,
Value: []byte("yield"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 13,
},
},
Val: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
Value: []byte("$a"),
},
},
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprFunctionCall_ExprArg(t *testing.T) {
src := `<? ceil($foo/3);`
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.ExprFunctionCall{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Function: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("ceil"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("ceil"),
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
Args: []ast.Vertex{
&ast.Argument{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 14,
},
Expr: &ast.ExprBinaryDiv{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 14,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 12,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 12,
},
},
Value: []byte("$foo"),
},
},
OpTkn: &token.Token{
ID: token.ID(47),
Value: []byte("/"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
Right: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("3"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
Value: []byte("3"),
},
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprPostDec(t *testing.T) {
src := `<? $a--;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
Expr: &ast.ExprPostDec{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$a"),
},
},
DecTkn: &token.Token{
ID: token.T_DEC,
Value: []byte("--"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 7,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprPostInc(t *testing.T) {
src := `<? $a++;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
Expr: &ast.ExprPostInc{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$a"),
},
},
IncTkn: &token.Token{
ID: token.T_INC,
Value: []byte("++"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 7,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprPreDec(t *testing.T) {
src := `<? --$a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
Expr: &ast.ExprPreDec{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
DecTkn: &token.Token{
ID: token.T_DEC,
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 7,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 7,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 7,
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprPreInc(t *testing.T) {
src := `<? ++$a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
Expr: &ast.ExprPreInc{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
IncTkn: &token.Token{
ID: token.T_INC,
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 7,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 7,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 7,
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprInclude(t *testing.T) {
src := `<? include $a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Expr: &ast.ExprInclude{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
IncludeTkn: &token.Token{
ID: token.T_INCLUDE,
Value: []byte("include"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Expr: &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("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 13,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprInclude_Once(t *testing.T) {
src := `<? include_once $a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Expr: &ast.ExprIncludeOnce{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 18,
},
IncludeOnceTkn: &token.Token{
ID: token.T_INCLUDE_ONCE,
Value: []byte("include_once"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Expr: &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("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprRequire(t *testing.T) {
src := `<? require $a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Expr: &ast.ExprRequire{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
RequireTkn: &token.Token{
ID: token.T_REQUIRE,
Value: []byte("require"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Expr: &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("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 13,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprRequire_Once(t *testing.T) {
src := `<? require_once $a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Expr: &ast.ExprRequireOnce{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 18,
},
RequireOnceTkn: &token.Token{
ID: token.T_REQUIRE_ONCE,
Value: []byte("require_once"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Expr: &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("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprInstanceOf(t *testing.T) {
src := `<? $a instanceof Foo;`
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.ExprInstanceOf{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 20,
},
Expr: &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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$a"),
},
},
InstanceOfTkn: &token.Token{
ID: token.T_INSTANCEOF,
Value: []byte("instanceof"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
Class: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 20,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 20,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
Value: []byte("Foo"),
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprInstanceOf_Relative(t *testing.T) {
src := `<? $a instanceof namespace\Foo;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 31,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 31,
},
Expr: &ast.ExprInstanceOf{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 30,
},
Expr: &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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$a"),
},
},
InstanceOfTkn: &token.Token{
ID: token.T_INSTANCEOF,
Value: []byte("instanceof"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
Class: &ast.NameRelative{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 30,
},
NsTkn: &token.Token{
ID: token.T_NAMESPACE,
Value: []byte("namespace"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 26,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 30,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 30,
},
},
Value: []byte("Foo"),
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 30,
EndPos: 31,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprInstanceOf_FullyQualified(t *testing.T) {
src := `<? $a instanceof \Foo;`
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.ExprInstanceOf{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 21,
},
Expr: &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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$a"),
},
},
InstanceOfTkn: &token.Token{
ID: token.T_INSTANCEOF,
Value: []byte("instanceof"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
Class: &ast.NameFullyQualified{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 21,
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
},
Value: []byte("Foo"),
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprIsset(t *testing.T) {
src := `<? isset($a);`
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.ExprIsset{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
IssetTkn: &token.Token{
ID: token.T_ISSET,
Value: []byte("isset"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
Vars: []ast.Vertex{
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
},
Value: []byte("$a"),
},
},
},
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprIsset_Variables(t *testing.T) {
src := `<? isset($a, $b);`
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.ExprIsset{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 16,
},
IssetTkn: &token.Token{
ID: token.T_ISSET,
Value: []byte("isset"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
Vars: []ast.Vertex{
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
},
Value: []byte("$a"),
},
},
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Value: []byte("$b"),
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprList_Empty(t *testing.T) {
src := `<? list() = $b;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Expr: &ast.ExprAssign{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Var: &ast.ExprList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
ListTkn: &token.Token{
ID: token.T_LIST,
Value: []byte("list"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
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,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
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,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprList(t *testing.T) {
src := `<? list($a) = $b;`
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.ExprAssign{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 16,
},
Var: &ast.ExprList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
ListTkn: &token.Token{
ID: token.T_LIST,
Value: []byte("list"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
Items: []ast.Vertex{
&ast.ExprArrayItem{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
Val: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
},
Value: []byte("$a"),
},
},
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprList_ArrayIndex(t *testing.T) {
src := `<? list($a[]) = $b;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Expr: &ast.ExprAssign{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 18,
},
Var: &ast.ExprList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
ListTkn: &token.Token{
ID: token.T_LIST,
Value: []byte("list"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
Items: []ast.Vertex{
&ast.ExprArrayItem{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 12,
},
Val: &ast.ExprArrayDimFetch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 12,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
},
Value: []byte("$a"),
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(91),
Value: []byte("["),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(93),
Value: []byte("]"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
Expr: &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,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprList_List(t *testing.T) {
src := `<? list(list($a)) = $b;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Expr: &ast.ExprAssign{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 22,
},
Var: &ast.ExprList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 17,
},
ListTkn: &token.Token{
ID: token.T_LIST,
Value: []byte("list"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
Items: []ast.Vertex{
&ast.ExprArrayItem{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 16,
},
Val: &ast.ExprList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 16,
},
ListTkn: &token.Token{
ID: token.T_LIST,
Value: []byte("list"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 12,
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
Items: []ast.Vertex{
&ast.ExprArrayItem{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
Val: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
},
Value: []byte("$a"),
},
},
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 22,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 22,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprList_EmptyItem(t *testing.T) {
src := `<? list(, $a) = $b;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Expr: &ast.ExprAssign{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 18,
},
Var: &ast.ExprList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
ListTkn: &token.Token{
ID: token.T_LIST,
Value: []byte("list"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
Items: []ast.Vertex{
&ast.ExprArrayItem{},
&ast.ExprArrayItem{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
Val: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
},
},
Value: []byte("$a"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
Expr: &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,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprList_EmptyItems(t *testing.T) {
src := `<? list(, , $a, ) = $b;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Expr: &ast.ExprAssign{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 22,
},
Var: &ast.ExprList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 17,
},
ListTkn: &token.Token{
ID: token.T_LIST,
Value: []byte("list"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
Items: []ast.Vertex{
&ast.ExprArrayItem{},
&ast.ExprArrayItem{},
&ast.ExprArrayItem{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
Val: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
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,
},
},
},
},
Value: []byte("$a"),
},
},
},
&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: 10,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
},
},
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 22,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 22,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 19,
EndPos: 20,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprMethodCall(t *testing.T) {
src := `<? $a->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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$a"),
},
},
ObjectOperatorTkn: &token.Token{
ID: token.T_OBJECT_OPERATOR,
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprNew(t *testing.T) {
src := `<? new 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.ExprNew{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 10,
},
NewTkn: &token.Token{
ID: token.T_NEW,
Value: []byte("new"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Class: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprNew_Relative(t *testing.T) {
src := `<? new namespace\Foo();`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Expr: &ast.ExprNew{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 22,
},
NewTkn: &token.Token{
ID: token.T_NEW,
Value: []byte("new"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Class: &ast.NameRelative{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 20,
},
NsTkn: &token.Token{
ID: token.T_NAMESPACE,
Value: []byte("namespace"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 20,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 20,
},
},
Value: []byte("Foo"),
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprNew_FullyQualified(t *testing.T) {
src := `<? new \Foo();`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Expr: &ast.ExprNew{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
NewTkn: &token.Token{
ID: token.T_NEW,
Value: []byte("new"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Class: &ast.NameFullyQualified{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 11,
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 11,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 11,
},
},
Value: []byte("Foo"),
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprNew_Anonymous(t *testing.T) {
src := `<? new class ($a, ...$b) {};`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 28,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 28,
},
Expr: &ast.ExprNew{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 27,
},
NewTkn: &token.Token{
ID: token.T_NEW,
Value: []byte("new"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Class: &ast.StmtClass{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 27,
},
ClassTkn: &token.Token{
ID: token.T_CLASS,
Value: []byte("class"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Args: []ast.Vertex{
&ast.Argument{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
},
Value: []byte("$a"),
},
},
},
&ast.Argument{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 23,
},
VariadicTkn: &token.Token{
ID: token.T_ELLIPSIS,
Value: []byte("..."),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 23,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 23,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 23,
},
},
Value: []byte("$b"),
},
},
},
},
SeparatorTkns: []*token.Token{
{
ID: token.ID(44),
Value: []byte(","),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 24,
},
},
OpenCurlyBracketTkn: &token.Token{
ID: token.ID(123),
Value: []byte("{"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 24,
EndPos: 25,
},
},
},
},
Stmts: []ast.Vertex{},
CloseCurlyBracketTkn: &token.Token{
ID: token.ID(125),
Value: []byte("}"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 26,
EndPos: 27,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 27,
EndPos: 28,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprPrint(t *testing.T) {
src := `<? print($a);`
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.ExprPrint{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
PrintTkn: &token.Token{
ID: token.T_PRINT,
Value: []byte("print"),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Expr: &ast.ExprBrackets{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 12,
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
},
Value: []byte("$a"),
},
},
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprPropertyFetch(t *testing.T) {
src := `<? $a->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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$a"),
},
},
ObjectOperatorTkn: &token.Token{
ID: token.T_OBJECT_OPERATOR,
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprShellExec(t *testing.T) {
src := "<? `cmd $a`;"
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Expr: &ast.ExprShellExec{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
OpenBacktickTkn: &token.Token{
ID: token.ID(96),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 8,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("cmd "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 8,
},
},
Value: []byte("cmd "),
},
&ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
},
Value: []byte("$a"),
},
},
},
CloseBacktickTkn: &token.Token{
ID: token.ID(96),
Value: []byte("`"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprShortArray(t *testing.T) {
src := `<? [];`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
Expr: &ast.ExprArray{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 5,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(93),
Value: []byte("]"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 5,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprShortArray_Item(t *testing.T) {
src := `<? [1];`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Expr: &ast.ExprArray{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Items: []ast.Vertex{
&ast.ExprArrayItem{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 5,
},
Val: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 5,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 5,
},
},
Value: []byte("1"),
},
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(93),
Value: []byte("]"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprShortArray_Items(t *testing.T) {
src := `<? [1=>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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Items: []ast.Vertex{
&ast.ExprArrayItem{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 8,
},
Key: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 5,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 5,
},
},
Value: []byte("1"),
},
DoubleArrowTkn: &token.Token{
ID: token.T_DOUBLE_ARROW,
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.T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG,
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprShortList(t *testing.T) {
src := `<? [$a] = $b;`
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.ExprAssign{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Var: &ast.ExprList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Items: []ast.Vertex{
&ast.ExprArrayItem{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
Val: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
},
Value: []byte("$a"),
},
},
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(93),
Value: []byte("]"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprShortList_ArrayIndex(t *testing.T) {
src := `<? [$a[]] = $b;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Expr: &ast.ExprAssign{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Var: &ast.ExprList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Items: []ast.Vertex{
&ast.ExprArrayItem{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 8,
},
Val: &ast.ExprArrayDimFetch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 8,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
},
Value: []byte("$a"),
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(91),
Value: []byte("["),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(93),
Value: []byte("]"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(93),
Value: []byte("]"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
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,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 14,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
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,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprShortList_List(t *testing.T) {
src := `<? [list($a)] = $b;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 19,
},
Expr: &ast.ExprAssign{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 18,
},
Var: &ast.ExprList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Items: []ast.Vertex{
&ast.ExprArrayItem{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 12,
},
Val: &ast.ExprList{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 12,
},
ListTkn: &token.Token{
ID: token.T_LIST,
Value: []byte("list"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 8,
},
},
OpenBracketTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
Items: []ast.Vertex{
&ast.ExprArrayItem{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Val: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
},
Value: []byte("$a"),
},
},
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
},
CloseBracketTkn: &token.Token{
ID: token.ID(93),
Value: []byte("]"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
Expr: &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,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 19,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprStaticCall(t *testing.T) {
src := `<? Foo::bar();`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Expr: &ast.ExprStaticCall{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
Class: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("Foo"),
},
},
},
DoubleColonTkn: &token.Token{
ID: token.T_PAAMAYIM_NEKUDOTAYIM,
Value: []byte("::"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 8,
},
},
Call: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 11,
},
},
Value: []byte("bar"),
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprStaticCall_Relative(t *testing.T) {
src := `<? namespace\Foo::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.ExprStaticCall{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Class: &ast.NameRelative{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 16,
},
NsTkn: &token.Token{
ID: token.T_NAMESPACE,
Value: []byte("namespace"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
},
Value: []byte("Foo"),
},
},
},
DoubleColonTkn: &token.Token{
ID: token.T_PAAMAYIM_NEKUDOTAYIM,
Value: []byte("::"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 18,
},
},
Call: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 21,
},
},
Value: []byte("bar"),
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprStaticCall_FullyQualified(t *testing.T) {
src := `<? \Foo::bar();`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Expr: &ast.ExprStaticCall{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Class: &ast.NameFullyQualified{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 7,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 7,
},
},
Value: []byte("Foo"),
},
},
},
DoubleColonTkn: &token.Token{
ID: token.T_PAAMAYIM_NEKUDOTAYIM,
Value: []byte("::"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
},
Call: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 12,
},
},
Value: []byte("bar"),
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprStaticCall_Var(t *testing.T) {
src := `<? Foo::$bar();`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Expr: &ast.ExprStaticCall{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Class: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("Foo"),
},
},
},
DoubleColonTkn: &token.Token{
ID: token.T_PAAMAYIM_NEKUDOTAYIM,
Value: []byte("::"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 8,
},
},
Call: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 12,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 12,
},
},
Value: []byte("$bar"),
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 15,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprStaticCall_VarVar(t *testing.T) {
src := `<? $foo::$bar();`
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.ExprStaticCall{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Class: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$foo"),
},
},
DoubleColonTkn: &token.Token{
ID: token.T_PAAMAYIM_NEKUDOTAYIM,
Value: []byte("::"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
},
Call: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 13,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 13,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 13,
},
},
Value: []byte("$bar"),
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprStaticPropertyFetch(t *testing.T) {
src := `<? Foo::$bar;`
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.ExprStaticPropertyFetch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Class: &ast.Name{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("Foo"),
},
},
},
DoubleColonTkn: &token.Token{
ID: token.T_PAAMAYIM_NEKUDOTAYIM,
Value: []byte("::"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 8,
},
},
Prop: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 12,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 12,
},
},
Value: []byte("$bar"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprStaticPropertyFetch_Relative(t *testing.T) {
src := `<? namespace\Foo::$bar;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 23,
},
Expr: &ast.ExprStaticPropertyFetch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 22,
},
Class: &ast.NameRelative{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 16,
},
NsTkn: &token.Token{
ID: token.T_NAMESPACE,
Value: []byte("namespace"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
Value: []byte("\\"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 16,
},
},
Value: []byte("Foo"),
},
},
},
DoubleColonTkn: &token.Token{
ID: token.T_PAAMAYIM_NEKUDOTAYIM,
Value: []byte("::"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 18,
},
},
Prop: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 22,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 22,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 22,
},
},
Value: []byte("$bar"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprStaticPropertyFetch_FullyQualified(t *testing.T) {
src := `<? \Foo::$bar;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 14,
},
Expr: &ast.ExprStaticPropertyFetch{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
Class: &ast.NameFullyQualified{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
NsSeparatorTkn: &token.Token{
ID: token.T_NS_SEPARATOR,
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 7,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 7,
},
},
Value: []byte("Foo"),
},
},
},
DoubleColonTkn: &token.Token{
ID: token.T_PAAMAYIM_NEKUDOTAYIM,
Value: []byte("::"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 9,
},
},
Prop: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 13,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 13,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$bar"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 13,
},
},
Value: []byte("$bar"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprTernary(t *testing.T) {
src := `<? $a ? $b : $c;`
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.ExprTernary{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Cond: &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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$a"),
},
},
QuestionTkn: &token.Token{
ID: token.ID(63),
Value: []byte("?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
IfTrue: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
},
Value: []byte("$b"),
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
IfFalse: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$c"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Value: []byte("$c"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprTernary_Simple(t *testing.T) {
src := `<? $a ? : $c;`
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.ExprTernary{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Cond: &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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$a"),
},
},
QuestionTkn: &token.Token{
ID: token.ID(63),
Value: []byte("?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
},
IfFalse: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$c"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
},
},
},
Value: []byte("$c"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprTernary_NestedTrue(t *testing.T) {
src := `<? $a ? $b ? $c : $d : $e;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 26,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 26,
},
Expr: &ast.ExprTernary{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 25,
},
Cond: &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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$a"),
},
},
QuestionTkn: &token.Token{
ID: token.ID(63),
Value: []byte("?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
IfTrue: &ast.ExprTernary{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 20,
},
Cond: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
},
Value: []byte("$b"),
},
},
QuestionTkn: &token.Token{
ID: token.ID(63),
Value: []byte("?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
IfTrue: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$c"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Value: []byte("$c"),
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
IfFalse: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$d"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("$d"),
},
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
},
},
IfFalse: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 25,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 25,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$e"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 25,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
Value: []byte("$e"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprTernary_NestedCond(t *testing.T) {
src := `<? $a ? $b : $c ? $d : $e;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 26,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 26,
},
Expr: &ast.ExprTernary{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 25,
},
Cond: &ast.ExprTernary{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 15,
},
Cond: &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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$a"),
},
},
QuestionTkn: &token.Token{
ID: token.ID(63),
Value: []byte("?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
IfTrue: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 7,
EndPos: 8,
},
},
},
},
Value: []byte("$b"),
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
IfFalse: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$c"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 15,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 12,
EndPos: 13,
},
},
},
},
Value: []byte("$c"),
},
},
},
QuestionTkn: &token.Token{
ID: token.ID(63),
Value: []byte("?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 15,
EndPos: 16,
},
},
},
},
IfTrue: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$d"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 18,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 17,
EndPos: 18,
},
},
},
},
Value: []byte("$d"),
},
},
ColonTkn: &token.Token{
ID: token.ID(58),
Value: []byte(":"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 21,
EndPos: 22,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 20,
EndPos: 21,
},
},
},
},
IfFalse: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 25,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 25,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$e"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 23,
EndPos: 25,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 22,
EndPos: 23,
},
},
},
},
Value: []byte("$e"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 25,
EndPos: 26,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprUnaryMinus(t *testing.T) {
src := `<? -$a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Expr: &ast.ExprUnaryMinus{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
MinusTkn: &token.Token{
ID: token.ID(45),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprUnaryPlus(t *testing.T) {
src := `<? +$a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Expr: &ast.ExprUnaryPlus{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
PlusTkn: &token.Token{
ID: token.ID(43),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprVariable(t *testing.T) {
src := `<? $a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
Expr: &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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Value: []byte("$a"),
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 5,
EndPos: 6,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprVariable_Variable(t *testing.T) {
src := `<? $$a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 7,
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 6,
},
DollarTkn: &token.Token{
ID: token.ID(36),
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Name: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 4,
EndPos: 6,
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 6,
EndPos: 7,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprYield(t *testing.T) {
src := `<? yield;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 9,
},
Expr: &ast.ExprYield{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 8,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprYield_Val(t *testing.T) {
src := `<? yield $a;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 12,
},
Expr: &ast.ExprYield{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 11,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Val: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 11,
EndPos: 12,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprYield_KeyVal(t *testing.T) {
src := `<? yield $a => $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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Key: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("$a"),
},
},
DoubleArrowTkn: &token.Token{
ID: token.T_DOUBLE_ARROW,
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprYield_Expr(t *testing.T) {
src := `<? yield 1;`
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.ExprYield{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 10,
},
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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Val: &ast.ScalarLnumber{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
NumberTkn: &token.Token{
ID: token.T_LNUMBER,
Value: []byte("1"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 10,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("1"),
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 10,
EndPos: 11,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprYield_KeyExpr(t *testing.T) {
src := `<? yield $a => 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: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Key: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 9,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 8,
EndPos: 9,
},
},
},
},
Value: []byte("$a"),
},
},
DoubleArrowTkn: &token.Token{
ID: token.T_DOUBLE_ARROW,
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 := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestExprYieldFrom(t *testing.T) {
src := `<? yield from $a;`
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.ExprYieldFrom{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 16,
},
YieldFromTkn: &token.Token{
ID: token.T_YIELD_FROM,
Value: []byte("yield from"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 3,
EndPos: 13,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 2,
EndPos: 3,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 14,
EndPos: 16,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 13,
EndPos: 14,
},
},
},
},
Value: []byte("$a"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 16,
EndPos: 17,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
// expr assign
func TestExprAssign_Assign(t *testing.T) {
src := `<?
$a = $b;
$a =& $b;
$a =& new Foo;
$a =& new Foo($b);
$a &= $b;
$a |= $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: 18,
StartPos: 5,
EndPos: 223,
},
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: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 8,
EndPos: 9,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 7,
EndPos: 8,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 10,
EndPos: 12,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 10,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 10,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 10,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 13,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 16,
EndPos: 25,
},
Expr: &ast.ExprAssignReference{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 16,
EndPos: 24,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 16,
EndPos: 18,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 16,
EndPos: 18,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 16,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 13,
EndPos: 16,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 19,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 18,
EndPos: 19,
},
},
},
},
AmpersandTkn: &token.Token{
ID: token.T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG,
Value: []byte("&"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 20,
EndPos: 21,
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 22,
EndPos: 24,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 22,
EndPos: 24,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 22,
EndPos: 24,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 21,
EndPos: 22,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 24,
EndPos: 25,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 28,
EndPos: 42,
},
Expr: &ast.ExprAssignReference{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 28,
EndPos: 41,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 28,
EndPos: 30,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 28,
EndPos: 30,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 28,
EndPos: 30,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 3,
EndLine: 4,
StartPos: 25,
EndPos: 28,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 31,
EndPos: 32,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 30,
EndPos: 31,
},
},
},
},
AmpersandTkn: &token.Token{
ID: token.T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG,
Value: []byte("&"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 32,
EndPos: 33,
},
},
Expr: &ast.ExprNew{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 34,
EndPos: 41,
},
NewTkn: &token.Token{
ID: token.T_NEW,
Value: []byte("new"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 34,
EndPos: 37,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 33,
EndPos: 34,
},
},
},
},
Class: &ast.Name{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 38,
EndPos: 41,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 38,
EndPos: 41,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 38,
EndPos: 41,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 37,
EndPos: 38,
},
},
},
},
Value: []byte("Foo"),
},
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 41,
EndPos: 42,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 45,
EndPos: 63,
},
Expr: &ast.ExprAssignReference{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 45,
EndPos: 62,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 45,
EndPos: 47,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 45,
EndPos: 47,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 45,
EndPos: 47,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 4,
EndLine: 5,
StartPos: 42,
EndPos: 45,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.ID(61),
Value: []byte("="),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 48,
EndPos: 49,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 47,
EndPos: 48,
},
},
},
},
AmpersandTkn: &token.Token{
ID: token.T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG,
Value: []byte("&"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 49,
EndPos: 50,
},
},
Expr: &ast.ExprNew{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 51,
EndPos: 62,
},
NewTkn: &token.Token{
ID: token.T_NEW,
Value: []byte("new"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 51,
EndPos: 54,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 50,
EndPos: 51,
},
},
},
},
Class: &ast.Name{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 55,
EndPos: 58,
},
Parts: []ast.Vertex{
&ast.NamePart{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 55,
EndPos: 58,
},
StringTkn: &token.Token{
ID: token.T_STRING,
Value: []byte("Foo"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 55,
EndPos: 58,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 54,
EndPos: 55,
},
},
},
},
Value: []byte("Foo"),
},
},
},
OpenParenthesisTkn: &token.Token{
ID: token.ID(40),
Value: []byte("("),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 58,
EndPos: 59,
},
},
Args: []ast.Vertex{
&ast.Argument{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 59,
EndPos: 61,
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 59,
EndPos: 61,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 59,
EndPos: 61,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 59,
EndPos: 61,
},
},
Value: []byte("$b"),
},
},
},
},
CloseParenthesisTkn: &token.Token{
ID: token.ID(41),
Value: []byte(")"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 61,
EndPos: 62,
},
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 62,
EndPos: 63,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 66,
EndPos: 75,
},
Expr: &ast.ExprAssignBitwiseAnd{
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 66,
EndPos: 74,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 66,
EndPos: 68,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 66,
EndPos: 68,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 66,
EndPos: 68,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 5,
EndLine: 6,
StartPos: 63,
EndPos: 66,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.T_AND_EQUAL,
Value: []byte("&="),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 69,
EndPos: 71,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 68,
EndPos: 69,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 72,
EndPos: 74,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 72,
EndPos: 74,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 72,
EndPos: 74,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 71,
EndPos: 72,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 74,
EndPos: 75,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 78,
EndPos: 87,
},
Expr: &ast.ExprAssignBitwiseOr{
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 78,
EndPos: 86,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 78,
EndPos: 80,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 78,
EndPos: 80,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 78,
EndPos: 80,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 6,
EndLine: 7,
StartPos: 75,
EndPos: 78,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.T_OR_EQUAL,
Value: []byte("|="),
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 81,
EndPos: 83,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 80,
EndPos: 81,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 84,
EndPos: 86,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 84,
EndPos: 86,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 84,
EndPos: 86,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 83,
EndPos: 84,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 86,
EndPos: 87,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 90,
EndPos: 99,
},
Expr: &ast.ExprAssignBitwiseXor{
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 90,
EndPos: 98,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 90,
EndPos: 92,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 90,
EndPos: 92,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 90,
EndPos: 92,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 7,
EndLine: 8,
StartPos: 87,
EndPos: 90,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.T_XOR_EQUAL,
Value: []byte("^="),
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 93,
EndPos: 95,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 92,
EndPos: 93,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 96,
EndPos: 98,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 96,
EndPos: 98,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 96,
EndPos: 98,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 95,
EndPos: 96,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 98,
EndPos: 99,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 102,
EndPos: 111,
},
Expr: &ast.ExprAssignConcat{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 102,
EndPos: 110,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 102,
EndPos: 104,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 102,
EndPos: 104,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 102,
EndPos: 104,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 8,
EndLine: 9,
StartPos: 99,
EndPos: 102,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.T_CONCAT_EQUAL,
Value: []byte(".="),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 105,
EndPos: 107,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 104,
EndPos: 105,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 108,
EndPos: 110,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 108,
EndPos: 110,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 108,
EndPos: 110,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 107,
EndPos: 108,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 110,
EndPos: 111,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 114,
EndPos: 123,
},
Expr: &ast.ExprAssignDiv{
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 114,
EndPos: 122,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 114,
EndPos: 116,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 114,
EndPos: 116,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 114,
EndPos: 116,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 9,
EndLine: 10,
StartPos: 111,
EndPos: 114,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.T_DIV_EQUAL,
Value: []byte("/="),
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 117,
EndPos: 119,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 116,
EndPos: 117,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 120,
EndPos: 122,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 120,
EndPos: 122,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 120,
EndPos: 122,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 119,
EndPos: 120,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 122,
EndPos: 123,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 126,
EndPos: 135,
},
Expr: &ast.ExprAssignMinus{
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 126,
EndPos: 134,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 126,
EndPos: 128,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 126,
EndPos: 128,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 126,
EndPos: 128,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 10,
EndLine: 11,
StartPos: 123,
EndPos: 126,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.T_MINUS_EQUAL,
Value: []byte("-="),
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 129,
EndPos: 131,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 128,
EndPos: 129,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 132,
EndPos: 134,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 132,
EndPos: 134,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 132,
EndPos: 134,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 131,
EndPos: 132,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 134,
EndPos: 135,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 138,
EndPos: 147,
},
Expr: &ast.ExprAssignMod{
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 138,
EndPos: 146,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 138,
EndPos: 140,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 138,
EndPos: 140,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 138,
EndPos: 140,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 11,
EndLine: 12,
StartPos: 135,
EndPos: 138,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.T_MOD_EQUAL,
Value: []byte("%="),
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 141,
EndPos: 143,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 140,
EndPos: 141,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 144,
EndPos: 146,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 144,
EndPos: 146,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 144,
EndPos: 146,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 143,
EndPos: 144,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 146,
EndPos: 147,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 150,
EndPos: 159,
},
Expr: &ast.ExprAssignMul{
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 150,
EndPos: 158,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 150,
EndPos: 152,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 150,
EndPos: 152,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 150,
EndPos: 152,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 12,
EndLine: 13,
StartPos: 147,
EndPos: 150,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.T_MUL_EQUAL,
Value: []byte("*="),
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 153,
EndPos: 155,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 152,
EndPos: 153,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 156,
EndPos: 158,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 156,
EndPos: 158,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 156,
EndPos: 158,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 155,
EndPos: 156,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 158,
EndPos: 159,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 162,
EndPos: 171,
},
Expr: &ast.ExprAssignPlus{
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 162,
EndPos: 170,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 162,
EndPos: 164,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 162,
EndPos: 164,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 162,
EndPos: 164,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 13,
EndLine: 14,
StartPos: 159,
EndPos: 162,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.T_PLUS_EQUAL,
Value: []byte("+="),
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 165,
EndPos: 167,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 164,
EndPos: 165,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 168,
EndPos: 170,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 168,
EndPos: 170,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 168,
EndPos: 170,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 167,
EndPos: 168,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 170,
EndPos: 171,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 174,
EndPos: 184,
},
Expr: &ast.ExprAssignPow{
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 174,
EndPos: 183,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 174,
EndPos: 176,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 174,
EndPos: 176,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 174,
EndPos: 176,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 14,
EndLine: 15,
StartPos: 171,
EndPos: 174,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.T_POW_EQUAL,
Value: []byte("**="),
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 177,
EndPos: 180,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 176,
EndPos: 177,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 181,
EndPos: 183,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 181,
EndPos: 183,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 181,
EndPos: 183,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 180,
EndPos: 181,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 183,
EndPos: 184,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 187,
EndPos: 197,
},
Expr: &ast.ExprAssignShiftLeft{
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 187,
EndPos: 196,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 187,
EndPos: 189,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 187,
EndPos: 189,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 187,
EndPos: 189,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 15,
EndLine: 16,
StartPos: 184,
EndPos: 187,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.T_SL_EQUAL,
Value: []byte("<<="),
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 190,
EndPos: 193,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 189,
EndPos: 190,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 194,
EndPos: 196,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 194,
EndPos: 196,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 194,
EndPos: 196,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 193,
EndPos: 194,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 196,
EndPos: 197,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 200,
EndPos: 210,
},
Expr: &ast.ExprAssignShiftRight{
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 200,
EndPos: 209,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 200,
EndPos: 202,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 200,
EndPos: 202,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 200,
EndPos: 202,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 16,
EndLine: 17,
StartPos: 197,
EndPos: 200,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.T_SR_EQUAL,
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,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 213,
EndPos: 223,
},
Expr: &ast.ExprAssignCoalesce{
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 213,
EndPos: 222,
},
Var: &ast.ExprVariable{
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 213,
EndPos: 215,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 213,
EndPos: 215,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 213,
EndPos: 215,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 17,
EndLine: 18,
StartPos: 210,
EndPos: 213,
},
},
},
},
Value: []byte("$a"),
},
},
EqualTkn: &token.Token{
ID: token.T_COALESCE_EQUAL,
Value: []byte("??="),
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 216,
EndPos: 219,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 215,
EndPos: 216,
},
},
},
},
Expr: &ast.ExprVariable{
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 220,
EndPos: 222,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 220,
EndPos: 222,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 220,
EndPos: 222,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 219,
EndPos: 220,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 222,
EndPos: 223,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
// expr binary
func TestExprBinary_BitwiseAnd(t *testing.T) {
src := `<?
$a & $b;
$a | $b;
$a ^ $b;
$a && $b;
$a || $b;
$a ?? $b;
$a . $b;
$a / $b;
$a == $b;
$a >= $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;
$a <=> $b;`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 28,
StartPos: 5,
EndPos: 320,
},
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: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG,
Value: []byte("&"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 8,
EndPos: 9,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 7,
EndPos: 8,
},
},
},
},
Right: &ast.ExprVariable{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 10,
EndPos: 12,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 10,
EndPos: 12,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 10,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 9,
EndPos: 10,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 12,
EndPos: 13,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 16,
EndPos: 24,
},
Expr: &ast.ExprBinaryBitwiseOr{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 16,
EndPos: 23,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 16,
EndPos: 18,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 16,
EndPos: 18,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 16,
EndPos: 18,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 13,
EndPos: 16,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.ID(124),
Value: []byte("|"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 19,
EndPos: 20,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 18,
EndPos: 19,
},
},
},
},
Right: &ast.ExprVariable{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 21,
EndPos: 23,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 21,
EndPos: 23,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 21,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 20,
EndPos: 21,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 23,
EndPos: 24,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 27,
EndPos: 35,
},
Expr: &ast.ExprBinaryBitwiseXor{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 27,
EndPos: 34,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 27,
EndPos: 29,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 27,
EndPos: 29,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 27,
EndPos: 29,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 3,
EndLine: 4,
StartPos: 24,
EndPos: 27,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.ID(94),
Value: []byte("^"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 30,
EndPos: 31,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 29,
EndPos: 30,
},
},
},
},
Right: &ast.ExprVariable{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 32,
EndPos: 34,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 32,
EndPos: 34,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 32,
EndPos: 34,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 31,
EndPos: 32,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 34,
EndPos: 35,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 38,
EndPos: 47,
},
Expr: &ast.ExprBinaryBooleanAnd{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 38,
EndPos: 46,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 38,
EndPos: 40,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 38,
EndPos: 40,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 38,
EndPos: 40,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 4,
EndLine: 5,
StartPos: 35,
EndPos: 38,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.T_BOOLEAN_AND,
Value: []byte("&&"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 41,
EndPos: 43,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 40,
EndPos: 41,
},
},
},
},
Right: &ast.ExprVariable{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 44,
EndPos: 46,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 44,
EndPos: 46,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 44,
EndPos: 46,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 43,
EndPos: 44,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 46,
EndPos: 47,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 50,
EndPos: 59,
},
Expr: &ast.ExprBinaryBooleanOr{
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 50,
EndPos: 58,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 50,
EndPos: 52,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 50,
EndPos: 52,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 50,
EndPos: 52,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 5,
EndLine: 6,
StartPos: 47,
EndPos: 50,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.T_BOOLEAN_OR,
Value: []byte("||"),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 53,
EndPos: 55,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 52,
EndPos: 53,
},
},
},
},
Right: &ast.ExprVariable{
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 56,
EndPos: 58,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 56,
EndPos: 58,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 56,
EndPos: 58,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 55,
EndPos: 56,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 58,
EndPos: 59,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 62,
EndPos: 71,
},
Expr: &ast.ExprBinaryCoalesce{
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 62,
EndPos: 70,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 62,
EndPos: 64,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 62,
EndPos: 64,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 62,
EndPos: 64,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 6,
EndLine: 7,
StartPos: 59,
EndPos: 62,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.T_COALESCE,
Value: []byte("??"),
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 65,
EndPos: 67,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 64,
EndPos: 65,
},
},
},
},
Right: &ast.ExprVariable{
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 68,
EndPos: 70,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 68,
EndPos: 70,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 68,
EndPos: 70,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 67,
EndPos: 68,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 70,
EndPos: 71,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 74,
EndPos: 82,
},
Expr: &ast.ExprBinaryConcat{
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 74,
EndPos: 81,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 74,
EndPos: 76,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 74,
EndPos: 76,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 74,
EndPos: 76,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 7,
EndLine: 8,
StartPos: 71,
EndPos: 74,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.ID(46),
Value: []byte("."),
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 77,
EndPos: 78,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 76,
EndPos: 77,
},
},
},
},
Right: &ast.ExprVariable{
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 79,
EndPos: 81,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 79,
EndPos: 81,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 79,
EndPos: 81,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 78,
EndPos: 79,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 81,
EndPos: 82,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 85,
EndPos: 93,
},
Expr: &ast.ExprBinaryDiv{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 85,
EndPos: 92,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 85,
EndPos: 87,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 85,
EndPos: 87,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 85,
EndPos: 87,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 8,
EndLine: 9,
StartPos: 82,
EndPos: 85,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.ID(47),
Value: []byte("/"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 88,
EndPos: 89,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 87,
EndPos: 88,
},
},
},
},
Right: &ast.ExprVariable{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 90,
EndPos: 92,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 90,
EndPos: 92,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 90,
EndPos: 92,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 89,
EndPos: 90,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 92,
EndPos: 93,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 96,
EndPos: 105,
},
Expr: &ast.ExprBinaryEqual{
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 96,
EndPos: 104,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 96,
EndPos: 98,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 96,
EndPos: 98,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 96,
EndPos: 98,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 9,
EndLine: 10,
StartPos: 93,
EndPos: 96,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.T_IS_EQUAL,
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: 117,
},
Expr: &ast.ExprBinaryGreaterOrEqual{
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 108,
EndPos: 116,
},
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.T_IS_GREATER_OR_EQUAL,
Value: []byte(">="),
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 111,
EndPos: 113,
},
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: 114,
EndPos: 116,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 114,
EndPos: 116,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 114,
EndPos: 116,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 113,
EndPos: 114,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 116,
EndPos: 117,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 120,
EndPos: 128,
},
Expr: &ast.ExprBinaryGreater{
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 120,
EndPos: 127,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 120,
EndPos: 122,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 120,
EndPos: 122,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 120,
EndPos: 122,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 11,
EndLine: 12,
StartPos: 117,
EndPos: 120,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.ID(62),
Value: []byte(">"),
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 123,
EndPos: 124,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 122,
EndPos: 123,
},
},
},
},
Right: &ast.ExprVariable{
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 125,
EndPos: 127,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 125,
EndPos: 127,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 125,
EndPos: 127,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 124,
EndPos: 125,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 127,
EndPos: 128,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 131,
EndPos: 141,
},
Expr: &ast.ExprBinaryIdentical{
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 131,
EndPos: 140,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 131,
EndPos: 133,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 131,
EndPos: 133,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 131,
EndPos: 133,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 12,
EndLine: 13,
StartPos: 128,
EndPos: 131,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.T_IS_IDENTICAL,
Value: []byte("==="),
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 134,
EndPos: 137,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 133,
EndPos: 134,
},
},
},
},
Right: &ast.ExprVariable{
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 138,
EndPos: 140,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 138,
EndPos: 140,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 138,
EndPos: 140,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 137,
EndPos: 138,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 140,
EndPos: 141,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 144,
EndPos: 154,
},
Expr: &ast.ExprBinaryLogicalAnd{
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 144,
EndPos: 153,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 144,
EndPos: 146,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 144,
EndPos: 146,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 144,
EndPos: 146,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 13,
EndLine: 14,
StartPos: 141,
EndPos: 144,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.T_LOGICAL_AND,
Value: []byte("and"),
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 147,
EndPos: 150,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 146,
EndPos: 147,
},
},
},
},
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: 166,
},
Expr: &ast.ExprBinaryLogicalOr{
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 157,
EndPos: 165,
},
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_OR,
Value: []byte("or"),
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 160,
EndPos: 162,
},
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: 163,
EndPos: 165,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 163,
EndPos: 165,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 163,
EndPos: 165,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 162,
EndPos: 163,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 165,
EndPos: 166,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 169,
EndPos: 179,
},
Expr: &ast.ExprBinaryLogicalXor{
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 169,
EndPos: 178,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 169,
EndPos: 171,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 169,
EndPos: 171,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 169,
EndPos: 171,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 15,
EndLine: 16,
StartPos: 166,
EndPos: 169,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.T_LOGICAL_XOR,
Value: []byte("xor"),
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 172,
EndPos: 175,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 171,
EndPos: 172,
},
},
},
},
Right: &ast.ExprVariable{
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 176,
EndPos: 178,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 176,
EndPos: 178,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 176,
EndPos: 178,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 175,
EndPos: 176,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 16,
EndLine: 16,
StartPos: 178,
EndPos: 179,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 182,
EndPos: 190,
},
Expr: &ast.ExprBinaryMinus{
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 182,
EndPos: 189,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 182,
EndPos: 184,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 182,
EndPos: 184,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 182,
EndPos: 184,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 16,
EndLine: 17,
StartPos: 179,
EndPos: 182,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.ID(45),
Value: []byte("-"),
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 185,
EndPos: 186,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 184,
EndPos: 185,
},
},
},
},
Right: &ast.ExprVariable{
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 187,
EndPos: 189,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 187,
EndPos: 189,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 187,
EndPos: 189,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 186,
EndPos: 187,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 17,
EndLine: 17,
StartPos: 189,
EndPos: 190,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 193,
EndPos: 201,
},
Expr: &ast.ExprBinaryMod{
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 193,
EndPos: 200,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 193,
EndPos: 195,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 193,
EndPos: 195,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 193,
EndPos: 195,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 17,
EndLine: 18,
StartPos: 190,
EndPos: 193,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.ID(37),
Value: []byte("%"),
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 196,
EndPos: 197,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 195,
EndPos: 196,
},
},
},
},
Right: &ast.ExprVariable{
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 198,
EndPos: 200,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 198,
EndPos: 200,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 198,
EndPos: 200,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 197,
EndPos: 198,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 18,
EndLine: 18,
StartPos: 200,
EndPos: 201,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 19,
EndLine: 19,
StartPos: 204,
EndPos: 212,
},
Expr: &ast.ExprBinaryMul{
Position: &position.Position{
StartLine: 19,
EndLine: 19,
StartPos: 204,
EndPos: 211,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 19,
EndLine: 19,
StartPos: 204,
EndPos: 206,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 19,
EndLine: 19,
StartPos: 204,
EndPos: 206,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 19,
EndLine: 19,
StartPos: 204,
EndPos: 206,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 18,
EndLine: 19,
StartPos: 201,
EndPos: 204,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.ID(42),
Value: []byte("*"),
Position: &position.Position{
StartLine: 19,
EndLine: 19,
StartPos: 207,
EndPos: 208,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 19,
EndLine: 19,
StartPos: 206,
EndPos: 207,
},
},
},
},
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: 224,
},
Expr: &ast.ExprBinaryNotEqual{
Position: &position.Position{
StartLine: 20,
EndLine: 20,
StartPos: 215,
EndPos: 223,
},
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_EQUAL,
Value: []byte("!="),
Position: &position.Position{
StartLine: 20,
EndLine: 20,
StartPos: 218,
EndPos: 220,
},
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: 221,
EndPos: 223,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 20,
EndLine: 20,
StartPos: 221,
EndPos: 223,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 20,
EndLine: 20,
StartPos: 221,
EndPos: 223,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 20,
EndLine: 20,
StartPos: 220,
EndPos: 221,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 20,
EndLine: 20,
StartPos: 223,
EndPos: 224,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 21,
EndLine: 21,
StartPos: 227,
EndPos: 237,
},
Expr: &ast.ExprBinaryNotIdentical{
Position: &position.Position{
StartLine: 21,
EndLine: 21,
StartPos: 227,
EndPos: 236,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 21,
EndLine: 21,
StartPos: 227,
EndPos: 229,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 21,
EndLine: 21,
StartPos: 227,
EndPos: 229,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 21,
EndLine: 21,
StartPos: 227,
EndPos: 229,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 20,
EndLine: 21,
StartPos: 224,
EndPos: 227,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.T_IS_NOT_IDENTICAL,
Value: []byte("!=="),
Position: &position.Position{
StartLine: 21,
EndLine: 21,
StartPos: 230,
EndPos: 233,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 21,
EndLine: 21,
StartPos: 229,
EndPos: 230,
},
},
},
},
Right: &ast.ExprVariable{
Position: &position.Position{
StartLine: 21,
EndLine: 21,
StartPos: 234,
EndPos: 236,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 21,
EndLine: 21,
StartPos: 234,
EndPos: 236,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 21,
EndLine: 21,
StartPos: 234,
EndPos: 236,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 21,
EndLine: 21,
StartPos: 233,
EndPos: 234,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 21,
EndLine: 21,
StartPos: 236,
EndPos: 237,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 22,
EndLine: 22,
StartPos: 240,
EndPos: 248,
},
Expr: &ast.ExprBinaryPlus{
Position: &position.Position{
StartLine: 22,
EndLine: 22,
StartPos: 240,
EndPos: 247,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 22,
EndLine: 22,
StartPos: 240,
EndPos: 242,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 22,
EndLine: 22,
StartPos: 240,
EndPos: 242,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 22,
EndLine: 22,
StartPos: 240,
EndPos: 242,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 21,
EndLine: 22,
StartPos: 237,
EndPos: 240,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.ID(43),
Value: []byte("+"),
Position: &position.Position{
StartLine: 22,
EndLine: 22,
StartPos: 243,
EndPos: 244,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 22,
EndLine: 22,
StartPos: 242,
EndPos: 243,
},
},
},
},
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.ExprBinaryPow{
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_POW,
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.ExprBinaryShiftLeft{
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_SL,
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.ExprBinaryShiftRight{
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_SR,
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: 296,
},
Expr: &ast.ExprBinarySmallerOrEqual{
Position: &position.Position{
StartLine: 26,
EndLine: 26,
StartPos: 287,
EndPos: 295,
},
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.T_IS_SMALLER_OR_EQUAL,
Value: []byte("<="),
Position: &position.Position{
StartLine: 26,
EndLine: 26,
StartPos: 290,
EndPos: 292,
},
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: 293,
EndPos: 295,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 26,
EndLine: 26,
StartPos: 293,
EndPos: 295,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 26,
EndLine: 26,
StartPos: 293,
EndPos: 295,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 26,
EndLine: 26,
StartPos: 292,
EndPos: 293,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 26,
EndLine: 26,
StartPos: 295,
EndPos: 296,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 27,
EndLine: 27,
StartPos: 299,
EndPos: 307,
},
Expr: &ast.ExprBinarySmaller{
Position: &position.Position{
StartLine: 27,
EndLine: 27,
StartPos: 299,
EndPos: 306,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 27,
EndLine: 27,
StartPos: 299,
EndPos: 301,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 27,
EndLine: 27,
StartPos: 299,
EndPos: 301,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 27,
EndLine: 27,
StartPos: 299,
EndPos: 301,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 26,
EndLine: 27,
StartPos: 296,
EndPos: 299,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.ID(60),
Value: []byte("<"),
Position: &position.Position{
StartLine: 27,
EndLine: 27,
StartPos: 302,
EndPos: 303,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 27,
EndLine: 27,
StartPos: 301,
EndPos: 302,
},
},
},
},
Right: &ast.ExprVariable{
Position: &position.Position{
StartLine: 27,
EndLine: 27,
StartPos: 304,
EndPos: 306,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 27,
EndLine: 27,
StartPos: 304,
EndPos: 306,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 27,
EndLine: 27,
StartPos: 304,
EndPos: 306,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 27,
EndLine: 27,
StartPos: 303,
EndPos: 304,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 27,
EndLine: 27,
StartPos: 306,
EndPos: 307,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 28,
EndLine: 28,
StartPos: 310,
EndPos: 320,
},
Expr: &ast.ExprBinarySpaceship{
Position: &position.Position{
StartLine: 28,
EndLine: 28,
StartPos: 310,
EndPos: 319,
},
Left: &ast.ExprVariable{
Position: &position.Position{
StartLine: 28,
EndLine: 28,
StartPos: 310,
EndPos: 312,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 28,
EndLine: 28,
StartPos: 310,
EndPos: 312,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$a"),
Position: &position.Position{
StartLine: 28,
EndLine: 28,
StartPos: 310,
EndPos: 312,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 27,
EndLine: 28,
StartPos: 307,
EndPos: 310,
},
},
},
},
Value: []byte("$a"),
},
},
OpTkn: &token.Token{
ID: token.T_SPACESHIP,
Value: []byte("<=>"),
Position: &position.Position{
StartLine: 28,
EndLine: 28,
StartPos: 313,
EndPos: 316,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 28,
EndLine: 28,
StartPos: 312,
EndPos: 313,
},
},
},
},
Right: &ast.ExprVariable{
Position: &position.Position{
StartLine: 28,
EndLine: 28,
StartPos: 317,
EndPos: 319,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 28,
EndLine: 28,
StartPos: 317,
EndPos: 319,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$b"),
Position: &position.Position{
StartLine: 28,
EndLine: 28,
StartPos: 317,
EndPos: 319,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte(" "),
Position: &position.Position{
StartLine: 28,
EndLine: 28,
StartPos: 316,
EndPos: 317,
},
},
},
},
Value: []byte("$b"),
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 28,
EndLine: 28,
StartPos: 319,
EndPos: 320,
},
},
},
},
EndTkn: &token.Token{},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
// expr cast
func TestStrings(t *testing.T) {
src := `<?
"test";
"\$test";
"
test
";
'$test';
'
$test
';
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 10,
StartPos: 5,
EndPos: 70,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 12,
},
Expr: &ast.ScalarString{
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 11,
},
StringTkn: &token.Token{
ID: token.T_CONSTANT_ENCAPSED_STRING,
Value: []byte("\"test\""),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 11,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
Value: []byte("\"test\""),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 11,
EndPos: 12,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 15,
EndPos: 24,
},
Expr: &ast.ScalarString{
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 15,
EndPos: 23,
},
StringTkn: &token.Token{
ID: token.T_CONSTANT_ENCAPSED_STRING,
Value: []byte("\"\\$test\""),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 15,
EndPos: 23,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 12,
EndPos: 15,
},
},
},
},
Value: []byte("\"\\$test\""),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 23,
EndPos: 24,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 4,
EndLine: 6,
StartPos: 27,
EndPos: 41,
},
Expr: &ast.ScalarString{
Position: &position.Position{
StartLine: 4,
EndLine: 6,
StartPos: 27,
EndPos: 40,
},
StringTkn: &token.Token{
ID: token.T_CONSTANT_ENCAPSED_STRING,
Value: []byte("\"\n\t\t\ttest\n\t\t\""),
Position: &position.Position{
StartLine: 4,
EndLine: 6,
StartPos: 27,
EndPos: 40,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 3,
EndLine: 4,
StartPos: 24,
EndPos: 27,
},
},
},
},
Value: []byte("\"\n\t\t\ttest\n\t\t\""),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 40,
EndPos: 41,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 44,
EndPos: 52,
},
Expr: &ast.ScalarString{
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 44,
EndPos: 51,
},
StringTkn: &token.Token{
ID: token.T_CONSTANT_ENCAPSED_STRING,
Value: []byte("'$test'"),
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 44,
EndPos: 51,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 6,
EndLine: 7,
StartPos: 41,
EndPos: 44,
},
},
},
},
Value: []byte("'$test'"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 51,
EndPos: 52,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 8,
EndLine: 10,
StartPos: 55,
EndPos: 70,
},
Expr: &ast.ScalarString{
Position: &position.Position{
StartLine: 8,
EndLine: 10,
StartPos: 55,
EndPos: 69,
},
StringTkn: &token.Token{
ID: token.T_CONSTANT_ENCAPSED_STRING,
Value: []byte("'\n\t\t\t$test\n\t\t'"),
Position: &position.Position{
StartLine: 8,
EndLine: 10,
StartPos: 55,
EndPos: 69,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 7,
EndLine: 8,
StartPos: 52,
EndPos: 55,
},
},
},
},
Value: []byte("'\n\t\t\t$test\n\t\t'"),
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 69,
EndPos: 70,
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t"),
Position: &position.Position{
StartLine: 10,
EndLine: 11,
StartPos: 70,
EndPos: 72,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestHeredoc(t *testing.T) {
src := `<?
<<<CAD
CAD;
<<<CAD
hello
CAD;
<<<"CAD"
hello
CAD;
<<<"CAD"
hello $world
CAD;
<<<'CAD'
hello $world
CAD;
`
expected := &ast.Root{
Position: &position.Position{
StartLine: 2,
EndLine: 15,
StartPos: 5,
EndPos: 120,
},
Stmts: []ast.Vertex{
&ast.StmtExpression{
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 5,
EndPos: 16,
},
Expr: &ast.ScalarHeredoc{
Position: &position.Position{
StartLine: 2,
EndLine: 3,
StartPos: 5,
EndPos: 15,
},
OpenHeredocTkn: &token.Token{
ID: token.T_START_HEREDOC,
Value: []byte("<<<CAD\n"),
Position: &position.Position{
StartLine: 2,
EndLine: 2,
StartPos: 5,
EndPos: 12,
},
FreeFloating: []*token.Token{
{
ID: token.T_OPEN_TAG,
Value: []byte("<?"),
Position: &position.Position{
StartLine: 1,
EndLine: 1,
StartPos: 0,
EndPos: 2,
},
},
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 1,
EndLine: 2,
StartPos: 2,
EndPos: 5,
},
},
},
},
CloseHeredocTkn: &token.Token{
ID: token.T_END_HEREDOC,
Value: []byte("AD"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 13,
EndPos: 15,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 3,
EndLine: 3,
StartPos: 15,
EndPos: 16,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 4,
EndLine: 6,
StartPos: 19,
EndPos: 37,
},
Expr: &ast.ScalarHeredoc{
Position: &position.Position{
StartLine: 4,
EndLine: 6,
StartPos: 19,
EndPos: 36,
},
OpenHeredocTkn: &token.Token{
ID: token.T_START_HEREDOC,
Value: []byte("<<<CAD\n"),
Position: &position.Position{
StartLine: 4,
EndLine: 4,
StartPos: 19,
EndPos: 26,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 3,
EndLine: 4,
StartPos: 16,
EndPos: 19,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 26,
EndPos: 33,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("\thello\n"),
Position: &position.Position{
StartLine: 5,
EndLine: 5,
StartPos: 26,
EndPos: 33,
},
},
Value: []byte("\thello\n"),
},
},
CloseHeredocTkn: &token.Token{
ID: token.T_END_HEREDOC,
Value: []byte("CAD"),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 33,
EndPos: 36,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 6,
EndLine: 6,
StartPos: 36,
EndPos: 37,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 7,
EndLine: 9,
StartPos: 40,
EndPos: 60,
},
Expr: &ast.ScalarHeredoc{
Position: &position.Position{
StartLine: 7,
EndLine: 9,
StartPos: 40,
EndPos: 59,
},
OpenHeredocTkn: &token.Token{
ID: token.T_START_HEREDOC,
Value: []byte("<<<\"CAD\"\n"),
Position: &position.Position{
StartLine: 7,
EndLine: 7,
StartPos: 40,
EndPos: 49,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 6,
EndLine: 7,
StartPos: 37,
EndPos: 40,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 49,
EndPos: 56,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("\thello\n"),
Position: &position.Position{
StartLine: 8,
EndLine: 8,
StartPos: 49,
EndPos: 56,
},
},
Value: []byte("\thello\n"),
},
},
CloseHeredocTkn: &token.Token{
ID: token.T_END_HEREDOC,
Value: []byte("CAD"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 56,
EndPos: 59,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 9,
EndLine: 9,
StartPos: 59,
EndPos: 60,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 10,
EndLine: 12,
StartPos: 63,
EndPos: 90,
},
Expr: &ast.ScalarHeredoc{
Position: &position.Position{
StartLine: 10,
EndLine: 12,
StartPos: 63,
EndPos: 89,
},
OpenHeredocTkn: &token.Token{
ID: token.T_START_HEREDOC,
Value: []byte("<<<\"CAD\"\n"),
Position: &position.Position{
StartLine: 10,
EndLine: 10,
StartPos: 63,
EndPos: 72,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 9,
EndLine: 10,
StartPos: 60,
EndPos: 63,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 72,
EndPos: 79,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("\thello "),
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 72,
EndPos: 79,
},
},
Value: []byte("\thello "),
},
&ast.ExprVariable{
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 79,
EndPos: 85,
},
Name: &ast.Identifier{
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 79,
EndPos: 85,
},
IdentifierTkn: &token.Token{
ID: token.T_VARIABLE,
Value: []byte("$world"),
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 79,
EndPos: 85,
},
},
Value: []byte("$world"),
},
},
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 85,
EndPos: 86,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("\n"),
Position: &position.Position{
StartLine: 11,
EndLine: 11,
StartPos: 85,
EndPos: 86,
},
},
Value: []byte("\n"),
},
},
CloseHeredocTkn: &token.Token{
ID: token.T_END_HEREDOC,
Value: []byte("CAD"),
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 86,
EndPos: 89,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 12,
EndLine: 12,
StartPos: 89,
EndPos: 90,
},
},
},
&ast.StmtExpression{
Position: &position.Position{
StartLine: 13,
EndLine: 15,
StartPos: 93,
EndPos: 120,
},
Expr: &ast.ScalarHeredoc{
Position: &position.Position{
StartLine: 13,
EndLine: 15,
StartPos: 93,
EndPos: 119,
},
OpenHeredocTkn: &token.Token{
ID: token.T_START_HEREDOC,
Value: []byte("<<<'CAD'\n"),
Position: &position.Position{
StartLine: 13,
EndLine: 13,
StartPos: 93,
EndPos: 102,
},
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t\t"),
Position: &position.Position{
StartLine: 12,
EndLine: 13,
StartPos: 90,
EndPos: 93,
},
},
},
},
Parts: []ast.Vertex{
&ast.ScalarEncapsedStringPart{
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 102,
EndPos: 116,
},
EncapsedStrTkn: &token.Token{
ID: token.T_ENCAPSED_AND_WHITESPACE,
Value: []byte("\thello $world\n"),
Position: &position.Position{
StartLine: 14,
EndLine: 14,
StartPos: 102,
EndPos: 116,
},
},
Value: []byte("\thello $world\n"),
},
},
CloseHeredocTkn: &token.Token{
ID: token.T_END_HEREDOC,
Value: []byte("CAD"),
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 116,
EndPos: 119,
},
},
},
SemiColonTkn: &token.Token{
ID: token.ID(59),
Value: []byte(";"),
Position: &position.Position{
StartLine: 15,
EndLine: 15,
StartPos: 119,
EndPos: 120,
},
},
},
},
EndTkn: &token.Token{
FreeFloating: []*token.Token{
{
ID: token.T_WHITESPACE,
Value: []byte("\n\t"),
Position: &position.Position{
StartLine: 15,
EndLine: 16,
StartPos: 120,
EndPos: 122,
},
},
},
},
}
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
actual := php8parser.GetRootNode()
assert.DeepEqual(t, expected, actual)
}
func TestControlCharsErrors(t *testing.T) {
src := "<?php \004 echo $b; \"$a[\005test]\";"
expected := []*errors.Error{
{
Msg: "WARNING: Unexpected character in input: '\004' (ASCII=4)",
Pos: &position.Position{StartLine: 1, EndLine: 1, StartPos: 6, EndPos: 7},
},
{
Msg: "WARNING: Unexpected character in input: '\005' (ASCII=5)",
Pos: &position.Position{StartLine: 1, EndLine: 1, StartPos: 21, EndPos: 22},
},
}
var parserErrors []*errors.Error
config := conf.Config{
Version: &version.Version{
Major: 7,
Minor: 4,
},
ErrorHandlerFunc: func(e *errors.Error) {
parserErrors = append(parserErrors, e)
},
}
lexer := php8.NewLexer([]byte(src), config)
php8parser := php8.NewParser(lexer, config)
php8parser.Parse()
assert.DeepEqual(t, expected, parserErrors)
}