zclsyntax: parsing of function call expressions
This commit is contained in:
parent
e66e6a5f51
commit
a1368a4d4d
@ -122,6 +122,30 @@ func TestExpressionParseAndValue(t *testing.T) {
|
|||||||
cty.StringVal("hello $$nonescape"),
|
cty.StringVal("hello $$nonescape"),
|
||||||
0,
|
0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
`upper("foo")`,
|
||||||
|
&zcl.EvalContext{
|
||||||
|
Functions: map[string]function.Function{
|
||||||
|
"upper": stdlib.UpperFunc,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cty.StringVal("FOO"),
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`
|
||||||
|
upper(
|
||||||
|
"foo"
|
||||||
|
)
|
||||||
|
`,
|
||||||
|
&zcl.EvalContext{
|
||||||
|
Functions: map[string]function.Function{
|
||||||
|
"upper": stdlib.UpperFunc,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cty.StringVal("FOO"),
|
||||||
|
0,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
@ -463,6 +463,10 @@ func (p *parser) parseExpressionTerm() (Expression, zcl.Diagnostics) {
|
|||||||
case TokenIdent:
|
case TokenIdent:
|
||||||
tok := p.Read() // eat identifier token
|
tok := p.Read() // eat identifier token
|
||||||
|
|
||||||
|
if p.Peek().Type == TokenOParen {
|
||||||
|
return p.finishParsingFunctionCall(tok)
|
||||||
|
}
|
||||||
|
|
||||||
name := string(tok.Bytes)
|
name := string(tok.Bytes)
|
||||||
switch name {
|
switch name {
|
||||||
case "true":
|
case "true":
|
||||||
@ -549,6 +553,81 @@ func (p *parser) parseExpressionTerm() (Expression, zcl.Diagnostics) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// finishParsingFunctionCall parses a function call assuming that the function
|
||||||
|
// name was already read, and so the peeker should be pointing at the opening
|
||||||
|
// parenthesis after the name.
|
||||||
|
func (p *parser) finishParsingFunctionCall(name Token) (Expression, zcl.Diagnostics) {
|
||||||
|
openTok := p.Read()
|
||||||
|
if openTok.Type != TokenOParen {
|
||||||
|
// should never happen if callers behave
|
||||||
|
panic("finishParsingFunctionCall called with non-parenthesis as next token")
|
||||||
|
}
|
||||||
|
|
||||||
|
var args []Expression
|
||||||
|
var diags zcl.Diagnostics
|
||||||
|
var closeTok Token
|
||||||
|
|
||||||
|
// Arbitrary newlines are allowed inside the function call parentheses.
|
||||||
|
p.PushIncludeNewlines(false)
|
||||||
|
|
||||||
|
Token:
|
||||||
|
for {
|
||||||
|
tok := p.Peek()
|
||||||
|
|
||||||
|
if tok.Type == TokenCParen {
|
||||||
|
closeTok = p.Read() // eat closing paren
|
||||||
|
break Token
|
||||||
|
}
|
||||||
|
|
||||||
|
arg, argDiags := p.ParseExpression()
|
||||||
|
args = append(args, arg)
|
||||||
|
diags = append(diags, argDiags...)
|
||||||
|
if p.recovery && argDiags.HasErrors() {
|
||||||
|
// if there was a parse error in the argument then we've
|
||||||
|
// probably been left in a weird place in the token stream,
|
||||||
|
// so we'll bail out with a partial argument list.
|
||||||
|
p.recover(TokenCParen)
|
||||||
|
break Token
|
||||||
|
}
|
||||||
|
|
||||||
|
sep := p.Read()
|
||||||
|
if sep.Type == TokenCParen {
|
||||||
|
closeTok = sep
|
||||||
|
break Token
|
||||||
|
}
|
||||||
|
|
||||||
|
if sep.Type != TokenComma {
|
||||||
|
diags = append(diags, &zcl.Diagnostic{
|
||||||
|
Severity: zcl.DiagError,
|
||||||
|
Summary: "Missing argument separator",
|
||||||
|
Detail: "A comma is required to separate each function argument from the next.",
|
||||||
|
Subject: &sep.Range,
|
||||||
|
Context: zcl.RangeBetween(name.Range, sep.Range).Ptr(),
|
||||||
|
})
|
||||||
|
p.recover(TokenCParen)
|
||||||
|
break Token
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Peek().Type == TokenCParen {
|
||||||
|
// A trailing comma after the last argument gets us in here.
|
||||||
|
closeTok = p.Read() // eat closing paren
|
||||||
|
break Token
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
p.PopIncludeNewlines()
|
||||||
|
|
||||||
|
return &FunctionCallExpr{
|
||||||
|
Name: string(name.Bytes),
|
||||||
|
Args: args,
|
||||||
|
|
||||||
|
NameRange: name.Range,
|
||||||
|
OpenParenRange: openTok.Range,
|
||||||
|
CloseParenRange: closeTok.Range,
|
||||||
|
}, diags
|
||||||
|
}
|
||||||
|
|
||||||
func (p *parser) ParseTemplate(end TokenType) (Expression, zcl.Diagnostics) {
|
func (p *parser) ParseTemplate(end TokenType) (Expression, zcl.Diagnostics) {
|
||||||
var parts []Expression
|
var parts []Expression
|
||||||
var diags zcl.Diagnostics
|
var diags zcl.Diagnostics
|
||||||
|
Loading…
Reference in New Issue
Block a user