php8.1: added first class callable syntax (#18)

This commit is contained in:
Makhnev Petr 2021-07-31 23:50:59 +03:00 committed by GitHub
parent 13ed0df282
commit 50ed139750
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 2096 additions and 2037 deletions

View File

@ -524,6 +524,7 @@ func (b *Builder) NewMethodCall(
OpenParenthesisTkn: argumentList.OpenParenthesisTkn, OpenParenthesisTkn: argumentList.OpenParenthesisTkn,
Args: argumentList.Arguments, Args: argumentList.Arguments,
SeparatorTkns: argumentList.SeparatorTkns, SeparatorTkns: argumentList.SeparatorTkns,
EllipsisTkn: argumentList.EllipsisTkn,
CloseParenthesisTkn: argumentList.CloseParenthesisTkn, CloseParenthesisTkn: argumentList.CloseParenthesisTkn,
} }
@ -551,6 +552,7 @@ func (b *Builder) NewNullsafeMethodCall(
OpenParenthesisTkn: argumentList.OpenParenthesisTkn, OpenParenthesisTkn: argumentList.OpenParenthesisTkn,
Args: argumentList.Arguments, Args: argumentList.Arguments,
SeparatorTkns: argumentList.SeparatorTkns, SeparatorTkns: argumentList.SeparatorTkns,
EllipsisTkn: argumentList.EllipsisTkn,
CloseParenthesisTkn: argumentList.CloseParenthesisTkn, CloseParenthesisTkn: argumentList.CloseParenthesisTkn,
} }
@ -1528,3 +1530,37 @@ func (b *Builder) NewUse(
return use return use
} }
func (b *Builder) NewArgumentList(
OpenParenthesisTkn *token.Token,
ArgList ast.Vertex,
CommaTkn *token.Token,
EllipsisTkn *token.Token,
CloseParenthesisTkn *token.Token,
) *ArgumentList {
if ArgList == nil {
return &ArgumentList{
Position: b.Pos.NewTokensPosition(OpenParenthesisTkn, CloseParenthesisTkn),
OpenParenthesisTkn: OpenParenthesisTkn,
EllipsisTkn: EllipsisTkn,
CloseParenthesisTkn: CloseParenthesisTkn,
}
}
args, sepTkns := b.SeparatedListItems(ArgList)
if CommaTkn != nil {
sepTkns = append(sepTkns, CommaTkn)
}
return &ArgumentList{
Position: b.Pos.NewTokensPosition(OpenParenthesisTkn, CloseParenthesisTkn),
OpenParenthesisTkn: OpenParenthesisTkn,
Arguments: args,
SeparatorTkns: sepTkns,
CloseParenthesisTkn: CloseParenthesisTkn,
}
}

View File

@ -57,6 +57,7 @@ type ArgumentList struct {
OpenParenthesisTkn *token.Token OpenParenthesisTkn *token.Token
Arguments []ast.Vertex Arguments []ast.Vertex
SeparatorTkns []*token.Token SeparatorTkns []*token.Token
EllipsisTkn *token.Token
CloseParenthesisTkn *token.Token CloseParenthesisTkn *token.Token
} }

File diff suppressed because it is too large Load Diff

View File

@ -1340,48 +1340,22 @@ optional_return_type:
; ;
argument_list: argument_list:
'(' ')' '(' ')' { $$ = yylex.(*Parser).builder.NewArgumentList($1, nil, nil, nil, $2) }
{
$$ = &ArgumentList{
Position: yylex.(*Parser).builder.Pos.NewTokensPosition($1, $2),
OpenParenthesisTkn: $1,
CloseParenthesisTkn: $2,
}
}
| '(' non_empty_argument_list optional_comma ')' | '(' non_empty_argument_list optional_comma ')'
{ { $$ = yylex.(*Parser).builder.NewArgumentList($1, $2, $3, nil, $4) }
argumentList := $2.(*ArgumentList) | '(' T_ELLIPSIS ')' { $$ = yylex.(*Parser).builder.NewArgumentList($1, nil, nil, $2, $3) }
argumentList.Position = yylex.(*Parser).builder.Pos.NewTokensPosition($1, $4)
argumentList.OpenParenthesisTkn = $1
if $3 != nil {
argumentList.SeparatorTkns = append(argumentList.SeparatorTkns, $3)
}
argumentList.CloseParenthesisTkn = $4
$$ = argumentList
}
; ;
non_empty_argument_list: non_empty_argument_list:
argument argument { $$ = yylex.(*Parser).builder.NewSeparatedList($1) }
{
$$ = &ArgumentList{
Arguments: []ast.Vertex{$1},
}
}
| non_empty_argument_list ',' argument | non_empty_argument_list ',' argument
{ { $$ = yylex.(*Parser).builder.AppendToSeparatedList($1, $2, $3) }
$1.(*ArgumentList).SeparatorTkns = append($1.(*ArgumentList).SeparatorTkns, $2)
$1.(*ArgumentList).Arguments = append($1.(*ArgumentList).Arguments, $3)
$$ = $1
}
; ;
argument: argument:
expr { $$ = yylex.(*Parser).builder.NewArgument($1) } expr { $$ = yylex.(*Parser).builder.NewArgument($1) }
| T_ELLIPSIS expr { $$ = yylex.(*Parser).builder.NewVariadicArgument($1, $2) } | T_ELLIPSIS expr { $$ = yylex.(*Parser).builder.NewVariadicArgument($1, $2) }
| identifier_ex ':' expr { $$ = yylex.(*Parser).builder.NewNamedArgument($1, $2, $3) } | identifier_ex ':' expr { $$ = yylex.(*Parser).builder.NewNamedArgument($1, $2, $3) }
; ;
global_var_list: global_var_list:
@ -2694,6 +2668,7 @@ function_call:
OpenParenthesisTkn: $2.(*ArgumentList).OpenParenthesisTkn, OpenParenthesisTkn: $2.(*ArgumentList).OpenParenthesisTkn,
Args: $2.(*ArgumentList).Arguments, Args: $2.(*ArgumentList).Arguments,
SeparatorTkns: $2.(*ArgumentList).SeparatorTkns, SeparatorTkns: $2.(*ArgumentList).SeparatorTkns,
EllipsisTkn: $2.(*ArgumentList).EllipsisTkn,
CloseParenthesisTkn: $2.(*ArgumentList).CloseParenthesisTkn, CloseParenthesisTkn: $2.(*ArgumentList).CloseParenthesisTkn,
} }
} }
@ -2707,6 +2682,7 @@ function_call:
OpenParenthesisTkn: $4.(*ArgumentList).OpenParenthesisTkn, OpenParenthesisTkn: $4.(*ArgumentList).OpenParenthesisTkn,
Args: $4.(*ArgumentList).Arguments, Args: $4.(*ArgumentList).Arguments,
SeparatorTkns: $4.(*ArgumentList).SeparatorTkns, SeparatorTkns: $4.(*ArgumentList).SeparatorTkns,
EllipsisTkn: $4.(*ArgumentList).EllipsisTkn,
CloseParenthesisTkn: $4.(*ArgumentList).CloseParenthesisTkn, CloseParenthesisTkn: $4.(*ArgumentList).CloseParenthesisTkn,
} }
@ -2726,6 +2702,7 @@ function_call:
OpenParenthesisTkn: $2.(*ArgumentList).OpenParenthesisTkn, OpenParenthesisTkn: $2.(*ArgumentList).OpenParenthesisTkn,
Args: $2.(*ArgumentList).Arguments, Args: $2.(*ArgumentList).Arguments,
SeparatorTkns: $2.(*ArgumentList).SeparatorTkns, SeparatorTkns: $2.(*ArgumentList).SeparatorTkns,
EllipsisTkn: $2.(*ArgumentList).EllipsisTkn,
CloseParenthesisTkn: $2.(*ArgumentList).CloseParenthesisTkn, CloseParenthesisTkn: $2.(*ArgumentList).CloseParenthesisTkn,
} }
} }

View File

@ -1506,6 +1506,7 @@ type ExprFunctionCall struct {
OpenParenthesisTkn *token.Token OpenParenthesisTkn *token.Token
Args []Vertex Args []Vertex
SeparatorTkns []*token.Token SeparatorTkns []*token.Token
EllipsisTkn *token.Token
CloseParenthesisTkn *token.Token CloseParenthesisTkn *token.Token
} }
@ -1610,6 +1611,7 @@ type ExprMethodCall struct {
OpenParenthesisTkn *token.Token OpenParenthesisTkn *token.Token
Args []Vertex Args []Vertex
SeparatorTkns []*token.Token SeparatorTkns []*token.Token
EllipsisTkn *token.Token
CloseParenthesisTkn *token.Token CloseParenthesisTkn *token.Token
} }
@ -1632,6 +1634,7 @@ type ExprNullsafeMethodCall struct {
OpenParenthesisTkn *token.Token OpenParenthesisTkn *token.Token
Args []Vertex Args []Vertex
SeparatorTkns []*token.Token SeparatorTkns []*token.Token
EllipsisTkn *token.Token
CloseParenthesisTkn *token.Token CloseParenthesisTkn *token.Token
} }
@ -1830,6 +1833,7 @@ type ExprStaticCall struct {
OpenParenthesisTkn *token.Token OpenParenthesisTkn *token.Token
Args []Vertex Args []Vertex
SeparatorTkns []*token.Token SeparatorTkns []*token.Token
EllipsisTkn *token.Token
CloseParenthesisTkn *token.Token CloseParenthesisTkn *token.Token
} }

View File

@ -1323,6 +1323,7 @@ func (v *Dumper) ExprFunctionCall(n *ast.ExprFunctionCall) {
v.dumpToken("OpenParenthesisTkn", n.OpenParenthesisTkn) v.dumpToken("OpenParenthesisTkn", n.OpenParenthesisTkn)
v.dumpVertexList("Args", n.Args) v.dumpVertexList("Args", n.Args)
v.dumpTokenList("SeparatorTkns", n.SeparatorTkns) v.dumpTokenList("SeparatorTkns", n.SeparatorTkns)
v.dumpToken("EllipsisTkn", n.EllipsisTkn)
v.dumpToken("CloseParenthesisTkn", n.CloseParenthesisTkn) v.dumpToken("CloseParenthesisTkn", n.CloseParenthesisTkn)
v.indent-- v.indent--
@ -1409,6 +1410,7 @@ func (v *Dumper) ExprMethodCall(n *ast.ExprMethodCall) {
v.dumpToken("OpenParenthesisTkn", n.OpenParenthesisTkn) v.dumpToken("OpenParenthesisTkn", n.OpenParenthesisTkn)
v.dumpVertexList("Args", n.Args) v.dumpVertexList("Args", n.Args)
v.dumpTokenList("SeparatorTkns", n.SeparatorTkns) v.dumpTokenList("SeparatorTkns", n.SeparatorTkns)
v.dumpToken("EllipsisTkn", n.EllipsisTkn)
v.dumpToken("CloseParenthesisTkn", n.CloseParenthesisTkn) v.dumpToken("CloseParenthesisTkn", n.CloseParenthesisTkn)
v.indent-- v.indent--
@ -1428,6 +1430,7 @@ func (v *Dumper) ExprNullsafeMethodCall(n *ast.ExprNullsafeMethodCall) {
v.dumpToken("OpenParenthesisTkn", n.OpenParenthesisTkn) v.dumpToken("OpenParenthesisTkn", n.OpenParenthesisTkn)
v.dumpVertexList("Args", n.Args) v.dumpVertexList("Args", n.Args)
v.dumpTokenList("SeparatorTkns", n.SeparatorTkns) v.dumpTokenList("SeparatorTkns", n.SeparatorTkns)
v.dumpToken("EllipsisTkn", n.EllipsisTkn)
v.dumpToken("CloseParenthesisTkn", n.CloseParenthesisTkn) v.dumpToken("CloseParenthesisTkn", n.CloseParenthesisTkn)
v.indent-- v.indent--
@ -1591,6 +1594,7 @@ func (v *Dumper) ExprStaticCall(n *ast.ExprStaticCall) {
v.dumpVertexList("Args", n.Args) v.dumpVertexList("Args", n.Args)
v.dumpTokenList("SeparatorTkns", n.SeparatorTkns) v.dumpTokenList("SeparatorTkns", n.SeparatorTkns)
v.dumpToken("CloseParenthesisTkn", n.CloseParenthesisTkn) v.dumpToken("CloseParenthesisTkn", n.CloseParenthesisTkn)
v.dumpToken("EllipsisTkn", n.EllipsisTkn)
v.indent-- v.indent--
v.print(v.indent, "},\n") v.print(v.indent, "},\n")

View File

@ -1364,6 +1364,9 @@ func (f *formatter) ExprFunctionCall(n *ast.ExprFunctionCall) {
if len(n.Args) > 0 { if len(n.Args) > 0 {
n.SeparatorTkns = f.formatList(n.Args, ',') n.SeparatorTkns = f.formatList(n.Args, ',')
} }
if n.EllipsisTkn != nil {
n.EllipsisTkn = f.newToken(token.T_ELLIPSIS, []byte("..."))
}
n.CloseParenthesisTkn = f.newToken(')', []byte(")")) n.CloseParenthesisTkn = f.newToken(')', []byte(")"))
} }
@ -1424,6 +1427,9 @@ func (f *formatter) ExprMethodCall(n *ast.ExprMethodCall) {
if len(n.Args) > 0 { if len(n.Args) > 0 {
n.SeparatorTkns = f.formatList(n.Args, ',') n.SeparatorTkns = f.formatList(n.Args, ',')
} }
if n.EllipsisTkn != nil {
n.EllipsisTkn = f.newToken(token.T_ELLIPSIS, []byte("..."))
}
n.CloseParenthesisTkn = f.newToken(')', []byte(")")) n.CloseParenthesisTkn = f.newToken(')', []byte(")"))
} }
@ -1448,6 +1454,9 @@ func (f *formatter) ExprNullsafeMethodCall(n *ast.ExprNullsafeMethodCall) {
if len(n.Args) > 0 { if len(n.Args) > 0 {
n.SeparatorTkns = f.formatList(n.Args, ',') n.SeparatorTkns = f.formatList(n.Args, ',')
} }
if n.EllipsisTkn != nil {
n.EllipsisTkn = f.newToken(token.T_ELLIPSIS, []byte("..."))
}
n.CloseParenthesisTkn = f.newToken(')', []byte(")")) n.CloseParenthesisTkn = f.newToken(')', []byte(")"))
} }
@ -1569,6 +1578,9 @@ func (f *formatter) ExprStaticCall(n *ast.ExprStaticCall) {
if len(n.Args) > 0 { if len(n.Args) > 0 {
n.SeparatorTkns = f.formatList(n.Args, ',') n.SeparatorTkns = f.formatList(n.Args, ',')
} }
if n.EllipsisTkn != nil {
n.EllipsisTkn = f.newToken(token.T_ELLIPSIS, []byte("..."))
}
n.CloseParenthesisTkn = f.newToken(')', []byte(")")) n.CloseParenthesisTkn = f.newToken(')', []byte(")"))
} }

View File

@ -787,6 +787,7 @@ func (p *printer) ExprFunctionCall(n *ast.ExprFunctionCall) {
p.printNode(n.Function) p.printNode(n.Function)
p.printToken(n.OpenParenthesisTkn, []byte("(")) p.printToken(n.OpenParenthesisTkn, []byte("("))
p.printSeparatedList(n.Args, n.SeparatorTkns, []byte(",")) p.printSeparatedList(n.Args, n.SeparatorTkns, []byte(","))
p.printToken(n.EllipsisTkn, nil)
p.printToken(n.CloseParenthesisTkn, []byte(")")) p.printToken(n.CloseParenthesisTkn, []byte(")"))
} }
@ -828,6 +829,7 @@ func (p *printer) ExprMethodCall(n *ast.ExprMethodCall) {
p.printToken(n.CloseCurlyBracketTkn, nil) p.printToken(n.CloseCurlyBracketTkn, nil)
p.printToken(n.OpenParenthesisTkn, []byte("(")) p.printToken(n.OpenParenthesisTkn, []byte("("))
p.printSeparatedList(n.Args, n.SeparatorTkns, []byte(",")) p.printSeparatedList(n.Args, n.SeparatorTkns, []byte(","))
p.printToken(n.EllipsisTkn, nil)
p.printToken(n.CloseParenthesisTkn, []byte(")")) p.printToken(n.CloseParenthesisTkn, []byte(")"))
} }
@ -839,6 +841,7 @@ func (p *printer) ExprNullsafeMethodCall(n *ast.ExprNullsafeMethodCall) {
p.printToken(n.CloseCurlyBracketTkn, nil) p.printToken(n.CloseCurlyBracketTkn, nil)
p.printToken(n.OpenParenthesisTkn, []byte("(")) p.printToken(n.OpenParenthesisTkn, []byte("("))
p.printSeparatedList(n.Args, n.SeparatorTkns, []byte(",")) p.printSeparatedList(n.Args, n.SeparatorTkns, []byte(","))
p.printToken(n.EllipsisTkn, nil)
p.printToken(n.CloseParenthesisTkn, []byte(")")) p.printToken(n.CloseParenthesisTkn, []byte(")"))
} }
@ -915,6 +918,7 @@ func (p *printer) ExprStaticCall(n *ast.ExprStaticCall) {
p.printToken(n.CloseCurlyBracketTkn, nil) p.printToken(n.CloseCurlyBracketTkn, nil)
p.printToken(n.OpenParenthesisTkn, p.ifNodeList(n.Args, []byte("("))) p.printToken(n.OpenParenthesisTkn, p.ifNodeList(n.Args, []byte("(")))
p.printSeparatedList(n.Args, n.SeparatorTkns, []byte(",")) p.printSeparatedList(n.Args, n.SeparatorTkns, []byte(","))
p.printToken(n.EllipsisTkn, nil)
p.printToken(n.CloseParenthesisTkn, p.ifNodeList(n.Args, []byte(")"))) p.printToken(n.CloseParenthesisTkn, p.ifNodeList(n.Args, []byte(")")))
} }

View File

@ -84,3 +84,23 @@ class Foo {
} }
`) `)
} }
func TestFirstClassCallableSyntaxPHP81(t *testing.T) {
tester.NewParserPrintTestSuite(t).UsePHP8().Run(`<?php
$fn = id(...);
stdClass::doesNotExist(...);
(new stdClass)->doesNotExist(...);
Test::privateMethod(...);
Test::instanceMethod(...);
$fn = (new A)->$name2(...);
false && strlen(...);
$foo?->foo->bar(...);
$foo?->foo($foo->bar(...));
$foo = $closure->__invoke(...);
// #[Attribute(...)] // not working
// class Foo {}
// new Foo(...); // not working
`)
}