php-parser/internal/php8/builder.go

1600 lines
38 KiB
Go

package php8
import (
"bytes"
"git.maride.cc/maride/php-parser/internal/position"
"git.maride.cc/maride/php-parser/pkg/ast"
position2 "git.maride.cc/maride/php-parser/pkg/position"
"git.maride.cc/maride/php-parser/pkg/token"
)
// Builder is responsible for creating nodes inside grammar rules.
// Creating nodes directly in grammar rules is inconvenient, since
// there is no autocompletion and you cannot put breakpoints inside.
type Builder struct {
Pos *position.Builder
Parser *Parser
}
// NewBuilder creates a new Builder.
func NewBuilder(pos *position.Builder, parser *Parser) *Builder {
return &Builder{
Pos: pos,
Parser: parser,
}
}
// NewEmptySeparatedList creates a new empty list.
// Used for places where a delimited list is used.
func (b *Builder) NewEmptySeparatedList() *ParserSeparatedList {
return &ParserSeparatedList{}
}
// NewSeparatedList creates a new single-element list.
// Used for places where a delimited list is used.
func (b *Builder) NewSeparatedList(node ast.Vertex) *ParserSeparatedList {
return &ParserSeparatedList{Items: []ast.Vertex{node}}
}
// NewSeparatedListWithTwoElements creates a new two-element list.
// Used for places where a delimited list is used.
func (b *Builder) NewSeparatedListWithTwoElements(node1 ast.Vertex, tkn *token.Token, node2 ast.Vertex) *ParserSeparatedList {
return &ParserSeparatedList{
Items: []ast.Vertex{node1, node2},
SeparatorTkns: []*token.Token{tkn},
}
}
func (b *Builder) NewNonEmptySeparatedList(nodes []ast.Vertex, tkns []*token.Token) *ParserSeparatedList {
return &ParserSeparatedList{
Items: nodes,
SeparatorTkns: tkns,
}
}
// AppendToSeparatedList inserts a new node and/or token into the list.
func (b *Builder) AppendToSeparatedList(list ast.Vertex, tkn *token.Token, node ast.Vertex) *ParserSeparatedList {
sepList := list.(*ParserSeparatedList)
if node != nil {
sepList.Items = append(sepList.Items, node)
}
if tkn != nil {
sepList.SeparatorTkns = append(sepList.SeparatorTkns, tkn)
}
return sepList
}
func (b *Builder) SeparatedListItems(list ast.Vertex) (items []ast.Vertex, sepTkns []*token.Token) {
if list == nil {
return nil, nil
}
paramsList, ok := list.(*ParserSeparatedList)
if !ok {
return nil, nil
}
return paramsList.Items, paramsList.SeparatorTkns
}
// namespace\Foo
func (b *Builder) parseNameRelativeToken(t *token.Token) *ast.NameRelative {
n := &ast.NameRelative{
Position: b.Pos.NewTokenPosition(t),
}
s := t.Position.StartPos
v := t.Value
// namespace token
p1 := b.Parser.Lexer.positionPool.Get()
p1.StartLine = t.Position.StartLine
p1.EndLine = t.Position.EndLine
p1.StartPos = s
p1.EndPos = s + 9
n.NsTkn = &token.Token{
ID: token.T_NAMESPACE,
Value: v[:9],
Position: p1,
FreeFloating: t.FreeFloating,
}
s = s + 9
v = v[9:]
// ns separator token
p1 = b.Parser.Lexer.positionPool.Get()
p1.StartLine = t.Position.StartLine
p1.EndLine = t.Position.EndLine
p1.StartPos = s
p1.EndPos = s + 1
n.NsSeparatorTkn = &token.Token{
ID: token.T_NS_SEPARATOR,
Value: v[:1],
Position: p1,
}
s = s + 1
v = v[1:]
// parts
for {
i := bytes.Index(v, []byte("\\"))
if i < 0 {
break
}
p1 = b.Parser.Lexer.positionPool.Get()
p1.StartLine = t.Position.StartLine
p1.EndLine = t.Position.EndLine
p1.StartPos = s
p1.EndPos = s + i
p2 := b.Parser.Lexer.positionPool.Get()
*p2 = *p1
n.Parts = append(n.Parts, &ast.NamePart{
Position: p1,
StringTkn: &token.Token{
ID: token.T_STRING,
Value: v[:i],
Position: p2,
},
Value: v[:i],
})
t.FreeFloating = nil
s = s + i
v = v[i:]
p1 = b.Parser.Lexer.positionPool.Get()
p1.StartLine = t.Position.StartLine
p1.EndLine = t.Position.EndLine
p1.StartPos = s
p1.EndPos = s + 1
n.SeparatorTkns = append(n.SeparatorTkns, &token.Token{
ID: token.T_NS_SEPARATOR,
Value: v[:1],
Position: p1,
})
s = s + 1
v = v[1:]
}
// last part
p1 = b.Parser.Lexer.positionPool.Get()
p1.StartLine = t.Position.StartLine
p1.EndLine = t.Position.EndLine
p1.StartPos = s
p1.EndPos = s + len(v)
p2 := b.Parser.Lexer.positionPool.Get()
*p2 = *p1
n.Parts = append(n.Parts, &ast.NamePart{
Position: p1,
StringTkn: &token.Token{
ID: token.T_STRING,
Value: v,
Position: p2,
},
Value: v,
})
return n
}
// \Foo\Boo
func (b *Builder) parseNameFullyQualifiedToken(t *token.Token) *ast.NameFullyQualified {
n := &ast.NameFullyQualified{
Position: b.Pos.NewTokenPosition(t),
}
s := t.Position.StartPos
v := t.Value
// ns separator token
p1 := b.Parser.Lexer.positionPool.Get()
p1.StartLine = t.Position.StartLine
p1.EndLine = t.Position.EndLine
p1.StartPos = s
p1.EndPos = s + 1
n.NsSeparatorTkn = &token.Token{
ID: token.T_NS_SEPARATOR,
Value: v[:1],
Position: p1,
FreeFloating: t.FreeFloating,
}
s = s + 1
v = v[1:]
// parts
for {
i := bytes.Index(v, []byte("\\"))
if i < 0 {
break
}
p1 = b.Parser.Lexer.positionPool.Get()
p1.StartLine = t.Position.StartLine
p1.EndLine = t.Position.EndLine
p1.StartPos = s
p1.EndPos = s + i
p2 := b.Parser.Lexer.positionPool.Get()
*p2 = *p1
n.Parts = append(n.Parts, &ast.NamePart{
Position: p1,
StringTkn: &token.Token{
ID: token.T_STRING,
Value: v[:i],
Position: p2,
},
Value: v[:i],
})
t.FreeFloating = nil
s = s + i
v = v[i:]
p1 = b.Parser.Lexer.positionPool.Get()
p1.StartLine = t.Position.StartLine
p1.EndLine = t.Position.EndLine
p1.StartPos = s
p1.EndPos = s + 1
n.SeparatorTkns = append(n.SeparatorTkns, &token.Token{
ID: token.T_NS_SEPARATOR,
Value: v[:1],
Position: p1,
})
s = s + 1
v = v[1:]
}
// last part
p1 = b.Parser.Lexer.positionPool.Get()
p1.StartLine = t.Position.StartLine
p1.EndLine = t.Position.EndLine
p1.StartPos = s
p1.EndPos = s + len(v)
p2 := b.Parser.Lexer.positionPool.Get()
*p2 = *p1
n.Parts = append(n.Parts, &ast.NamePart{
Position: p1,
StringTkn: &token.Token{
ID: token.T_STRING,
Value: v,
Position: p2,
},
Value: v,
})
return n
}
// Foo\Boo
func (b *Builder) parseNameToken(t *token.Token) *ast.NameRelative {
n := &ast.NameRelative{
Position: b.Pos.NewTokenPosition(t),
}
s := t.Position.StartPos
sc := t.Position.StartCol
v := t.Value
if bytes.HasPrefix(bytes.ToLower(v), []byte("namespace")) {
p1 := b.Parser.Lexer.positionPool.Get()
p1.StartLine = t.Position.StartLine
p1.EndLine = t.Position.EndLine
p1.StartPos = s
p1.EndPos = s + 9
p1.StartCol = sc
p1.EndCol = sc + 9
n.NsTkn = &token.Token{
ID: token.T_NAMESPACE,
Value: v[:9],
Position: p1,
}
s = s + 9
sc = sc + 9
v = v[9:]
}
if bytes.HasPrefix(bytes.ToLower(v), []byte("\\")) {
p1 := b.Parser.Lexer.positionPool.Get()
p1.StartLine = t.Position.StartLine
p1.EndLine = t.Position.EndLine
p1.StartPos = s
p1.EndPos = s + 1
p1.StartCol = sc
p1.EndCol = sc + 1
n.NsSeparatorTkn = &token.Token{
ID: token.T_NS_SEPARATOR,
Value: v[:1],
Position: p1,
}
s = s + 1
sc = sc + 1
v = v[1:]
}
for {
i := bytes.Index(v, []byte("\\"))
if i < 0 {
break
}
p1 := b.Parser.Lexer.positionPool.Get()
p1.StartLine = t.Position.StartLine
p1.EndLine = t.Position.EndLine
p1.StartPos = s
p1.EndPos = s + i
p1.StartCol = sc
p1.EndCol = sc + i
p2 := b.Parser.Lexer.positionPool.Get()
*p2 = *p1
n.Parts = append(n.Parts, &ast.NamePart{
Position: p1,
StringTkn: &token.Token{
ID: token.T_STRING,
Value: v[:i],
Position: p2,
FreeFloating: t.FreeFloating,
},
Value: v[:i],
})
t.FreeFloating = nil
s = s + i
sc = sc + i
v = v[i:]
p1 = b.Parser.Lexer.positionPool.Get()
p1.StartLine = t.Position.StartLine
p1.EndLine = t.Position.EndLine
p1.StartPos = s
p1.EndPos = s + 1
p1.StartCol = sc
p1.EndCol = sc + 1
n.SeparatorTkns = append(n.SeparatorTkns, &token.Token{
ID: token.T_NS_SEPARATOR,
Value: v[:1],
Position: p1,
})
s = s + 1
sc = sc + 1
v = v[1:]
}
p1 := b.Parser.Lexer.positionPool.Get()
p1.StartLine = t.Position.StartLine
p1.EndLine = t.Position.EndLine
p1.StartPos = s
p1.EndPos = s + len(v)
p1.StartCol = sc
p1.EndCol = sc + len(v)
p2 := b.Parser.Lexer.positionPool.Get()
*p2 = *p1
n.Parts = append(n.Parts, &ast.NamePart{
Position: p1,
StringTkn: &token.Token{
ID: token.T_STRING,
Value: v,
Position: p2,
FreeFloating: t.FreeFloating,
},
Value: v,
})
return n
}
func (b *Builder) NewScalarMagicConstant(
MagicConstantTkn *token.Token,
) *ast.ScalarMagicConstant {
return &ast.ScalarMagicConstant{
Position: b.Pos.NewTokenPosition(MagicConstantTkn),
MagicConstTkn: MagicConstantTkn,
Value: MagicConstantTkn.Value,
}
}
func (b *Builder) NewBracket(
OpenParenthesisTkn *token.Token,
Expr ast.Vertex,
CloseParenthesisTkn *token.Token,
) *ast.ExprBrackets {
return &ast.ExprBrackets{
Position: b.Pos.NewTokensPosition(OpenParenthesisTkn, CloseParenthesisTkn),
OpenParenthesisTkn: OpenParenthesisTkn,
Expr: Expr,
CloseParenthesisTkn: CloseParenthesisTkn,
}
}
func (b *Builder) NewExpressionStmt(
Expr ast.Vertex,
SemiColonTkn *token.Token,
) ast.Vertex {
if throwExpr, ok := Expr.(*ast.ExprThrow); ok {
// For backwards-compatibility reasons, convert throw in statement position into
// StmtThrow rather than StmtExpression(ExprThrow).
return &ast.StmtThrow{
Position: b.Pos.NewTokensPosition(throwExpr.ThrowTkn, SemiColonTkn),
ThrowTkn: throwExpr.ThrowTkn,
Expr: throwExpr.Expr,
SemiColonTkn: SemiColonTkn,
}
}
return &ast.StmtExpression{
Position: b.Pos.NewNodeTokenPosition(Expr, SemiColonTkn),
Expr: Expr,
SemiColonTkn: SemiColonTkn,
}
}
func (b *Builder) NewIdentifier(
IdentifierTkn *token.Token,
) ast.Vertex {
if IdentifierTkn == nil {
return nil
}
return &ast.Identifier{
Position: b.Pos.NewTokenPosition(IdentifierTkn),
IdentifierTkn: IdentifierTkn,
Value: IdentifierTkn.Value,
}
}
func (b *Builder) NewName(
NameTkn *token.Token,
) *ast.Name {
return &ast.Name{
Position: b.Pos.NewTokenPosition(NameTkn),
Parts: []ast.Vertex{
&ast.NamePart{
Position: b.Pos.NewTokenPosition(NameTkn),
StringTkn: NameTkn,
Value: NameTkn.Value,
},
},
}
}
func (b *Builder) NewNameQualified(
NameTkn *token.Token,
) *ast.Name {
name := b.parseNameToken(NameTkn)
return &ast.Name{
Position: b.Pos.NewTokenPosition(NameTkn),
Parts: name.Parts,
SeparatorTkns: name.SeparatorTkns,
}
}
func (b *Builder) NewNameFullyQualified(
NameTkn *token.Token,
) *ast.NameFullyQualified {
return b.parseNameFullyQualifiedToken(NameTkn)
}
func (b *Builder) NewNameRelative(
NameTkn *token.Token,
) *ast.NameRelative {
return b.parseNameRelativeToken(NameTkn)
}
func (b *Builder) NewNamePart(
NameTkn *token.Token,
) *ast.NamePart {
return &ast.NamePart{
Position: b.Pos.NewTokenPosition(NameTkn),
StringTkn: NameTkn,
Value: NameTkn.Value,
}
}
func (b *Builder) NewConstFetch(
Name ast.Vertex,
) *ast.ExprConstFetch {
return &ast.ExprConstFetch{
Position: b.Pos.NewNodePosition(Name),
Const: Name,
}
}
func (b *Builder) NewMethodCall(
Expr ast.Vertex,
ObjectOperatorTkn *token.Token,
PropertyName ast.Vertex,
ArgList ast.Vertex,
) *ast.ExprMethodCall {
argumentList := ArgList.(*ArgumentList)
methodCall := &ast.ExprMethodCall{
Position: b.Pos.NewNodesPosition(Expr, ArgList),
Var: Expr,
ObjectOperatorTkn: ObjectOperatorTkn,
Method: PropertyName,
OpenParenthesisTkn: argumentList.OpenParenthesisTkn,
Args: argumentList.Arguments,
SeparatorTkns: argumentList.SeparatorTkns,
EllipsisTkn: argumentList.EllipsisTkn,
CloseParenthesisTkn: argumentList.CloseParenthesisTkn,
}
if brackets, ok := PropertyName.(*ParserBrackets); ok {
methodCall.OpenCurlyBracketTkn = brackets.OpenBracketTkn
methodCall.Method = brackets.Child
methodCall.CloseCurlyBracketTkn = brackets.CloseBracketTkn
}
return methodCall
}
func (b *Builder) NewNullsafeMethodCall(
Expr ast.Vertex,
ObjectOperatorTkn *token.Token,
PropertyName ast.Vertex,
ArgList ast.Vertex,
) *ast.ExprNullsafeMethodCall {
argumentList := ArgList.(*ArgumentList)
methodCall := &ast.ExprNullsafeMethodCall{
Position: b.Pos.NewNodesPosition(Expr, ArgList),
Var: Expr,
ObjectOperatorTkn: ObjectOperatorTkn,
Method: PropertyName,
OpenParenthesisTkn: argumentList.OpenParenthesisTkn,
Args: argumentList.Arguments,
SeparatorTkns: argumentList.SeparatorTkns,
EllipsisTkn: argumentList.EllipsisTkn,
CloseParenthesisTkn: argumentList.CloseParenthesisTkn,
}
if brackets, ok := PropertyName.(*ParserBrackets); ok {
methodCall.OpenCurlyBracketTkn = brackets.OpenBracketTkn
methodCall.Method = brackets.Child
methodCall.CloseCurlyBracketTkn = brackets.CloseBracketTkn
}
return methodCall
}
func (b *Builder) NewPropertyFetch(
Expr ast.Vertex,
ObjectOperatorTkn *token.Token,
PropertyName ast.Vertex,
) *ast.ExprPropertyFetch {
propertyFetch := &ast.ExprPropertyFetch{
Position: b.Pos.NewNodesPosition(Expr, PropertyName),
Var: Expr,
ObjectOperatorTkn: ObjectOperatorTkn,
Prop: PropertyName,
}
if brackets, ok := PropertyName.(*ParserBrackets); ok {
propertyFetch.OpenCurlyBracketTkn = brackets.OpenBracketTkn
propertyFetch.Prop = brackets.Child
propertyFetch.CloseCurlyBracketTkn = brackets.CloseBracketTkn
}
return propertyFetch
}
func (b *Builder) NewPropertyFetchFromTokens(
VariableTkn *token.Token,
ObjectOperatorTkn *token.Token,
StringTkn *token.Token,
) *ast.ExprPropertyFetch {
return &ast.ExprPropertyFetch{
Position: b.Pos.NewTokensPosition(VariableTkn, StringTkn),
Var: &ast.ExprVariable{
Position: b.Pos.NewTokenPosition(VariableTkn),
Name: &ast.Identifier{
Position: b.Pos.NewTokenPosition(VariableTkn),
IdentifierTkn: VariableTkn,
Value: VariableTkn.Value,
},
},
ObjectOperatorTkn: ObjectOperatorTkn,
Prop: &ast.Identifier{
Position: b.Pos.NewTokenPosition(StringTkn),
IdentifierTkn: StringTkn,
Value: StringTkn.Value,
},
}
}
func (b *Builder) NewNullsafePropertyFetch(
Expr ast.Vertex,
ObjectOperatorTkn *token.Token,
PropertyName ast.Vertex,
) *ast.ExprNullsafePropertyFetch {
propertyFetch := &ast.ExprNullsafePropertyFetch{
Position: b.Pos.NewNodesPosition(Expr, PropertyName),
Var: Expr,
ObjectOperatorTkn: ObjectOperatorTkn,
Prop: PropertyName,
}
if brackets, ok := PropertyName.(*ParserBrackets); ok {
propertyFetch.OpenCurlyBracketTkn = brackets.OpenBracketTkn
propertyFetch.Prop = brackets.Child
propertyFetch.CloseCurlyBracketTkn = brackets.CloseBracketTkn
}
return propertyFetch
}
func (b *Builder) NewNullsafePropertyFetchFromTokens(
VariableTkn *token.Token,
ObjectOperatorTkn *token.Token,
StringTkn *token.Token,
) *ast.ExprNullsafePropertyFetch {
return &ast.ExprNullsafePropertyFetch{
Position: b.Pos.NewTokensPosition(VariableTkn, StringTkn),
Var: &ast.ExprVariable{
Position: b.Pos.NewTokenPosition(VariableTkn),
Name: &ast.Identifier{
Position: b.Pos.NewTokenPosition(VariableTkn),
IdentifierTkn: VariableTkn,
Value: VariableTkn.Value,
},
},
ObjectOperatorTkn: ObjectOperatorTkn,
Prop: &ast.Identifier{
Position: b.Pos.NewTokenPosition(StringTkn),
IdentifierTkn: StringTkn,
Value: StringTkn.Value,
},
}
}
func (b *Builder) NewArgument(
Expr ast.Vertex,
) *ast.Argument {
return &ast.Argument{
Position: b.Pos.NewNodePosition(Expr),
Expr: Expr,
}
}
func (b *Builder) NewVariadicArgument(
VariadicTkn *token.Token,
Expr ast.Vertex,
) *ast.Argument {
return &ast.Argument{
Position: b.Pos.NewTokenNodePosition(VariadicTkn, Expr),
VariadicTkn: VariadicTkn,
Expr: Expr,
}
}
func (b *Builder) NewNamedArgument(
Name *token.Token,
ColonTkn *token.Token,
Expr ast.Vertex,
) *ast.Argument {
return &ast.Argument{
Position: b.Pos.NewTokenNodePosition(Name, Expr),
Name: &ast.Identifier{
Position: Name.Position,
IdentifierTkn: Name,
Value: Name.Value,
},
ColonTkn: ColonTkn,
Expr: Expr,
}
}
func (b *Builder) NewMatch(
MatchTkn *token.Token,
OpenParenthesisTkn *token.Token,
Expr ast.Vertex,
CloseParenthesisTkn *token.Token,
OpenCurlyBracketTkn *token.Token,
Cases ast.Vertex,
CloseCurlyBracketTkn *token.Token,
) *ast.ExprMatch {
var arms []ast.Vertex
var sepTkns []*token.Token
if Cases != nil {
cases := Cases.(*ParserSeparatedList)
arms = cases.Items
sepTkns = cases.SeparatorTkns
}
return &ast.ExprMatch{
Position: b.Pos.NewTokensPosition(MatchTkn, CloseCurlyBracketTkn),
MatchTkn: MatchTkn,
OpenParenthesisTkn: OpenParenthesisTkn,
Expr: Expr,
CloseParenthesisTkn: CloseParenthesisTkn,
OpenCurlyBracketTkn: OpenCurlyBracketTkn,
Arms: arms,
SeparatorTkns: sepTkns,
CloseCurlyBracketTkn: CloseCurlyBracketTkn,
}
}
func (b *Builder) NewMatchArm(
DefaultTkn *token.Token,
DefaultCommaTkn *token.Token,
Exprs ast.Vertex,
DoubleArrowTkn *token.Token,
ReturnExpr ast.Vertex,
) *ast.MatchArm {
// Default branch.
if Exprs == nil {
return &ast.MatchArm{
Position: b.Pos.NewTokenNodePosition(DefaultTkn, ReturnExpr),
DefaultTkn: DefaultTkn,
DefaultCommaTkn: DefaultCommaTkn,
DoubleArrowTkn: DoubleArrowTkn,
ReturnExpr: ReturnExpr,
}
}
list := Exprs.(*ParserSeparatedList)
return &ast.MatchArm{
Position: b.Pos.NewNodeListNodePosition(list.Items, ReturnExpr),
DefaultTkn: nil,
Exprs: list.Items,
SeparatorTkns: list.SeparatorTkns,
DoubleArrowTkn: DoubleArrowTkn,
ReturnExpr: ReturnExpr,
}
}
func (b *Builder) NewNameType(
IdentifierTkn *token.Token,
) *ast.Identifier {
return &ast.Identifier{
Position: b.Pos.NewTokenPosition(IdentifierTkn),
IdentifierTkn: IdentifierTkn,
Value: IdentifierTkn.Value,
}
}
func (b *Builder) NewNullableType(
QuestionTkn *token.Token,
Expr ast.Vertex,
) *ast.Nullable {
return &ast.Nullable{
Position: b.Pos.NewTokenNodePosition(QuestionTkn, Expr),
QuestionTkn: QuestionTkn,
Expr: Expr,
}
}
func (b *Builder) NewUnionType(
Types ast.Vertex,
) *ast.Union {
var types []ast.Vertex
var sepTkns []*token.Token
if Types != nil {
cases := Types.(*ParserSeparatedList)
types = cases.Items
sepTkns = cases.SeparatorTkns
}
return &ast.Union{
Position: b.Pos.NewNodeListPosition(types),
Types: types,
SeparatorTkns: sepTkns,
}
}
func (b *Builder) NewIntersectionType(
Types ast.Vertex,
) *ast.Intersection {
var types []ast.Vertex
var sepTkns []*token.Token
if Types != nil {
cases := Types.(*ParserSeparatedList)
types = cases.Items
sepTkns = cases.SeparatorTkns
}
return &ast.Intersection{
Position: b.Pos.NewNodeListPosition(types),
Types: types,
SeparatorTkns: sepTkns,
}
}
func (b *Builder) NewReturnType(
ColonTkn *token.Token,
Type ast.Vertex,
) *ReturnType {
return &ReturnType{
ColonTkn: ColonTkn,
Type: Type,
}
}
func (b *Builder) NewTry(
TryTkn *token.Token,
OpenCurlyBracketTkn *token.Token,
Stmts []ast.Vertex,
CloseCurlyBracketTkn *token.Token,
Catches ast.Vertex,
Finally ast.Vertex,
) *ast.StmtTry {
var catches []ast.Vertex
if Catches != nil {
catchList := Catches.(*ParserSeparatedList)
catches = catchList.Items
}
var pos *position2.Position
if Finally != nil {
pos = b.Pos.NewTokenNodePosition(TryTkn, Finally)
} else {
pos = b.Pos.NewTokenNodeListPosition(TryTkn, catches)
}
return &ast.StmtTry{
Position: pos,
TryTkn: TryTkn,
OpenCurlyBracketTkn: OpenCurlyBracketTkn,
Stmts: Stmts,
CloseCurlyBracketTkn: CloseCurlyBracketTkn,
Catches: catches,
Finally: Finally,
}
}
func (b *Builder) NewCatch(
CatchTkn *token.Token,
OpenParenthesisTkn *token.Token,
CatchNameList ast.Vertex,
Variable *token.Token,
CloseParenthesisTkn *token.Token,
OpenCurlyBracketTkn *token.Token,
Stmts []ast.Vertex,
CloseCurlyBracketTkn *token.Token,
) *ast.StmtCatch {
var types []ast.Vertex
var sepTkns []*token.Token
if CatchNameList != nil {
catchList := CatchNameList.(*ParserSeparatedList)
types = catchList.Items
sepTkns = catchList.SeparatorTkns
}
var variable ast.Vertex
if Variable != nil {
variable = &ast.ExprVariable{
Position: b.Pos.NewTokenPosition(Variable),
Name: &ast.Identifier{
Position: b.Pos.NewTokenPosition(Variable),
IdentifierTkn: Variable,
Value: Variable.Value,
},
}
}
return &ast.StmtCatch{
Position: b.Pos.NewTokensPosition(CatchTkn, CloseCurlyBracketTkn),
CatchTkn: CatchTkn,
OpenParenthesisTkn: OpenParenthesisTkn,
Types: types,
SeparatorTkns: sepTkns,
Var: variable,
CloseParenthesisTkn: CloseParenthesisTkn,
OpenCurlyBracketTkn: OpenCurlyBracketTkn,
Stmts: Stmts,
CloseCurlyBracketTkn: CloseCurlyBracketTkn,
}
}
func (b *Builder) NewThrowStmt(
ThrowTkn *token.Token,
Expr ast.Vertex,
) *ast.StmtThrow {
return &ast.StmtThrow{
Position: b.Pos.NewTokenNodePosition(ThrowTkn, Expr),
ThrowTkn: ThrowTkn,
Expr: Expr,
}
}
func (b *Builder) NewThrowExpr(
ThrowTkn *token.Token,
Expr ast.Vertex,
) *ast.ExprThrow {
return &ast.ExprThrow{
Position: b.Pos.NewTokenNodePosition(ThrowTkn, Expr),
ThrowTkn: ThrowTkn,
Expr: Expr,
}
}
func (b *Builder) NewParameter(
AttrGroups []ast.Vertex,
Modifiers []ast.Vertex,
Type ast.Vertex,
AmpersandTkn *token.Token,
VariadicTkn *token.Token,
VarTkn *token.Token,
EqualTkn *token.Token,
DefaultValue ast.Vertex,
WithDefault bool,
) *ast.Parameter {
var pos *position2.Position
if WithDefault {
if AttrGroups != nil {
pos = b.Pos.NewNodeListNodePosition(AttrGroups, DefaultValue)
} else if Modifiers != nil {
pos = b.Pos.NewNodeListNodePosition(Modifiers, DefaultValue)
} else if Type != nil {
pos = b.Pos.NewNodesPosition(Type, DefaultValue)
} else if AmpersandTkn != nil {
pos = b.Pos.NewTokenNodePosition(AmpersandTkn, DefaultValue)
} else if VariadicTkn != nil {
pos = b.Pos.NewTokenNodePosition(VariadicTkn, DefaultValue)
} else {
pos = b.Pos.NewTokenNodePosition(VarTkn, DefaultValue)
}
} else {
if AttrGroups != nil {
pos = b.Pos.NewNodeListTokenPosition(AttrGroups, VarTkn)
} else if Modifiers != nil {
pos = b.Pos.NewNodeListTokenPosition(Modifiers, VarTkn)
} else if Type != nil {
pos = b.Pos.NewNodeTokenPosition(Type, VarTkn)
} else if AmpersandTkn != nil {
pos = b.Pos.NewTokensPosition(AmpersandTkn, VarTkn)
} else if VariadicTkn != nil {
pos = b.Pos.NewTokensPosition(VariadicTkn, VarTkn)
} else {
pos = b.Pos.NewTokenPosition(VarTkn)
}
}
return &ast.Parameter{
Position: pos,
AttrGroups: AttrGroups,
Modifiers: Modifiers,
Type: Type,
AmpersandTkn: AmpersandTkn,
VariadicTkn: VariadicTkn,
Var: &ast.ExprVariable{
Position: b.Pos.NewTokenPosition(VarTkn),
Name: &ast.Identifier{
Position: b.Pos.NewTokenPosition(VarTkn),
IdentifierTkn: VarTkn,
Value: VarTkn.Value,
},
},
EqualTkn: EqualTkn,
DefaultValue: DefaultValue,
}
}
func (b *Builder) NewAttribute(
Name ast.Vertex,
ArgList ast.Vertex,
) *ast.Attribute {
if ArgList == nil {
return &ast.Attribute{
Position: b.Pos.NewNodePosition(Name),
Name: Name,
}
}
argList := ArgList.(*ArgumentList)
return &ast.Attribute{
Position: b.Pos.NewNodeTokenPosition(Name, argList.CloseParenthesisTkn),
Name: Name,
OpenParenthesisTkn: argList.OpenParenthesisTkn,
Args: argList.Arguments,
SeparatorTkns: argList.SeparatorTkns,
CloseParenthesisTkn: argList.CloseParenthesisTkn,
}
}
func (b *Builder) NewAttributeGroup(
OpenAttributeTkn *token.Token,
AttrsList ast.Vertex,
OptionalCommaTkn *token.Token,
CloseAttributeTkn *token.Token,
) *ast.AttributeGroup {
attrList := AttrsList.(*ParserSeparatedList)
if OptionalCommaTkn != nil {
attrList.SeparatorTkns = append(attrList.SeparatorTkns, OptionalCommaTkn)
}
return &ast.AttributeGroup{
Position: b.Pos.NewTokensPosition(OpenAttributeTkn, CloseAttributeTkn),
OpenAttributeTkn: OpenAttributeTkn,
Attrs: attrList.Items,
SeparatorTkns: attrList.SeparatorTkns,
CloseAttributeTkn: CloseAttributeTkn,
}
}
func (b *Builder) NewClass(
AttrGroups []ast.Vertex,
Modifiers []ast.Vertex,
ClassTkn *token.Token,
Name *token.Token,
ExtendsFrom ast.Vertex,
ImplementsList ast.Vertex,
OpenCurlyBracketTkn *token.Token,
Stmts []ast.Vertex,
CloseCurlyBracketTkn *token.Token,
) *ast.StmtClass {
var pos *position2.Position
if AttrGroups != nil {
pos = b.Pos.NewNodeListTokenPosition(AttrGroups, CloseCurlyBracketTkn)
} else if Modifiers != nil {
pos = b.Pos.NewNodeListTokenPosition(Modifiers, CloseCurlyBracketTkn)
} else {
pos = b.Pos.NewTokensPosition(ClassTkn, CloseCurlyBracketTkn)
}
var name ast.Vertex
if Name != nil {
name = &ast.Identifier{
Position: b.Pos.NewTokenPosition(Name),
IdentifierTkn: Name,
Value: Name.Value,
}
}
class := &ast.StmtClass{
Position: pos,
AttrGroups: AttrGroups,
Modifiers: Modifiers,
ClassTkn: ClassTkn,
Name: name,
OpenCurlyBracketTkn: OpenCurlyBracketTkn,
Stmts: Stmts,
CloseCurlyBracketTkn: CloseCurlyBracketTkn,
}
if ExtendsFrom != nil {
class.ExtendsTkn = ExtendsFrom.(*ast.StmtClass).ExtendsTkn
class.Extends = ExtendsFrom.(*ast.StmtClass).Extends
}
if ImplementsList != nil {
class.ImplementsTkn = ImplementsList.(*ast.StmtClass).ImplementsTkn
class.Implements = ImplementsList.(*ast.StmtClass).Implements
class.ImplementsSeparatorTkns = ImplementsList.(*ast.StmtClass).ImplementsSeparatorTkns
}
return class
}
func (b *Builder) NewAnonClass(
AttrGroups []ast.Vertex,
ClassTkn *token.Token,
ArgList ast.Vertex,
ExtendsFrom ast.Vertex,
ImplementsList ast.Vertex,
OpenCurlyBracketTkn *token.Token,
Stmts []ast.Vertex,
CloseCurlyBracketTkn *token.Token,
) *ast.StmtClass {
class := b.NewClass(
AttrGroups,
nil, // Modifiers
ClassTkn,
nil, // Name
ExtendsFrom,
ImplementsList,
OpenCurlyBracketTkn,
Stmts,
CloseCurlyBracketTkn,
)
if ArgList == nil {
return class
}
argList := ArgList.(*ArgumentList)
class.OpenParenthesisTkn = argList.OpenParenthesisTkn
class.Args = argList.Arguments
class.SeparatorTkns = argList.SeparatorTkns
class.CloseParenthesisTkn = argList.CloseParenthesisTkn
return class
}
func (b *Builder) NewTrait(
AttrGroups []ast.Vertex,
TraitTkn *token.Token,
Name *token.Token,
OpenCurlyBracketTkn *token.Token,
Stmts []ast.Vertex,
CloseCurlyBracketTkn *token.Token,
) *ast.StmtTrait {
return &ast.StmtTrait{
Position: b.Pos.NewOptionalListTokensPosition(AttrGroups, TraitTkn, CloseCurlyBracketTkn),
AttrGroups: AttrGroups,
TraitTkn: TraitTkn,
Name: &ast.Identifier{
Position: b.Pos.NewTokenPosition(Name),
IdentifierTkn: Name,
Value: Name.Value,
},
OpenCurlyBracketTkn: OpenCurlyBracketTkn,
Stmts: Stmts,
CloseCurlyBracketTkn: CloseCurlyBracketTkn,
}
}
func (b *Builder) NewInterface(
AttrGroups []ast.Vertex,
InterfaceTkn *token.Token,
Name *token.Token,
ExtendsFrom ast.Vertex,
OpenCurlyBracketTkn *token.Token,
Stmts []ast.Vertex,
CloseCurlyBracketTkn *token.Token,
) *ast.StmtInterface {
iface := &ast.StmtInterface{
Position: b.Pos.NewOptionalListTokensPosition(AttrGroups, InterfaceTkn, CloseCurlyBracketTkn),
AttrGroups: AttrGroups,
InterfaceTkn: InterfaceTkn,
Name: &ast.Identifier{
Position: b.Pos.NewTokenPosition(Name),
IdentifierTkn: Name,
Value: Name.Value,
},
OpenCurlyBracketTkn: OpenCurlyBracketTkn,
Stmts: Stmts,
CloseCurlyBracketTkn: CloseCurlyBracketTkn,
}
if ExtendsFrom != nil {
iface.ExtendsTkn = ExtendsFrom.(*ast.StmtInterface).ExtendsTkn
iface.Extends = ExtendsFrom.(*ast.StmtInterface).Extends
iface.ExtendsSeparatorTkns = ExtendsFrom.(*ast.StmtInterface).ExtendsSeparatorTkns
}
return iface
}
func (b *Builder) NewEnumType(
ColonTkn *token.Token,
Type ast.Vertex,
) *ReturnType {
return &ReturnType{
ColonTkn: ColonTkn,
Type: Type,
}
}
func (b *Builder) NewEnumExpr(
AssignTkn *token.Token,
Expr ast.Vertex,
) *EnumCaseExpr {
return &EnumCaseExpr{
AssignTkn: AssignTkn,
Expr: Expr,
}
}
func (b *Builder) NewEnum(
AttrGroups []ast.Vertex,
EnumTkn *token.Token,
Name *token.Token,
EnumScalarType ast.Vertex,
ImplementsList ast.Vertex,
OpenCurlyBracketTkn *token.Token,
Stmts []ast.Vertex,
CloseCurlyBracketTkn *token.Token,
) *ast.StmtEnum {
var pos *position2.Position
if AttrGroups != nil {
pos = b.Pos.NewNodeListTokenPosition(AttrGroups, CloseCurlyBracketTkn)
} else {
pos = b.Pos.NewTokensPosition(EnumTkn, CloseCurlyBracketTkn)
}
enum := &ast.StmtEnum{
Position: pos,
AttrGroups: AttrGroups,
EnumTkn: EnumTkn,
Name: b.NewIdentifier(Name),
OpenCurlyBracketTkn: OpenCurlyBracketTkn,
Stmts: Stmts,
CloseCurlyBracketTkn: CloseCurlyBracketTkn,
}
if EnumScalarType != nil {
enumType := EnumScalarType.(*ReturnType)
enum.ColonTkn = enumType.ColonTkn
enum.Type = enumType.Type
}
if ImplementsList != nil {
enum.ImplementsTkn = ImplementsList.(*ast.StmtClass).ImplementsTkn
enum.Implements = ImplementsList.(*ast.StmtClass).Implements
enum.ImplementsSeparatorTkns = ImplementsList.(*ast.StmtClass).ImplementsSeparatorTkns
}
return enum
}
func (b *Builder) NewEnumCase(
AttrGroups []ast.Vertex,
CaseTkn *token.Token,
Name *token.Token,
Expr ast.Vertex,
SemiColonTkn *token.Token,
) *ast.EnumCase {
var equalTkn *token.Token
var expr ast.Vertex
if Expr != nil {
caseExpr := Expr.(*EnumCaseExpr)
equalTkn = caseExpr.AssignTkn
expr = caseExpr.Expr
}
var pos *position2.Position
if AttrGroups != nil {
pos = b.Pos.NewNodeListTokenPosition(AttrGroups, SemiColonTkn)
} else {
pos = b.Pos.NewTokensPosition(CaseTkn, SemiColonTkn)
}
return &ast.EnumCase{
Position: pos,
CaseTkn: CaseTkn,
AttrGroups: AttrGroups,
Name: b.NewIdentifier(Name),
EqualTkn: equalTkn,
Expr: expr,
SemiColonTkn: SemiColonTkn,
}
}
func (b *Builder) NewFunction(
AttrGroups []ast.Vertex,
FunctionTkn *token.Token,
AmpersandTkn *token.Token,
Name *token.Token,
OpenParenthesisTkn *token.Token,
Params ast.Vertex,
CloseParenthesisTkn *token.Token,
RetType ast.Vertex,
OpenCurlyBracketTkn *token.Token,
Stmts []ast.Vertex,
CloseCurlyBracketTkn *token.Token,
) *ast.StmtFunction {
var params []ast.Vertex
var sepTkns []*token.Token
if Params != nil {
paramsList := Params.(*ParserSeparatedList)
params = paramsList.Items
sepTkns = paramsList.SeparatorTkns
}
returnType := RetType.(*ReturnType)
return &ast.StmtFunction{
Position: b.Pos.NewOptionalListTokensPosition(AttrGroups, FunctionTkn, CloseCurlyBracketTkn),
AttrGroups: AttrGroups,
FunctionTkn: FunctionTkn,
AmpersandTkn: AmpersandTkn,
Name: &ast.Identifier{
Position: b.Pos.NewTokenPosition(Name),
IdentifierTkn: Name,
Value: Name.Value,
},
OpenParenthesisTkn: OpenParenthesisTkn,
Params: params,
SeparatorTkns: sepTkns,
CloseParenthesisTkn: CloseParenthesisTkn,
ColonTkn: returnType.ColonTkn,
ReturnType: returnType.Type,
OpenCurlyBracketTkn: OpenCurlyBracketTkn,
Stmts: Stmts,
CloseCurlyBracketTkn: CloseCurlyBracketTkn,
}
}
func (b *Builder) NewPropertyList(
AttrGroups []ast.Vertex,
Modifiers []ast.Vertex,
Type ast.Vertex,
PropsList ast.Vertex,
SemiColonTkn *token.Token,
) *ast.StmtPropertyList {
props, sepTkns := b.SeparatedListItems(PropsList)
var pos *position2.Position
if AttrGroups != nil {
pos = b.Pos.NewNodeListTokenPosition(AttrGroups, SemiColonTkn)
} else {
pos = b.Pos.NewNodeListTokenPosition(Modifiers, SemiColonTkn)
}
return &ast.StmtPropertyList{
Position: pos,
AttrGroups: AttrGroups,
Modifiers: Modifiers,
Type: Type,
Props: props,
SeparatorTkns: sepTkns,
SemiColonTkn: SemiColonTkn,
}
}
func (b *Builder) NewClassConstList(
AttrGroups []ast.Vertex,
Modifiers []ast.Vertex,
ConstTkn *token.Token,
ConstList ast.Vertex,
SemiColonTkn *token.Token,
) *ast.StmtClassConstList {
consts, sepTkns := b.SeparatedListItems(ConstList)
var pos *position2.Position
if AttrGroups != nil {
pos = b.Pos.NewNodeListTokenPosition(AttrGroups, SemiColonTkn)
} else {
pos = b.Pos.NewOptionalListTokensPosition(Modifiers, ConstTkn, SemiColonTkn)
}
return &ast.StmtClassConstList{
Position: pos,
AttrGroups: AttrGroups,
Modifiers: Modifiers,
ConstTkn: ConstTkn,
Consts: consts,
SeparatorTkns: sepTkns,
SemiColonTkn: SemiColonTkn,
}
}
func (b *Builder) NewClassMethod(
AttrGroups []ast.Vertex,
Modifiers []ast.Vertex,
FunctionTkn *token.Token,
AmpersandTkn *token.Token,
Name *token.Token,
OpenParenthesisTkn *token.Token,
Params ast.Vertex,
CloseParenthesisTkn *token.Token,
RetType ast.Vertex,
Stmt ast.Vertex,
) *ast.StmtClassMethod {
params, sepTkns := b.SeparatedListItems(Params)
returnType := RetType.(*ReturnType)
var pos *position2.Position
if AttrGroups != nil {
pos = b.Pos.NewNodeListNodePosition(AttrGroups, Stmt)
} else if Modifiers != nil {
pos = b.Pos.NewNodeListNodePosition(Modifiers, Stmt)
} else {
pos = b.Pos.NewTokenNodePosition(FunctionTkn, Stmt)
}
return &ast.StmtClassMethod{
Position: pos,
AttrGroups: AttrGroups,
Modifiers: Modifiers,
FunctionTkn: FunctionTkn,
AmpersandTkn: AmpersandTkn,
Name: &ast.Identifier{
Position: b.Pos.NewTokenPosition(Name),
IdentifierTkn: Name,
Value: Name.Value,
},
OpenParenthesisTkn: OpenParenthesisTkn,
Params: params,
SeparatorTkns: sepTkns,
CloseParenthesisTkn: CloseParenthesisTkn,
ColonTkn: returnType.ColonTkn,
ReturnType: returnType.Type,
Stmt: Stmt,
}
}
func (b *Builder) NewNamespace(
NsTkn *token.Token,
Name ast.Vertex,
OpenCurlyBracketTkn *token.Token,
Stmts []ast.Vertex,
CloseCurlyBracketTkn *token.Token,
SemiColonTkn *token.Token,
) *ast.StmtNamespace {
var pos *position2.Position
if SemiColonTkn != nil {
pos = b.Pos.NewTokensPosition(NsTkn, SemiColonTkn)
} else {
pos = b.Pos.NewTokensPosition(NsTkn, CloseCurlyBracketTkn)
}
return &ast.StmtNamespace{
Position: pos,
NsTkn: NsTkn,
Name: Name,
OpenCurlyBracketTkn: OpenCurlyBracketTkn,
Stmts: Stmts,
CloseCurlyBracketTkn: CloseCurlyBracketTkn,
SemiColonTkn: SemiColonTkn,
}
}
func (b *Builder) NewUseList(
UseTkn *token.Token,
Type *token.Token,
UsesList ast.Vertex,
SemiColonTkn *token.Token,
) *ast.StmtUseList {
uses, sepTkns := b.SeparatedListItems(UsesList)
return &ast.StmtUseList{
Position: b.Pos.NewTokensPosition(UseTkn, SemiColonTkn),
UseTkn: UseTkn,
Type: b.NewIdentifier(Type),
Uses: uses,
SeparatorTkns: sepTkns,
SemiColonTkn: SemiColonTkn,
}
}
func (b *Builder) NewGroupUseList(
UseTkn *token.Token,
Type *token.Token,
Prefix ast.Vertex,
NsSeparatorTkn *token.Token,
OpenCurlyBracketTkn *token.Token,
UsesList ast.Vertex,
CloseCurlyBracketTkn *token.Token,
SemiColonTkn *token.Token,
) *ast.StmtGroupUseList {
uses, sepTkns := b.SeparatedListItems(UsesList)
groupUse := &ast.StmtGroupUseList{
Position: b.Pos.NewTokensPosition(UseTkn, SemiColonTkn),
UseTkn: UseTkn,
Type: b.NewIdentifier(Type),
Prefix: Prefix,
NsSeparatorTkn: NsSeparatorTkn,
OpenCurlyBracketTkn: OpenCurlyBracketTkn,
Uses: uses,
SeparatorTkns: sepTkns,
CloseCurlyBracketTkn: CloseCurlyBracketTkn,
SemiColonTkn: SemiColonTkn,
}
if n, ok := Prefix.(*ast.NameFullyQualified); ok {
groupUse.LeadingNsSeparatorTkn = n.NsSeparatorTkn
prefix := &ast.Name{
Position: n.Position,
Parts: n.Parts,
SeparatorTkns: n.SeparatorTkns,
}
prefix.Position.StartPos++
groupUse.Prefix = prefix
}
return groupUse
}
func (b *Builder) NewUse(
Type ast.Vertex,
UseName ast.Vertex,
AsTkn *token.Token,
Alias *token.Token,
) *ast.StmtUse {
use := &ast.StmtUse{
Type: Type,
Use: UseName,
AsTkn: AsTkn,
Alias: b.NewIdentifier(Alias),
}
if Alias != nil {
use.Position = b.Pos.NewNodeTokenPosition(UseName, Alias)
} else {
use.Position = b.Pos.NewNodePosition(UseName)
}
if n, ok := UseName.(*ast.NameFullyQualified); ok {
use.NsSeparatorTkn = n.NsSeparatorTkn
name := &ast.Name{
Position: n.Position,
Parts: n.Parts,
SeparatorTkns: n.SeparatorTkns,
}
name.Position.StartPos++
use.Use = name
}
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,
}
}