1package parser
2
3import (
4	"errors"
5	"fmt"
6	"strings"
7)
8
9// MetricRequest contains all necessary data to request a metric.
10type MetricRequest struct {
11	Metric string
12	From   int64
13	Until  int64
14}
15
16// ExprType defines a type for expression types constants (e.x. functions, values, constants, parameters, strings)
17type ExprType int
18
19const (
20	// EtName is a const for 'Series Name' type expression
21	EtName ExprType = iota
22	// EtFunc is a const for 'Function' type expression
23	EtFunc
24	// EtConst is a const for 'Constant' type expression
25	EtConst
26	// EtString is a const for 'String' type expression
27	EtString
28	// EtBool is a constant for 'Bool' type expression
29	EtBool
30)
31
32var (
33	// ErrMissingExpr is a parse error returned when an expression is missing.
34	ErrMissingExpr = errors.New("missing expression")
35	// ErrMissingComma is a parse error returned when an expression is missing a comma.
36	ErrMissingComma = errors.New("missing comma")
37	// ErrMissingQuote is a parse error returned when an expression is missing a quote.
38	ErrMissingQuote = errors.New("missing quote")
39	// ErrUnexpectedCharacter is a parse error returned when an expression contains an unexpected character.
40	ErrUnexpectedCharacter = errors.New("unexpected character")
41	// ErrBadType is an eval error returned when a argument has wrong type.
42	ErrBadType = errors.New("bad type")
43	// ErrMissingArgument is an eval error returned when a argument is missing.
44	ErrMissingArgument = errors.New("missing argument")
45	// ErrMissingTimeseries is an eval error returned when a time series argument is missing.
46	ErrMissingTimeseries = errors.New("missing time series argument")
47	// ErrSeriesDoesNotExist is an eval error returned when a requested time series argument does not exist.
48	ErrSeriesDoesNotExist = errors.New("no timeseries with that name")
49	// ErrUnknownTimeUnits is an eval error returned when a time unit is unknown to system
50	ErrUnknownTimeUnits = errors.New("unknown time units")
51)
52
53// NodeOrTag structure contains either Node (=integer) or Tag (=string)
54// They are distinguished by "IsTag" = true in case it's tag.
55type NodeOrTag struct {
56	IsTag bool
57	Value interface{}
58}
59
60// Expr defines an interface to talk with expressions
61type Expr interface {
62	// IsName checks if Expression is 'Series Name' expression
63	IsName() bool
64	// IsFunc checks if Expression is 'Function' expression
65	IsFunc() bool
66	// IsConst checks if Expression is 'Constant' expression
67	IsConst() bool
68	// IsString checks if Expression is 'String' expression
69	IsString() bool
70	// IsBool checks if Expression is 'Bool' expression
71	IsBool() bool
72	// Type returns type of the expression
73	Type() ExprType
74	// Target returns target value for expression
75	Target() string
76	// SetTarget changes target for the expression
77	SetTarget(string)
78	// MutateTarget changes target for the expression and returns new interface. Please note that it doesn't copy object yet
79	MutateTarget(string) Expr
80	// ToString returns string representation of expression
81	ToString() string
82
83	// FloatValue returns float value for expression.
84	FloatValue() float64
85
86	// StringValue returns value of String-typed expression (will return empty string for ConstExpr for example).
87	StringValue() string
88	// SetValString changes value of String-typed expression
89	SetValString(string)
90	// MutateValString changes ValString for the expression and returns new interface. Please note that it doesn't copy object yet
91	MutateValString(string) Expr
92
93	// Args returns slice of arguments (parsed, as Expr interface as well)
94	Args() []Expr
95	// NamedArgs returns map of named arguments. E.x. for nonNegativeDerivative(metric1,maxValue=32) it will return map{"maxValue": constExpr(32)}
96	NamedArgs() map[string]Expr
97	// RawArgs returns string that contains all arguments of expression exactly the same order they appear
98	RawArgs() string
99	// SetRawArgs changes raw argument list for current expression.
100	SetRawArgs(args string)
101	// MutateRawArgs changes raw argument list for the expression and returns new interface. Please note that it doesn't copy object yet
102	MutateRawArgs(args string) Expr
103
104	// Metrics returns list of metric requests
105	Metrics() []MetricRequest
106
107	// GetIntervalArg returns interval typed argument.
108	GetIntervalArg(n int, defaultSign int) (int32, error)
109
110	// GetStringArg returns n-th argument as string.
111	GetStringArg(n int) (string, error)
112	// GetStringArgs returns n-th argument as slice of strings.
113	GetStringArgs(n int) ([]string, error)
114	// GetStringArgDefault returns n-th argument as string. It will replace it with Default value if none present.
115	GetStringArgDefault(n int, s string) (string, error)
116	// GetStringNamedOrPosArgDefault returns specific positioned string-typed argument or replace it with default if none found.
117	GetStringNamedOrPosArgDefault(k string, n int, s string) (string, error)
118
119	// GetFloatArg returns n-th argument as float-typed (if it's convertible to float)
120	GetFloatArg(n int) (float64, error)
121	// GetFloatArgDefault returns n-th argument as float. It will replace it with Default value if none present.
122	GetFloatArgDefault(n int, v float64) (float64, error)
123	// GetFloatNamedOrPosArgDefault returns specific positioned float64-typed argument or replace it with default if none found.
124	GetFloatNamedOrPosArgDefault(k string, n int, v float64) (float64, error)
125
126	// GetIntArg returns n-th argument as int-typed
127	GetIntArg(n int) (int, error)
128	// GetIntArgs returns n-th argument as slice of ints
129	GetIntArgs(n int) ([]int, error)
130	// GetIntArgDefault returns n-th argument as int. It will replace it with Default value if none present.
131	GetIntArgDefault(n int, d int) (int, error)
132	// GetIntNamedOrPosArgDefault returns specific positioned int-typed argument or replace it with default if none found.
133	GetIntNamedOrPosArgDefault(k string, n int, d int) (int, error)
134
135	GetNamedArg(name string) Expr
136
137	// GetBoolArgDefault returns n-th argument as bool. It will replace it with Default value if none present.
138	GetBoolArgDefault(n int, b bool) (bool, error)
139	// GetBoolNamedOrPosArgDefault returns specific positioned bool-typed argument or replace it with default if none found.
140	GetBoolNamedOrPosArgDefault(k string, n int, b bool) (bool, error)
141
142	// GetNodeOrTagArgs returns n-th argument as slice of NodeOrTag structures.
143	GetNodeOrTagArgs(n int) ([]NodeOrTag, error)
144
145	IsInterfaceNil() bool
146
147	toExpr() interface{}
148}
149
150var _ Expr = &expr{}
151
152// Parse parses string as an expression.
153func Parse(e string) (Expr, string, error) {
154	return ParseExpr(e)
155}
156
157// NewTargetExpr Creates new expression with specified target only.
158func NewTargetExpr(target string) Expr {
159	e := &expr{
160		target:    target,
161		argString: target,
162	}
163	return e
164}
165
166// NewNameExpr Creates new expression with specified name only.
167func NewNameExpr(name string) Expr {
168	e := &expr{
169		target:    name,
170		etype:     EtName,
171		argString: name,
172	}
173	return e
174}
175
176// NewConstExpr Creates new Constant expression.
177func NewConstExpr(value float64) Expr {
178	e := &expr{
179		val:       value,
180		etype:     EtConst,
181		argString: fmt.Sprintf("%v", value),
182	}
183	return e
184}
185
186// NewValueExpr Creates new Value expression.
187func NewValueExpr(value string) Expr {
188	e := &expr{
189		valStr:    value,
190		etype:     EtString,
191		argString: value,
192	}
193	return e
194}
195
196// ArgName is a type for Name Argument
197type ArgName string
198
199// ArgValue is a type for Value Argument
200type ArgValue string
201
202// NamedArgs is a type for Hashmap of Named Arguments.
203type NamedArgs map[string]interface{}
204
205// NewExpr creates a new expression with specified target and arguments. It will do best it can to identify type of argument
206func NewExpr(target string, vaArgs ...interface{}) Expr {
207	var nArgsFinal map[string]*expr
208	args, nArgs := sliceExpr(vaArgs)
209	if args == nil {
210		panic(fmt.Sprintf("unsupported argument list for target=%v\n", target))
211	}
212
213	var a []*expr
214	var argStrs []string
215	for _, arg := range args {
216		argStrs = append(argStrs, arg.RawArgs())
217		a = append(a, arg)
218	}
219
220	if nArgs != nil {
221		nArgsFinal = make(map[string]*expr)
222		for k, v := range nArgs {
223			nArgsFinal[k] = v
224			argStrs = append(argStrs, k+"="+v.RawArgs())
225		}
226	}
227
228	e := &expr{
229		target:    target,
230		etype:     EtFunc,
231		args:      a,
232		argString: strings.Join(argStrs, ","),
233	}
234
235	if nArgsFinal != nil {
236		e.namedArgs = nArgsFinal
237	}
238
239	return e
240}
241
242// NewExprTyped creates a new expression with specified target and arguments. Strictly typed one.
243func NewExprTyped(target string, args []Expr) Expr {
244	var a []*expr
245	var argStrs []string
246	for _, arg := range args {
247		argStrs = append(argStrs, arg.Target())
248		a = append(a, arg.toExpr().(*expr))
249	}
250
251	e := &expr{
252		target:    target,
253		etype:     EtFunc,
254		args:      a,
255		argString: strings.Join(argStrs, ","),
256	}
257
258	return e
259}
260