Add influxql.Call.
parent
00f969af1f
commit
7288a778c3
|
@ -183,7 +183,7 @@ type VarRef struct {
|
|||
// Call represents a function call.
|
||||
type Call struct {
|
||||
Name string
|
||||
Expr Expr
|
||||
Args []Expr
|
||||
}
|
||||
|
||||
// NumberLiteral represents a numeric literal.
|
||||
|
@ -266,7 +266,9 @@ func Walk(v Visitor, node Node) {
|
|||
Walk(v, n.RHS)
|
||||
|
||||
case *Call:
|
||||
Walk(v, n.Expr)
|
||||
for _, expr := range n.Args {
|
||||
Walk(v, expr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -459,7 +459,14 @@ func (p *Parser) parseUnaryExpr() (Expr, error) {
|
|||
tok, pos, lit := p.scanIgnoreWhitespace()
|
||||
switch tok {
|
||||
case IDENT:
|
||||
return &VarRef{Val: lit}, nil
|
||||
// If the next immediate token is a left parentheses, parse as function call.
|
||||
// Otherwise parse as a variable reference.
|
||||
if tok0, _, _ := p.scan(); tok0 == LPAREN {
|
||||
return p.parseCall(lit)
|
||||
} else {
|
||||
p.unscan()
|
||||
return &VarRef{Val: lit}, nil
|
||||
}
|
||||
case STRING:
|
||||
return &StringLiteral{Val: lit}, nil
|
||||
case NUMBER:
|
||||
|
@ -478,6 +485,40 @@ func (p *Parser) parseUnaryExpr() (Expr, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// parseCall parses a function call.
|
||||
// This function assumes the function name and LPAREN have been consumed.
|
||||
func (p *Parser) parseCall(name string) (*Call, error) {
|
||||
// If there's a right paren then just return immediately.
|
||||
if tok, _, _ := p.scan(); tok == RPAREN {
|
||||
return &Call{Name: name}, nil
|
||||
}
|
||||
p.unscan()
|
||||
|
||||
// Otherwise parse function call arguments.
|
||||
var args []Expr
|
||||
for {
|
||||
// Parse an expression argument.
|
||||
arg, err := p.ParseExpr()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args = append(args, arg)
|
||||
|
||||
// If there's not a comma next then stop parsing arguments.
|
||||
if tok, _, _ := p.scan(); tok != COMMA {
|
||||
p.unscan()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// There should be a right parentheses at the end.
|
||||
if tok, pos, lit := p.scan(); tok != RPAREN {
|
||||
return nil, newParseError(tokstr(tok, lit), []string{")"}, pos)
|
||||
}
|
||||
|
||||
return &Call{Name: name, Args: args}, nil
|
||||
}
|
||||
|
||||
// scan returns the next token from the underlying scanner.
|
||||
func (p *Parser) scan() (tok Token, pos Pos, lit string) { return p.s.Scan() }
|
||||
|
||||
|
|
|
@ -234,6 +234,30 @@ func TestParser_ParseExpr(t *testing.T) {
|
|||
RHS: &influxql.BooleanLiteral{Val: true},
|
||||
},
|
||||
},
|
||||
|
||||
// 9. Function call (empty)
|
||||
{
|
||||
s: `my_func()`,
|
||||
expr: &influxql.Call{
|
||||
Name: "my_func",
|
||||
},
|
||||
},
|
||||
|
||||
// 10. Function call (multi-arg)
|
||||
{
|
||||
s: `my_func(1, 2 + 3)`,
|
||||
expr: &influxql.Call{
|
||||
Name: "my_func",
|
||||
Args: []influxql.Expr{
|
||||
&influxql.NumberLiteral{Val: 1},
|
||||
&influxql.BinaryExpr{
|
||||
Op: influxql.ADD,
|
||||
LHS: &influxql.NumberLiteral{Val: 2},
|
||||
RHS: &influxql.NumberLiteral{Val: 3},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
|
|
Loading…
Reference in New Issue