mirror of
https://github.com/google/go-jsonnet.git
synced 2025-09-29 01:11:02 +02:00
break up parseObjectRemainder
This commit is contained in:
parent
407c0f311a
commit
0959f85501
2
go.mod
2
go.mod
@ -8,3 +8,5 @@ require (
|
||||
github.com/stretchr/testify v1.3.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2 // indirect
|
||||
)
|
||||
|
||||
go 1.13
|
||||
|
@ -349,30 +349,7 @@ func (p *parser) parseObjectAssignmentOp() (opFodder ast.Fodder, plusSugar bool,
|
||||
// +gen set
|
||||
type LiteralField string
|
||||
|
||||
// Parse object or object comprehension without leading brace
|
||||
func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
|
||||
var fields ast.ObjectFields
|
||||
literalFields := make(LiteralFieldSet)
|
||||
binds := make(ast.IdentifierSet)
|
||||
|
||||
gotComma := false
|
||||
first := true
|
||||
|
||||
next := p.pop()
|
||||
|
||||
for {
|
||||
|
||||
if next.kind == tokenBraceR {
|
||||
return &ast.Object{
|
||||
NodeBase: ast.NewNodeBaseLoc(locFromTokens(tok, next), tok.fodder),
|
||||
Fields: fields,
|
||||
TrailingComma: gotComma,
|
||||
CloseFodder: next.fodder,
|
||||
}, next, nil
|
||||
}
|
||||
|
||||
if next.kind == tokenFor {
|
||||
// It's a comprehension
|
||||
func (p *parser) parseObjectRemainderComp(fields ast.ObjectFields, gotComma bool, tok *token, next *token) (ast.Node, *token, error) {
|
||||
numFields := 0
|
||||
numAsserts := 0
|
||||
var field ast.ObjectField
|
||||
@ -413,13 +390,7 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
|
||||
}, last, nil
|
||||
}
|
||||
|
||||
if !gotComma && !first {
|
||||
return nil, nil, errors.MakeStaticError("Expected a comma before next field.", next.loc)
|
||||
}
|
||||
|
||||
switch next.kind {
|
||||
case tokenBracketL, tokenIdentifier, tokenStringDouble, tokenStringSingle,
|
||||
tokenStringBlock, tokenVerbatimStringDouble, tokenVerbatimStringSingle:
|
||||
func (p *parser) parseObjectRemainderField(literalFields *LiteralFieldSet, tok *token, next *token) (*ast.ObjectField, error) {
|
||||
var kind ast.ObjectFieldKind
|
||||
var fodder1 ast.Fodder
|
||||
var expr1 ast.Node
|
||||
@ -440,11 +411,11 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
|
||||
var err error
|
||||
expr1, err = p.parse(maxPrecedence)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
bracketR, err := p.popExpect(tokenBracketR)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
fodder2 = bracketR.fodder
|
||||
}
|
||||
@ -459,31 +430,31 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
|
||||
var err error
|
||||
parenR, params, methComma, err = p.parseParameters("method parameter")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
isMethod = true
|
||||
}
|
||||
|
||||
opFodder, plusSugar, hide, err := p.parseObjectAssignmentOp()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if plusSugar && isMethod {
|
||||
return nil, nil, errors.MakeStaticError(
|
||||
return nil, errors.MakeStaticError(
|
||||
fmt.Sprintf("Cannot use +: syntax sugar in a method: %v", next.data), next.loc)
|
||||
}
|
||||
|
||||
if kind != ast.ObjectFieldExpr {
|
||||
if !literalFields.Add(LiteralField(next.data)) {
|
||||
return nil, nil, errors.MakeStaticError(
|
||||
return nil, errors.MakeStaticError(
|
||||
fmt.Sprintf("Duplicate field: %v", next.data), next.loc)
|
||||
}
|
||||
}
|
||||
|
||||
body, err := p.parse(maxPrecedence)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var method *ast.Function
|
||||
@ -502,7 +473,7 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
|
||||
commaFodder = p.peek().fodder
|
||||
}
|
||||
|
||||
fields = append(fields, ast.ObjectField{
|
||||
return &ast.ObjectField{
|
||||
Kind: kind,
|
||||
Hide: hide,
|
||||
SuperSugar: plusSugar,
|
||||
@ -514,18 +485,19 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
|
||||
OpFodder: opFodder,
|
||||
Expr2: body,
|
||||
CommaFodder: commaFodder,
|
||||
})
|
||||
}, nil
|
||||
}
|
||||
|
||||
case tokenLocal:
|
||||
func (p *parser) parseObjectRemainderLocal(binds *ast.IdentifierSet, tok *token, next *token) (*ast.ObjectField, error) {
|
||||
varID, err := p.popExpect(tokenIdentifier)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id := ast.Identifier(varID.data)
|
||||
|
||||
if binds.Contains(id) {
|
||||
return nil, nil, errors.MakeStaticError(fmt.Sprintf("Duplicate local var: %v", id), varID.loc)
|
||||
return nil, errors.MakeStaticError(fmt.Sprintf("Duplicate local var: %v", id), varID.loc)
|
||||
}
|
||||
|
||||
// TODO(sbarzowski) Can we reuse regular local bind parsing here?
|
||||
@ -540,17 +512,17 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
|
||||
isMethod = true
|
||||
parenR, params, funcComma, err = p.parseParameters("function parameter")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
opToken, err := p.popExpectOp("=")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body, err := p.parse(maxPrecedence)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var method *ast.Function
|
||||
@ -571,7 +543,7 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
|
||||
commaFodder = p.peek().fodder
|
||||
}
|
||||
|
||||
fields = append(fields, ast.ObjectField{
|
||||
return &ast.ObjectField{
|
||||
Kind: ast.ObjectLocal,
|
||||
Hide: ast.ObjectFieldVisible,
|
||||
SuperSugar: false,
|
||||
@ -582,12 +554,13 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
|
||||
OpFodder: opToken.fodder,
|
||||
Expr2: body,
|
||||
CommaFodder: commaFodder,
|
||||
})
|
||||
}, nil
|
||||
}
|
||||
|
||||
case tokenAssert:
|
||||
func (p *parser) parseObjectRemainderAssert(tok *token, next *token) (*ast.ObjectField, error) {
|
||||
cond, err := p.parse(maxPrecedence)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
var msg ast.Node
|
||||
var colonFodder ast.Fodder
|
||||
@ -596,7 +569,7 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
|
||||
colonFodder = colonToken.fodder
|
||||
msg, err = p.parse(maxPrecedence)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@ -605,7 +578,7 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
|
||||
commaFodder = p.peek().fodder
|
||||
}
|
||||
|
||||
fields = append(fields, ast.ObjectField{
|
||||
return &ast.ObjectField{
|
||||
Kind: ast.ObjectAssert,
|
||||
Hide: ast.ObjectFieldVisible,
|
||||
Fodder1: next.fodder,
|
||||
@ -613,10 +586,66 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
|
||||
OpFodder: colonFodder,
|
||||
Expr3: msg,
|
||||
CommaFodder: commaFodder,
|
||||
})
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Parse object or object comprehension without leading brace
|
||||
func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
|
||||
var fields ast.ObjectFields
|
||||
literalFields := make(LiteralFieldSet)
|
||||
binds := make(ast.IdentifierSet)
|
||||
|
||||
gotComma := false
|
||||
first := true
|
||||
|
||||
next := p.pop()
|
||||
|
||||
for {
|
||||
|
||||
if next.kind == tokenBraceR {
|
||||
return &ast.Object{
|
||||
NodeBase: ast.NewNodeBaseLoc(locFromTokens(tok, next), tok.fodder),
|
||||
Fields: fields,
|
||||
TrailingComma: gotComma,
|
||||
CloseFodder: next.fodder,
|
||||
}, next, nil
|
||||
}
|
||||
|
||||
if next.kind == tokenFor {
|
||||
// It's a comprehension
|
||||
return p.parseObjectRemainderComp(fields, gotComma, tok, next)
|
||||
}
|
||||
|
||||
if !gotComma && !first {
|
||||
return nil, nil, errors.MakeStaticError("Expected a comma before next field.", next.loc)
|
||||
}
|
||||
|
||||
var field *ast.ObjectField
|
||||
var err error
|
||||
switch next.kind {
|
||||
case tokenBracketL, tokenIdentifier, tokenStringDouble, tokenStringSingle,
|
||||
tokenStringBlock, tokenVerbatimStringDouble, tokenVerbatimStringSingle:
|
||||
field, err = p.parseObjectRemainderField(&literalFields, tok, next)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
case tokenLocal:
|
||||
field, err = p.parseObjectRemainderLocal(&binds, tok, next)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
case tokenAssert:
|
||||
field, err = p.parseObjectRemainderAssert(tok, next)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, nil, makeUnexpectedError(next, "parsing field definition")
|
||||
}
|
||||
fields = append(fields, *field)
|
||||
|
||||
next = p.pop()
|
||||
if next.kind == tokenComma {
|
||||
|
Loading…
x
Reference in New Issue
Block a user