| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | // Copyright 2015 The Prometheus Authors
 | 
					
						
							|  |  |  | // Licensed under the Apache License, Version 2.0 (the "License");
 | 
					
						
							|  |  |  | // you may not use this file except in compliance with the License.
 | 
					
						
							|  |  |  | // You may obtain a copy of the License at
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Unless required by applicable law or agreed to in writing, software
 | 
					
						
							|  |  |  | // distributed under the License is distributed on an "AS IS" BASIS,
 | 
					
						
							|  |  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					
						
							|  |  |  | // See the License for the specific language governing permissions and
 | 
					
						
							|  |  |  | // limitations under the License.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 00:23:44 +08:00
										 |  |  | package parser | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 	"math" | 
					
						
							| 
									
										
										
										
											2017-08-12 02:45:52 +08:00
										 |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	"runtime" | 
					
						
							|  |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2015-04-29 17:36:41 +08:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2020-01-10 01:36:13 +08:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-26 07:01:12 +08:00
										 |  |  | 	"github.com/pkg/errors" | 
					
						
							| 
									
										
										
										
											2015-08-20 23:18:46 +08:00
										 |  |  | 	"github.com/prometheus/common/model" | 
					
						
							| 
									
										
										
										
											2019-03-26 07:01:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-24 21:01:10 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/pkg/labels" | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/pkg/timestamp" | 
					
						
							| 
									
										
										
										
											2015-05-29 19:30:30 +08:00
										 |  |  | 	"github.com/prometheus/prometheus/util/strutil" | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 01:36:13 +08:00
										 |  |  | var parserPool = sync.Pool{ | 
					
						
							|  |  |  | 	New: func() interface{} { | 
					
						
							|  |  |  | 		return &parser{} | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | type parser struct { | 
					
						
							| 
									
										
										
										
											2020-01-10 01:36:13 +08:00
										 |  |  | 	lex Lexer | 
					
						
							| 
									
										
										
										
											2019-11-27 20:59:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 19:26:58 +08:00
										 |  |  | 	inject    ItemType | 
					
						
							| 
									
										
										
										
											2019-11-27 20:59:03 +08:00
										 |  |  | 	injecting bool | 
					
						
							| 
									
										
										
										
											2019-12-06 00:16:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-15 00:12:15 +08:00
										 |  |  | 	// Everytime an Item is lexed that could be the end
 | 
					
						
							|  |  |  | 	// of certain expressions its end position is stored here.
 | 
					
						
							|  |  |  | 	lastClosing Pos | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 19:26:58 +08:00
										 |  |  | 	yyParser yyParserImpl | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-16 21:58:47 +08:00
										 |  |  | 	generatedParserResult interface{} | 
					
						
							| 
									
										
										
										
											2020-01-16 23:20:20 +08:00
										 |  |  | 	parseErrors           ParseErrors | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-29 17:36:41 +08:00
										 |  |  | // ParseErr wraps a parsing error with line and position context.
 | 
					
						
							|  |  |  | type ParseErr struct { | 
					
						
							| 
									
										
										
										
											2020-01-16 04:01:49 +08:00
										 |  |  | 	PositionRange PositionRange | 
					
						
							|  |  |  | 	Err           error | 
					
						
							|  |  |  | 	Query         string | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 01:48:27 +08:00
										 |  |  | 	// LineOffset is an additional line offset to be added. Only used inside unit tests.
 | 
					
						
							|  |  |  | 	LineOffset int | 
					
						
							| 
									
										
										
										
											2015-04-29 17:36:41 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *ParseErr) Error() string { | 
					
						
							| 
									
										
										
										
											2020-01-16 04:01:49 +08:00
										 |  |  | 	pos := int(e.PositionRange.Start) | 
					
						
							|  |  |  | 	lastLineBreak := -1 | 
					
						
							| 
									
										
										
										
											2020-02-04 01:48:27 +08:00
										 |  |  | 	line := e.LineOffset + 1 | 
					
						
							| 
									
										
										
										
											2020-01-16 04:01:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	var positionStr string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if pos < 0 || pos > len(e.Query) { | 
					
						
							|  |  |  | 		positionStr = "invalid position:" | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-26 17:56:26 +08:00
										 |  |  | 		for i, c := range e.Query[:pos] { | 
					
						
							| 
									
										
										
										
											2020-01-16 04:01:49 +08:00
										 |  |  | 			if c == '\n' { | 
					
						
							|  |  |  | 				lastLineBreak = i | 
					
						
							|  |  |  | 				line++ | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		col := pos - lastLineBreak | 
					
						
							|  |  |  | 		positionStr = fmt.Sprintf("%d:%d:", line, col) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fmt.Sprintf("%s parse error: %s", positionStr, e.Err) | 
					
						
							| 
									
										
										
										
											2015-04-29 17:36:41 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-16 23:20:20 +08:00
										 |  |  | type ParseErrors []ParseErr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Since producing multiple error messages might look weird when combined with error wrapping,
 | 
					
						
							|  |  |  | // only the first error produced by the parser is included in the error string.
 | 
					
						
							|  |  |  | // If getting the full error list is desired, it is recommended to typecast the error returned
 | 
					
						
							|  |  |  | // by the parser to ParseErrors and work with the underlying slice.
 | 
					
						
							|  |  |  | func (errs ParseErrors) Error() string { | 
					
						
							|  |  |  | 	if len(errs) != 0 { | 
					
						
							|  |  |  | 		return errs[0].Error() | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-03-23 22:47:11 +08:00
										 |  |  | 	// Should never happen
 | 
					
						
							|  |  |  | 	// Panicking while printing an error seems like a bad idea, so the
 | 
					
						
							|  |  |  | 	// situation is explained in the error message instead.
 | 
					
						
							|  |  |  | 	return "error contains no error message" | 
					
						
							| 
									
										
										
										
											2020-01-16 23:20:20 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | // ParseExpr returns the expression parsed from the input.
 | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | func ParseExpr(input string) (expr Expr, err error) { | 
					
						
							| 
									
										
										
										
											2015-04-29 17:36:41 +08:00
										 |  |  | 	p := newParser(input) | 
					
						
							| 
									
										
										
										
											2020-01-10 01:36:13 +08:00
										 |  |  | 	defer parserPool.Put(p) | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 	defer p.recover(&err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-16 23:20:20 +08:00
										 |  |  | 	parseResult := p.parseGenerated(START_EXPRESSION) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if parseResult != nil { | 
					
						
							|  |  |  | 		expr = parseResult.(Expr) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Only typecheck when there are no syntax errors.
 | 
					
						
							|  |  |  | 	if len(p.parseErrors) == 0 { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		p.checkAST(expr) | 
					
						
							| 
									
										
										
										
											2020-01-16 23:20:20 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(p.parseErrors) != 0 { | 
					
						
							|  |  |  | 		err = p.parseErrors | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	return expr, err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-11 01:36:43 +08:00
										 |  |  | // ParseMetric parses the input into a metric
 | 
					
						
							| 
									
										
										
										
											2016-12-23 20:51:59 +08:00
										 |  |  | func ParseMetric(input string) (m labels.Labels, err error) { | 
					
						
							| 
									
										
										
										
											2015-06-11 01:36:43 +08:00
										 |  |  | 	p := newParser(input) | 
					
						
							| 
									
										
										
										
											2020-01-10 01:36:13 +08:00
										 |  |  | 	defer parserPool.Put(p) | 
					
						
							| 
									
										
										
										
											2015-06-11 01:36:43 +08:00
										 |  |  | 	defer p.recover(&err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-16 23:20:20 +08:00
										 |  |  | 	parseResult := p.parseGenerated(START_METRIC) | 
					
						
							|  |  |  | 	if parseResult != nil { | 
					
						
							|  |  |  | 		m = parseResult.(labels.Labels) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(p.parseErrors) != 0 { | 
					
						
							|  |  |  | 		err = p.parseErrors | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return m, err | 
					
						
							| 
									
										
										
										
											2015-06-11 01:36:43 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ParseMetricSelector parses the provided textual metric selector into a list of
 | 
					
						
							|  |  |  | // label matchers.
 | 
					
						
							| 
									
										
										
										
											2016-12-25 18:34:22 +08:00
										 |  |  | func ParseMetricSelector(input string) (m []*labels.Matcher, err error) { | 
					
						
							| 
									
										
										
										
											2015-06-11 01:36:43 +08:00
										 |  |  | 	p := newParser(input) | 
					
						
							| 
									
										
										
										
											2020-01-10 01:36:13 +08:00
										 |  |  | 	defer parserPool.Put(p) | 
					
						
							| 
									
										
										
										
											2015-06-11 01:36:43 +08:00
										 |  |  | 	defer p.recover(&err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-16 23:20:20 +08:00
										 |  |  | 	parseResult := p.parseGenerated(START_METRIC_SELECTOR) | 
					
						
							|  |  |  | 	if parseResult != nil { | 
					
						
							|  |  |  | 		m = parseResult.(*VectorSelector).LabelMatchers | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(p.parseErrors) != 0 { | 
					
						
							|  |  |  | 		err = p.parseErrors | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return m, err | 
					
						
							| 
									
										
										
										
											2015-06-11 01:36:43 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | // newParser returns a new parser.
 | 
					
						
							| 
									
										
										
										
											2015-04-29 17:36:41 +08:00
										 |  |  | func newParser(input string) *parser { | 
					
						
							| 
									
										
										
										
											2020-01-10 01:36:13 +08:00
										 |  |  | 	p := parserPool.Get().(*parser) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	p.injecting = false | 
					
						
							| 
									
										
										
										
											2020-01-16 23:20:20 +08:00
										 |  |  | 	p.parseErrors = nil | 
					
						
							| 
									
										
										
										
											2020-04-16 07:44:43 +08:00
										 |  |  | 	p.generatedParserResult = nil | 
					
						
							| 
									
										
										
										
											2020-01-10 01:36:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Clear lexer struct before reusing.
 | 
					
						
							|  |  |  | 	p.lex = Lexer{ | 
					
						
							|  |  |  | 		input: input, | 
					
						
							|  |  |  | 		state: lexStatements, | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return p | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 00:45:41 +08:00
										 |  |  | // SequenceValue is an omittable value in a sequence of time series values.
 | 
					
						
							|  |  |  | type SequenceValue struct { | 
					
						
							| 
									
										
										
										
											2020-02-04 01:48:27 +08:00
										 |  |  | 	Value   float64 | 
					
						
							|  |  |  | 	Omitted bool | 
					
						
							| 
									
										
										
										
											2015-05-11 20:04:53 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 00:45:41 +08:00
										 |  |  | func (v SequenceValue) String() string { | 
					
						
							| 
									
										
										
										
											2020-02-04 01:48:27 +08:00
										 |  |  | 	if v.Omitted { | 
					
						
							| 
									
										
										
										
											2015-05-11 20:04:53 +08:00
										 |  |  | 		return "_" | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-04 01:48:27 +08:00
										 |  |  | 	return fmt.Sprintf("%f", v.Value) | 
					
						
							| 
									
										
										
										
											2015-05-11 20:04:53 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-21 16:44:12 +08:00
										 |  |  | type seriesDescription struct { | 
					
						
							|  |  |  | 	labels labels.Labels | 
					
						
							| 
									
										
										
										
											2020-02-04 00:45:41 +08:00
										 |  |  | 	values []SequenceValue | 
					
						
							| 
									
										
										
										
											2019-12-21 16:44:12 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 01:48:27 +08:00
										 |  |  | // ParseSeriesDesc parses the description of a time series.
 | 
					
						
							|  |  |  | func ParseSeriesDesc(input string) (labels labels.Labels, values []SequenceValue, err error) { | 
					
						
							| 
									
										
										
										
											2018-03-20 22:30:52 +08:00
										 |  |  | 	p := newParser(input) | 
					
						
							|  |  |  | 	p.lex.seriesDesc = true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-10 01:36:13 +08:00
										 |  |  | 	defer parserPool.Put(p) | 
					
						
							| 
									
										
										
										
											2015-05-11 20:04:53 +08:00
										 |  |  | 	defer p.recover(&err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-16 23:20:20 +08:00
										 |  |  | 	parseResult := p.parseGenerated(START_SERIES_DESCRIPTION) | 
					
						
							|  |  |  | 	if parseResult != nil { | 
					
						
							|  |  |  | 		result := parseResult.(*seriesDescription) | 
					
						
							| 
									
										
										
										
											2015-05-11 20:04:53 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-16 23:20:20 +08:00
										 |  |  | 		labels = result.labels | 
					
						
							|  |  |  | 		values = result.values | 
					
						
							| 
									
										
										
										
											2015-05-11 20:04:53 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-16 23:20:20 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-05-11 20:04:53 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-16 23:20:20 +08:00
										 |  |  | 	if len(p.parseErrors) != 0 { | 
					
						
							|  |  |  | 		err = p.parseErrors | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-16 23:20:20 +08:00
										 |  |  | 	return labels, values, err | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-27 14:08:31 +08:00
										 |  |  | // addParseErrf formats the error and appends it to the list of parsing errors.
 | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | func (p *parser) addParseErrf(positionRange PositionRange, format string, args ...interface{}) { | 
					
						
							|  |  |  | 	p.addParseErr(positionRange, errors.Errorf(format, args...)) | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | // addParseErr appends the provided error to the list of parsing errors.
 | 
					
						
							|  |  |  | func (p *parser) addParseErr(positionRange PositionRange, err error) { | 
					
						
							| 
									
										
										
										
											2020-01-16 23:20:20 +08:00
										 |  |  | 	perr := ParseErr{ | 
					
						
							| 
									
										
										
										
											2020-01-16 04:01:49 +08:00
										 |  |  | 		PositionRange: positionRange, | 
					
						
							|  |  |  | 		Err:           err, | 
					
						
							|  |  |  | 		Query:         p.lex.input, | 
					
						
							| 
									
										
										
										
											2015-04-29 17:36:41 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-16 23:20:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	p.parseErrors = append(p.parseErrors, perr) | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-19 01:36:43 +08:00
										 |  |  | // unexpected creates a parser error complaining about an unexpected lexer item.
 | 
					
						
							|  |  |  | // The item that is presented as unexpected is always the last item produced
 | 
					
						
							|  |  |  | // by the lexer.
 | 
					
						
							|  |  |  | func (p *parser) unexpected(context string, expected string) { | 
					
						
							|  |  |  | 	var errMsg strings.Builder | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-16 22:47:47 +08:00
										 |  |  | 	// Do not report lexer errors twice
 | 
					
						
							|  |  |  | 	if p.yyParser.lval.item.Typ == ERROR { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-19 01:36:43 +08:00
										 |  |  | 	errMsg.WriteString("unexpected ") | 
					
						
							| 
									
										
										
										
											2020-01-09 19:26:58 +08:00
										 |  |  | 	errMsg.WriteString(p.yyParser.lval.item.desc()) | 
					
						
							| 
									
										
										
										
											2019-12-19 01:36:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if context != "" { | 
					
						
							|  |  |  | 		errMsg.WriteString(" in ") | 
					
						
							|  |  |  | 		errMsg.WriteString(context) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if expected != "" { | 
					
						
							|  |  |  | 		errMsg.WriteString(", expected ") | 
					
						
							|  |  |  | 		errMsg.WriteString(expected) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 	p.addParseErr(p.yyParser.lval.item.PositionRange(), errors.New(errMsg.String())) | 
					
						
							| 
									
										
										
										
											2019-12-19 01:36:43 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-26 07:01:12 +08:00
										 |  |  | var errUnexpected = errors.New("unexpected error") | 
					
						
							| 
									
										
										
										
											2015-08-03 18:53:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | // recover is the handler that turns panics into returns from the top level of Parse.
 | 
					
						
							|  |  |  | func (p *parser) recover(errp *error) { | 
					
						
							|  |  |  | 	e := recover() | 
					
						
							| 
									
										
										
										
											2019-04-16 01:06:25 +08:00
										 |  |  | 	if _, ok := e.(runtime.Error); ok { | 
					
						
							|  |  |  | 		// Print the stack trace but do not inhibit the running application.
 | 
					
						
							|  |  |  | 		buf := make([]byte, 64<<10) | 
					
						
							|  |  |  | 		buf = buf[:runtime.Stack(buf, false)] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		fmt.Fprintf(os.Stderr, "parser panic: %v\n%s", e, buf) | 
					
						
							|  |  |  | 		*errp = errUnexpected | 
					
						
							|  |  |  | 	} else if e != nil { | 
					
						
							|  |  |  | 		*errp = e.(error) | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-26 21:28:36 +08:00
										 |  |  | // Lex is expected by the yyLexer interface of the yacc generated parser.
 | 
					
						
							| 
									
										
										
										
											2019-12-10 03:03:31 +08:00
										 |  |  | // It writes the next Item provided by the lexer to the provided pointer address.
 | 
					
						
							| 
									
										
										
										
											2019-11-26 21:28:36 +08:00
										 |  |  | // Comments are skipped.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // The yyLexer interface is currently implemented by the parser to allow
 | 
					
						
							|  |  |  | // the generated and non-generated parts to work together with regards to lookahead
 | 
					
						
							|  |  |  | // and error handling.
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2021-06-17 19:18:51 +08:00
										 |  |  | // For more information, see https://pkg.go.dev/golang.org/x/tools/cmd/goyacc.
 | 
					
						
							| 
									
										
										
										
											2019-11-26 21:28:36 +08:00
										 |  |  | func (p *parser) Lex(lval *yySymType) int { | 
					
						
							| 
									
										
										
										
											2020-01-09 19:26:58 +08:00
										 |  |  | 	var typ ItemType | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-27 20:59:03 +08:00
										 |  |  | 	if p.injecting { | 
					
						
							|  |  |  | 		p.injecting = false | 
					
						
							| 
									
										
										
										
											2020-01-09 19:26:58 +08:00
										 |  |  | 		return int(p.inject) | 
					
						
							| 
									
										
										
										
											2020-03-23 22:47:11 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// Skip comments.
 | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		p.lex.NextItem(&lval.item) | 
					
						
							|  |  |  | 		typ = lval.item.Typ | 
					
						
							|  |  |  | 		if typ != COMMENT { | 
					
						
							|  |  |  | 			break | 
					
						
							| 
									
										
										
										
											2020-01-09 19:26:58 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-11-27 20:59:03 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-11-26 21:28:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-15 00:12:15 +08:00
										 |  |  | 	switch typ { | 
					
						
							|  |  |  | 	case ERROR: | 
					
						
							| 
									
										
										
										
											2020-03-16 22:47:47 +08:00
										 |  |  | 		pos := PositionRange{ | 
					
						
							|  |  |  | 			Start: p.lex.start, | 
					
						
							|  |  |  | 			End:   Pos(len(p.lex.input)), | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		p.addParseErr(pos, errors.New(p.yyParser.lval.item.Val)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Tells yacc that this is the end of input.
 | 
					
						
							|  |  |  | 		return 0 | 
					
						
							| 
									
										
										
										
											2020-01-15 00:12:15 +08:00
										 |  |  | 	case EOF: | 
					
						
							| 
									
										
										
										
											2020-01-09 19:26:58 +08:00
										 |  |  | 		lval.item.Typ = EOF | 
					
						
							| 
									
										
										
										
											2020-01-08 22:59:25 +08:00
										 |  |  | 		p.InjectItem(0) | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 	case RIGHT_BRACE, RIGHT_PAREN, RIGHT_BRACKET, DURATION, NUMBER: | 
					
						
							| 
									
										
										
										
											2020-01-15 00:12:15 +08:00
										 |  |  | 		p.lastClosing = lval.item.Pos + Pos(len(lval.item.Val)) | 
					
						
							| 
									
										
										
										
											2019-12-06 00:16:12 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return int(typ) | 
					
						
							| 
									
										
										
										
											2019-11-26 21:28:36 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Error is expected by the yyLexer interface of the yacc generated parser.
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2019-12-06 00:16:12 +08:00
										 |  |  | // It is a no-op since the parsers error routines are triggered
 | 
					
						
							| 
									
										
										
										
											2020-01-02 22:54:09 +08:00
										 |  |  | // by mechanisms that allow more fine-grained control
 | 
					
						
							| 
									
										
										
										
											2021-06-17 19:18:51 +08:00
										 |  |  | // For more information, see https://pkg.go.dev/golang.org/x/tools/cmd/goyacc.
 | 
					
						
							| 
									
										
										
										
											2019-11-26 21:28:36 +08:00
										 |  |  | func (p *parser) Error(e string) { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-10 03:03:31 +08:00
										 |  |  | // InjectItem allows injecting a single Item at the beginning of the token stream
 | 
					
						
							| 
									
										
										
										
											2019-11-27 20:59:03 +08:00
										 |  |  | // consumed by the generated parser.
 | 
					
						
							|  |  |  | // This allows having multiple start symbols as described in
 | 
					
						
							|  |  |  | // https://www.gnu.org/software/bison/manual/html_node/Multiple-start_002dsymbols.html .
 | 
					
						
							| 
									
										
										
										
											2019-12-10 03:03:31 +08:00
										 |  |  | // Only the Lex function used by the generated parser is affected by this injected Item.
 | 
					
						
							|  |  |  | // Trying to inject when a previously injected Item has not yet been consumed will panic.
 | 
					
						
							|  |  |  | // Only Item types that are supposed to be used as start symbols are allowed as an argument.
 | 
					
						
							| 
									
										
										
										
											2019-11-27 20:59:03 +08:00
										 |  |  | func (p *parser) InjectItem(typ ItemType) { | 
					
						
							|  |  |  | 	if p.injecting { | 
					
						
							| 
									
										
										
										
											2019-12-10 03:03:31 +08:00
										 |  |  | 		panic("cannot inject multiple Items into the token stream") | 
					
						
							| 
									
										
										
										
											2019-11-27 20:59:03 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-06 00:16:12 +08:00
										 |  |  | 	if typ != 0 && (typ <= startSymbolsStart || typ >= startSymbolsEnd) { | 
					
						
							| 
									
										
										
										
											2019-11-27 20:59:03 +08:00
										 |  |  | 		panic("cannot inject symbol that isn't start symbol") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 19:26:58 +08:00
										 |  |  | 	p.inject = typ | 
					
						
							| 
									
										
										
										
											2019-11-27 20:59:03 +08:00
										 |  |  | 	p.injecting = true | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | func (p *parser) newBinaryExpression(lhs Node, op Item, modifiers Node, rhs Node) *BinaryExpr { | 
					
						
							|  |  |  | 	ret := modifiers.(*BinaryExpr) | 
					
						
							| 
									
										
										
										
											2019-11-27 20:59:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 	ret.LHS = lhs.(Expr) | 
					
						
							|  |  |  | 	ret.RHS = rhs.(Expr) | 
					
						
							|  |  |  | 	ret.Op = op.Typ | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 	return ret | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-15 00:12:15 +08:00
										 |  |  | func (p *parser) assembleVectorSelector(vs *VectorSelector) { | 
					
						
							|  |  |  | 	if vs.Name != "" { | 
					
						
							|  |  |  | 		nameMatcher, err := labels.NewMatcher(labels.MatchEqual, labels.MetricName, vs.Name) | 
					
						
							| 
									
										
										
										
											2018-12-22 21:47:13 +08:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 			panic(err) // Must not happen with labels.MatchEqual
 | 
					
						
							| 
									
										
										
										
											2018-12-22 21:47:13 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-01-15 00:12:15 +08:00
										 |  |  | 		vs.LabelMatchers = append(vs.LabelMatchers, nameMatcher) | 
					
						
							| 
									
										
										
										
											2015-05-11 17:45:23 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | func (p *parser) newAggregateExpr(op Item, modifier Node, args Node) (ret *AggregateExpr) { | 
					
						
							|  |  |  | 	ret = modifier.(*AggregateExpr) | 
					
						
							|  |  |  | 	arguments := args.(Expressions) | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 	ret.PosRange = PositionRange{ | 
					
						
							|  |  |  | 		Start: op.Pos, | 
					
						
							|  |  |  | 		End:   p.lastClosing, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 	ret.Op = op.Typ | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 	if len(arguments) == 0 { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		p.addParseErrf(ret.PositionRange(), "no arguments for aggregate expression provided") | 
					
						
							| 
									
										
										
										
											2016-02-08 02:03:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		// Prevents invalid array accesses.
 | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 	desiredArgs := 1 | 
					
						
							| 
									
										
										
										
											2020-02-04 01:48:27 +08:00
										 |  |  | 	if ret.Op.IsAggregatorWithParam() { | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 		desiredArgs = 2 | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 		ret.Param = arguments[0] | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 	if len(arguments) != desiredArgs { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		p.addParseErrf(ret.PositionRange(), "wrong number of arguments for aggregate expression provided, expected %d, got %d", desiredArgs, len(arguments)) | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 	ret.Expr = arguments[desiredArgs-1] | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 	return ret | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | // number parses a number.
 | 
					
						
							|  |  |  | func (p *parser) number(val string) float64 { | 
					
						
							|  |  |  | 	n, err := strconv.ParseInt(val, 0, 64) | 
					
						
							|  |  |  | 	f := float64(n) | 
					
						
							| 
									
										
										
										
											2016-01-25 11:50:46 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 		f, err = strconv.ParseFloat(val, 64) | 
					
						
							| 
									
										
										
										
											2015-06-16 00:34:41 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		p.addParseErrf(p.yyParser.lval.item.PositionRange(), "error parsing number: %s", err) | 
					
						
							| 
									
										
										
										
											2015-06-16 00:34:41 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 	return f | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // expectType checks the type of the node and raises an error if it
 | 
					
						
							|  |  |  | // is not of the expected type.
 | 
					
						
							| 
									
										
										
										
											2016-12-23 20:51:59 +08:00
										 |  |  | func (p *parser) expectType(node Node, want ValueType, context string) { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 	t := p.checkAST(node) | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	if t != want { | 
					
						
							| 
									
										
										
										
											2020-02-04 01:00:41 +08:00
										 |  |  | 		p.addParseErrf(node.PositionRange(), "expected type %s in %s, got %s", DocumentedType(want), context, DocumentedType(t)) | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | // checkAST checks the sanity of the provided AST. This includes type checking.
 | 
					
						
							|  |  |  | func (p *parser) checkAST(node Node) (typ ValueType) { | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	// For expressions the type is determined by their Type function.
 | 
					
						
							| 
									
										
										
										
											2018-02-12 20:09:51 +08:00
										 |  |  | 	// Lists do not have a type but are not invalid either.
 | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	switch n := node.(type) { | 
					
						
							| 
									
										
										
										
											2018-02-12 20:09:51 +08:00
										 |  |  | 	case Expressions: | 
					
						
							| 
									
										
										
										
											2016-12-23 20:51:59 +08:00
										 |  |  | 		typ = ValueTypeNone | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	case Expr: | 
					
						
							|  |  |  | 		typ = n.Type() | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		p.addParseErrf(node.PositionRange(), "unknown node type: %T", node) | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Recursively check correct typing for child nodes and raise
 | 
					
						
							|  |  |  | 	// errors in case of bad typing.
 | 
					
						
							|  |  |  | 	switch n := node.(type) { | 
					
						
							|  |  |  | 	case *EvalStmt: | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		ty := p.checkAST(n.Expr) | 
					
						
							| 
									
										
										
										
											2016-12-23 20:51:59 +08:00
										 |  |  | 		if ty == ValueTypeNone { | 
					
						
							| 
									
										
										
										
											2020-02-04 01:00:41 +08:00
										 |  |  | 			p.addParseErrf(n.Expr.PositionRange(), "evaluation statement must have a valid expression type but got %s", DocumentedType(ty)) | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case Expressions: | 
					
						
							|  |  |  | 		for _, e := range n { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 			ty := p.checkAST(e) | 
					
						
							| 
									
										
										
										
											2016-12-23 20:51:59 +08:00
										 |  |  | 			if ty == ValueTypeNone { | 
					
						
							| 
									
										
										
										
											2020-02-04 01:00:41 +08:00
										 |  |  | 				p.addParseErrf(e.PositionRange(), "expression must have a valid expression type but got %s", DocumentedType(ty)) | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case *AggregateExpr: | 
					
						
							| 
									
										
										
										
											2020-02-04 01:48:27 +08:00
										 |  |  | 		if !n.Op.IsAggregator() { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 			p.addParseErrf(n.PositionRange(), "aggregation operator expected in aggregation expression but got %q", n.Op) | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-12-23 20:51:59 +08:00
										 |  |  | 		p.expectType(n.Expr, ValueTypeVector, "aggregation expression") | 
					
						
							| 
									
										
										
										
											2019-11-26 21:29:42 +08:00
										 |  |  | 		if n.Op == TOPK || n.Op == BOTTOMK || n.Op == QUANTILE { | 
					
						
							| 
									
										
										
										
											2016-12-23 20:51:59 +08:00
										 |  |  | 			p.expectType(n.Param, ValueTypeScalar, "aggregation parameter") | 
					
						
							| 
									
										
										
										
											2016-07-05 01:03:05 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-11-26 21:29:42 +08:00
										 |  |  | 		if n.Op == COUNT_VALUES { | 
					
						
							| 
									
										
										
										
											2016-12-23 20:51:59 +08:00
										 |  |  | 			p.expectType(n.Param, ValueTypeString, "aggregation parameter") | 
					
						
							| 
									
										
										
										
											2016-07-06 00:12:19 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case *BinaryExpr: | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		lt := p.checkAST(n.LHS) | 
					
						
							|  |  |  | 		rt := p.checkAST(n.RHS) | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-17 21:06:27 +08:00
										 |  |  | 		// opRange returns the PositionRange of the operator part of the BinaryExpr.
 | 
					
						
							|  |  |  | 		// This is made a function instead of a variable, so it is lazily evaluated on demand.
 | 
					
						
							|  |  |  | 		opRange := func() (r PositionRange) { | 
					
						
							|  |  |  | 			// Remove whitespace at the beginning and end of the range.
 | 
					
						
							|  |  |  | 			for r.Start = n.LHS.PositionRange().End; isSpace(rune(p.lex.input[r.Start])); r.Start++ { | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			for r.End = n.RHS.PositionRange().Start - 1; isSpace(rune(p.lex.input[r.End])); r.End-- { | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 01:48:27 +08:00
										 |  |  | 		if n.ReturnBool && !n.Op.IsComparisonOperator() { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 			p.addParseErrf(opRange(), "bool modifier can only be used on comparison operators") | 
					
						
							| 
									
										
										
										
											2020-01-17 21:06:27 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 01:48:27 +08:00
										 |  |  | 		if n.Op.IsComparisonOperator() && !n.ReturnBool && n.RHS.Type() == ValueTypeScalar && n.LHS.Type() == ValueTypeScalar { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 			p.addParseErrf(opRange(), "comparisons between scalars must use BOOL modifier") | 
					
						
							| 
									
										
										
										
											2020-01-17 21:06:27 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 01:48:27 +08:00
										 |  |  | 		if n.Op.IsSetOperator() && n.VectorMatching.Card == CardOneToOne { | 
					
						
							| 
									
										
										
										
											2020-01-17 21:06:27 +08:00
										 |  |  | 			n.VectorMatching.Card = CardManyToMany | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for _, l1 := range n.VectorMatching.MatchingLabels { | 
					
						
							|  |  |  | 			for _, l2 := range n.VectorMatching.Include { | 
					
						
							|  |  |  | 				if l1 == l2 && n.VectorMatching.On { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 					p.addParseErrf(opRange(), "label %q must not occur in ON and GROUP clause at once", l1) | 
					
						
							| 
									
										
										
										
											2020-01-17 21:06:27 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 01:48:27 +08:00
										 |  |  | 		if !n.Op.IsOperator() { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 			p.addParseErrf(n.PositionRange(), "binary expression does not support operator %q", n.Op) | 
					
						
							| 
									
										
										
										
											2020-01-16 04:01:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if lt != ValueTypeScalar && lt != ValueTypeVector { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 			p.addParseErrf(n.LHS.PositionRange(), "binary expression must contain only scalar and instant vector types") | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-01-16 04:01:49 +08:00
										 |  |  | 		if rt != ValueTypeScalar && rt != ValueTypeVector { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 			p.addParseErrf(n.RHS.PositionRange(), "binary expression must contain only scalar and instant vector types") | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-23 20:51:59 +08:00
										 |  |  | 		if (lt != ValueTypeVector || rt != ValueTypeVector) && n.VectorMatching != nil { | 
					
						
							| 
									
										
										
										
											2016-04-26 21:28:36 +08:00
										 |  |  | 			if len(n.VectorMatching.MatchingLabels) > 0 { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 				p.addParseErrf(n.PositionRange(), "vector matching only allowed between instant vectors") | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			n.VectorMatching = nil | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2016-12-24 17:40:09 +08:00
										 |  |  | 			// Both operands are Vectors.
 | 
					
						
							| 
									
										
										
										
											2020-02-04 01:48:27 +08:00
										 |  |  | 			if n.Op.IsSetOperator() { | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 				if n.VectorMatching.Card == CardOneToMany || n.VectorMatching.Card == CardManyToOne { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 					p.addParseErrf(n.PositionRange(), "no grouping allowed for %q operation", n.Op) | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				if n.VectorMatching.Card != CardManyToMany { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 					p.addParseErrf(n.PositionRange(), "set operations must always be many-to-many") | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-04 01:48:27 +08:00
										 |  |  | 		if (lt == ValueTypeScalar || rt == ValueTypeScalar) && n.Op.IsSetOperator() { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 			p.addParseErrf(n.PositionRange(), "set operator %q not allowed in binary scalar expression", n.Op) | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case *Call: | 
					
						
							|  |  |  | 		nargs := len(n.Func.ArgTypes) | 
					
						
							| 
									
										
										
										
											2017-06-16 21:51:22 +08:00
										 |  |  | 		if n.Func.Variadic == 0 { | 
					
						
							|  |  |  | 			if nargs != len(n.Args) { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 				p.addParseErrf(n.PositionRange(), "expected %d argument(s) in call to %q, got %d", nargs, n.Func.Name, len(n.Args)) | 
					
						
							| 
									
										
										
										
											2017-06-16 21:51:22 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			na := nargs - 1 | 
					
						
							|  |  |  | 			if na > len(n.Args) { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 				p.addParseErrf(n.PositionRange(), "expected at least %d argument(s) in call to %q, got %d", na, n.Func.Name, len(n.Args)) | 
					
						
							| 
									
										
										
										
											2017-06-16 21:51:22 +08:00
										 |  |  | 			} else if nargsmax := na + n.Func.Variadic; n.Func.Variadic > 0 && nargsmax < len(n.Args) { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 				p.addParseErrf(n.PositionRange(), "expected at most %d argument(s) in call to %q, got %d", nargsmax, n.Func.Name, len(n.Args)) | 
					
						
							| 
									
										
										
										
											2017-06-16 21:51:22 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-06-16 21:51:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 		for i, arg := range n.Args { | 
					
						
							| 
									
										
										
										
											2017-06-16 21:51:22 +08:00
										 |  |  | 			if i >= len(n.Func.ArgTypes) { | 
					
						
							| 
									
										
										
										
											2020-03-08 20:09:24 +08:00
										 |  |  | 				if n.Func.Variadic == 0 { | 
					
						
							|  |  |  | 					// This is not a vararg function so we should not check the
 | 
					
						
							|  |  |  | 					// type of the extra arguments.
 | 
					
						
							|  |  |  | 					break | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-06-16 21:51:22 +08:00
										 |  |  | 				i = len(n.Func.ArgTypes) - 1 | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 			p.expectType(arg, n.Func.ArgTypes[i], fmt.Sprintf("call to function %q", n.Func.Name)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case *ParenExpr: | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		p.checkAST(n.Expr) | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case *UnaryExpr: | 
					
						
							| 
									
										
										
										
											2019-11-26 21:29:42 +08:00
										 |  |  | 		if n.Op != ADD && n.Op != SUB { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 			p.addParseErrf(n.PositionRange(), "only + and - operators allowed for unary expressions") | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		if t := p.checkAST(n.Expr); t != ValueTypeScalar && t != ValueTypeVector { | 
					
						
							| 
									
										
										
										
											2020-02-04 01:00:41 +08:00
										 |  |  | 			p.addParseErrf(n.PositionRange(), "unary expression only allowed on expressions of type scalar or instant vector, got %q", DocumentedType(t)) | 
					
						
							| 
									
										
										
										
											2015-08-04 20:57:34 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-22 21:47:13 +08:00
										 |  |  | 	case *SubqueryExpr: | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		ty := p.checkAST(n.Expr) | 
					
						
							| 
									
										
										
										
											2018-12-22 21:47:13 +08:00
										 |  |  | 		if ty != ValueTypeVector { | 
					
						
							| 
									
										
										
										
											2020-11-12 22:25:52 +08:00
										 |  |  | 			p.addParseErrf(n.PositionRange(), "subquery is only allowed on instant vector, got %s instead", ty) | 
					
						
							| 
									
										
										
										
											2018-12-22 21:47:13 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-01-10 22:25:41 +08:00
										 |  |  | 	case *MatrixSelector: | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		p.checkAST(n.VectorSelector) | 
					
						
							| 
									
										
										
										
											2018-12-22 21:47:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 	case *VectorSelector: | 
					
						
							| 
									
										
										
										
											2021-01-07 18:38:38 +08:00
										 |  |  | 		if n.Name != "" { | 
					
						
							|  |  |  | 			// In this case the last LabelMatcher is checking for the metric name
 | 
					
						
							|  |  |  | 			// set outside the braces. This checks if the name has already been set
 | 
					
						
							|  |  |  | 			// previously.
 | 
					
						
							|  |  |  | 			for _, m := range n.LabelMatchers[0 : len(n.LabelMatchers)-1] { | 
					
						
							|  |  |  | 				if m != nil && m.Name == labels.MetricName { | 
					
						
							|  |  |  | 					p.addParseErrf(n.PositionRange(), "metric name must not be set twice: %q or %q", n.Name, m.Value) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Skip the check for non-empty matchers because an explicit
 | 
					
						
							|  |  |  | 			// metric name is a non-empty matcher.
 | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		// A Vector selector must contain at least one non-empty matcher to prevent
 | 
					
						
							|  |  |  | 		// implicit selection of all metrics (e.g. by a typo).
 | 
					
						
							|  |  |  | 		notEmpty := false | 
					
						
							|  |  |  | 		for _, lm := range n.LabelMatchers { | 
					
						
							|  |  |  | 			if lm != nil && !lm.Matches("") { | 
					
						
							|  |  |  | 				notEmpty = true | 
					
						
							|  |  |  | 				break | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if !notEmpty { | 
					
						
							|  |  |  | 			p.addParseErrf(n.PositionRange(), "vector selector must contain at least one non-empty matcher") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case *NumberLiteral, *StringLiteral: | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 		// Nothing to do for terminals.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		p.addParseErrf(n.PositionRange(), "unknown node type: %T", node) | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-01 03:27:08 +08:00
										 |  |  | func (p *parser) unquoteString(s string) string { | 
					
						
							|  |  |  | 	unquoted, err := strutil.Unquote(s) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		p.addParseErrf(p.yyParser.lval.item.PositionRange(), "error unquoting string %q: %s", s, err) | 
					
						
							| 
									
										
										
										
											2015-10-01 03:27:08 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return unquoted | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | func parseDuration(ds string) (time.Duration, error) { | 
					
						
							| 
									
										
										
										
											2016-01-29 22:23:11 +08:00
										 |  |  | 	dur, err := model.ParseDuration(ds) | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return 0, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if dur == 0 { | 
					
						
							| 
									
										
										
										
											2019-03-26 07:01:12 +08:00
										 |  |  | 		return 0, errors.New("duration must be greater than 0") | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-01-29 22:23:11 +08:00
										 |  |  | 	return time.Duration(dur), nil | 
					
						
							| 
									
										
										
										
											2015-03-31 00:12:51 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-12-06 00:16:12 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // parseGenerated invokes the yacc generated parser.
 | 
					
						
							|  |  |  | // The generated parser gets the provided startSymbol injected into
 | 
					
						
							|  |  |  | // the lexer stream, based on which grammar will be used.
 | 
					
						
							| 
									
										
										
										
											2020-01-08 22:59:25 +08:00
										 |  |  | func (p *parser) parseGenerated(startSymbol ItemType) interface{} { | 
					
						
							| 
									
										
										
										
											2019-12-06 00:16:12 +08:00
										 |  |  | 	p.InjectItem(startSymbol) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-09 19:26:58 +08:00
										 |  |  | 	p.yyParser.Parse(p) | 
					
						
							| 
									
										
										
										
											2019-12-06 00:16:12 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return p.generatedParserResult | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-10 03:03:31 +08:00
										 |  |  | func (p *parser) newLabelMatcher(label Item, operator Item, value Item) *labels.Matcher { | 
					
						
							|  |  |  | 	op := operator.Typ | 
					
						
							|  |  |  | 	val := p.unquoteString(value.Val) | 
					
						
							| 
									
										
										
										
											2019-12-06 00:16:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-10 03:03:31 +08:00
										 |  |  | 	// Map the Item to the respective match type.
 | 
					
						
							| 
									
										
										
										
											2019-12-06 00:16:12 +08:00
										 |  |  | 	var matchType labels.MatchType | 
					
						
							|  |  |  | 	switch op { | 
					
						
							|  |  |  | 	case EQL: | 
					
						
							|  |  |  | 		matchType = labels.MatchEqual | 
					
						
							|  |  |  | 	case NEQ: | 
					
						
							|  |  |  | 		matchType = labels.MatchNotEqual | 
					
						
							|  |  |  | 	case EQL_REGEX: | 
					
						
							|  |  |  | 		matchType = labels.MatchRegexp | 
					
						
							|  |  |  | 	case NEQ_REGEX: | 
					
						
							|  |  |  | 		matchType = labels.MatchNotRegexp | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2020-01-02 22:54:09 +08:00
										 |  |  | 		// This should never happen, since the error should have been caught
 | 
					
						
							| 
									
										
										
										
											2019-12-06 00:16:12 +08:00
										 |  |  | 		// by the generated parser.
 | 
					
						
							|  |  |  | 		panic("invalid operator") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-10 03:03:31 +08:00
										 |  |  | 	m, err := labels.NewMatcher(matchType, label.Val, val) | 
					
						
							| 
									
										
										
										
											2019-12-06 00:16:12 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		p.addParseErr(mergeRanges(&label, &value), err) | 
					
						
							| 
									
										
										
										
											2019-12-06 00:16:12 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return m | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | // addOffset is used to set the offset in the generated parser.
 | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | func (p *parser) addOffset(e Node, offset time.Duration) { | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 	var orgoffsetp *time.Duration | 
					
						
							| 
									
										
										
										
											2020-01-15 00:12:15 +08:00
										 |  |  | 	var endPosp *Pos | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	switch s := e.(type) { | 
					
						
							|  |  |  | 	case *VectorSelector: | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 		orgoffsetp = &s.OriginalOffset | 
					
						
							| 
									
										
										
										
											2020-01-15 00:12:15 +08:00
										 |  |  | 		endPosp = &s.PosRange.End | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 	case *MatrixSelector: | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 		vs, ok := s.VectorSelector.(*VectorSelector) | 
					
						
							|  |  |  | 		if !ok { | 
					
						
							|  |  |  | 			p.addParseErrf(e.PositionRange(), "ranges only allowed for vector selectors") | 
					
						
							|  |  |  | 			return | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 		orgoffsetp = &vs.OriginalOffset | 
					
						
							| 
									
										
										
										
											2020-01-15 00:12:15 +08:00
										 |  |  | 		endPosp = &s.EndPos | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 	case *SubqueryExpr: | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 		orgoffsetp = &s.OriginalOffset | 
					
						
							| 
									
										
										
										
											2020-01-15 00:12:15 +08:00
										 |  |  | 		endPosp = &s.EndPos | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2021-05-11 05:33:26 +08:00
										 |  |  | 		p.addParseErrf(e.PositionRange(), "offset modifier must be preceded by an instant vector selector or range vector selector or a subquery") | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// it is already ensured by parseDuration func that there never will be a zero offset modifier
 | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 	if *orgoffsetp != 0 { | 
					
						
							| 
									
										
										
										
											2020-01-17 23:16:58 +08:00
										 |  |  | 		p.addParseErrf(e.PositionRange(), "offset may not be set multiple times") | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 	} else if orgoffsetp != nil { | 
					
						
							|  |  |  | 		*orgoffsetp = offset | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*endPosp = p.lastClosing | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // setTimestamp is used to set the timestamp from the @ modifier in the generated parser.
 | 
					
						
							|  |  |  | func (p *parser) setTimestamp(e Node, ts float64) { | 
					
						
							|  |  |  | 	if math.IsInf(ts, -1) || math.IsInf(ts, 1) || math.IsNaN(ts) || | 
					
						
							|  |  |  | 		ts >= float64(math.MaxInt64) || ts <= float64(math.MinInt64) { | 
					
						
							|  |  |  | 		p.addParseErrf(e.PositionRange(), "timestamp out of bounds for @ modifier: %f", ts) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var timestampp **int64 | 
					
						
							|  |  |  | 	var endPosp *Pos | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-10 00:03:16 +08:00
										 |  |  | 	timestampp, _, endPosp, ok := p.getAtModifierVars(e) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if timestampp != nil { | 
					
						
							|  |  |  | 		*timestampp = new(int64) | 
					
						
							|  |  |  | 		**timestampp = timestamp.FromFloatSeconds(ts) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*endPosp = p.lastClosing | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // setAtModifierPreprocessor is used to set the preprocessor for the @ modifier.
 | 
					
						
							|  |  |  | func (p *parser) setAtModifierPreprocessor(e Node, op Item) { | 
					
						
							|  |  |  | 	_, preprocp, endPosp, ok := p.getAtModifierVars(e) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if preprocp != nil { | 
					
						
							|  |  |  | 		*preprocp = op.Typ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*endPosp = p.lastClosing | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (p *parser) getAtModifierVars(e Node) (**int64, *ItemType, *Pos, bool) { | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		timestampp **int64 | 
					
						
							|  |  |  | 		preprocp   *ItemType | 
					
						
							|  |  |  | 		endPosp    *Pos | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 	switch s := e.(type) { | 
					
						
							|  |  |  | 	case *VectorSelector: | 
					
						
							|  |  |  | 		timestampp = &s.Timestamp | 
					
						
							| 
									
										
										
										
											2021-02-10 00:03:16 +08:00
										 |  |  | 		preprocp = &s.StartOrEnd | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 		endPosp = &s.PosRange.End | 
					
						
							|  |  |  | 	case *MatrixSelector: | 
					
						
							|  |  |  | 		vs, ok := s.VectorSelector.(*VectorSelector) | 
					
						
							|  |  |  | 		if !ok { | 
					
						
							|  |  |  | 			p.addParseErrf(e.PositionRange(), "ranges only allowed for vector selectors") | 
					
						
							| 
									
										
										
										
											2021-02-10 00:03:16 +08:00
										 |  |  | 			return nil, nil, nil, false | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-02-10 00:03:16 +08:00
										 |  |  | 		preprocp = &vs.StartOrEnd | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 		timestampp = &vs.Timestamp | 
					
						
							|  |  |  | 		endPosp = &s.EndPos | 
					
						
							|  |  |  | 	case *SubqueryExpr: | 
					
						
							| 
									
										
										
										
											2021-02-10 00:03:16 +08:00
										 |  |  | 		preprocp = &s.StartOrEnd | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 		timestampp = &s.Timestamp | 
					
						
							|  |  |  | 		endPosp = &s.EndPos | 
					
						
							|  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2021-05-11 05:33:26 +08:00
										 |  |  | 		p.addParseErrf(e.PositionRange(), "@ modifier must be preceded by an instant vector selector or range vector selector or a subquery") | 
					
						
							| 
									
										
										
										
											2021-02-10 00:03:16 +08:00
										 |  |  | 		return nil, nil, nil, false | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-10 00:03:16 +08:00
										 |  |  | 	if *timestampp != nil || (*preprocp) == START || (*preprocp) == END { | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | 		p.addParseErrf(e.PositionRange(), "@ <timestamp> may not be set multiple times") | 
					
						
							| 
									
										
										
										
											2021-02-10 00:03:16 +08:00
										 |  |  | 		return nil, nil, nil, false | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-10 00:03:16 +08:00
										 |  |  | 	return timestampp, preprocp, endPosp, true | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-01-15 00:12:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-20 18:57:39 +08:00
										 |  |  | func MustLabelMatcher(mt labels.MatchType, name, val string) *labels.Matcher { | 
					
						
							|  |  |  | 	m, err := labels.NewMatcher(mt, name, val) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		panic(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return m | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func MustGetFunction(name string) *Function { | 
					
						
							|  |  |  | 	f, ok := getFunction(name) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		panic(errors.Errorf("function %q does not exist", name)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return f | 
					
						
							| 
									
										
										
										
											2020-01-08 19:04:47 +08:00
										 |  |  | } |