2019-12-05 11:16:12 -05:00
|
|
|
// Copyright 2019 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-03 11:23:44 -05:00
|
|
|
package parser
|
2019-12-05 11:16:12 -05:00
|
|
|
|
2019-12-21 03:44:12 -05:00
|
|
|
import (
|
|
|
|
|
"math"
|
|
|
|
|
"strconv"
|
2020-01-08 06:04:47 -05:00
|
|
|
"time"
|
2019-12-16 11:38:18 -05:00
|
|
|
|
2021-11-08 09:23:17 -05:00
|
|
|
"github.com/prometheus/prometheus/model/labels"
|
|
|
|
|
"github.com/prometheus/prometheus/model/value"
|
2023-08-25 17:35:42 -04:00
|
|
|
"github.com/prometheus/prometheus/model/histogram"
|
2023-11-07 17:37:37 -05:00
|
|
|
"github.com/prometheus/prometheus/promql/parser/posrange"
|
2024-08-01 10:07:08 -04:00
|
|
|
|
|
|
|
|
"github.com/prometheus/common/model"
|
2019-12-21 03:44:12 -05:00
|
|
|
)
|
2022-03-09 17:14:58 -05:00
|
|
|
|
2019-12-05 11:16:12 -05:00
|
|
|
%}
|
|
|
|
|
|
|
|
|
|
%union {
|
2023-08-25 17:35:42 -04:00
|
|
|
node Node
|
|
|
|
|
item Item
|
|
|
|
|
matchers []*labels.Matcher
|
|
|
|
|
matcher *labels.Matcher
|
|
|
|
|
label labels.Label
|
|
|
|
|
labels labels.Labels
|
|
|
|
|
lblList []labels.Label
|
|
|
|
|
strings []string
|
|
|
|
|
series []SequenceValue
|
|
|
|
|
histogram *histogram.FloatHistogram
|
|
|
|
|
descriptors map[string]interface{}
|
|
|
|
|
bucket_set []float64
|
|
|
|
|
int int64
|
|
|
|
|
uint uint64
|
|
|
|
|
float float64
|
2019-12-05 11:16:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-01-17 10:16:58 -05:00
|
|
|
%token <item>
|
2020-09-09 06:10:02 -04:00
|
|
|
EQL
|
2020-01-08 06:04:47 -05:00
|
|
|
BLANK
|
|
|
|
|
COLON
|
|
|
|
|
COMMA
|
|
|
|
|
COMMENT
|
|
|
|
|
DURATION
|
|
|
|
|
EOF
|
|
|
|
|
ERROR
|
|
|
|
|
IDENTIFIER
|
|
|
|
|
LEFT_BRACE
|
|
|
|
|
LEFT_BRACKET
|
|
|
|
|
LEFT_PAREN
|
2023-08-25 17:35:42 -04:00
|
|
|
OPEN_HIST
|
|
|
|
|
CLOSE_HIST
|
2020-01-08 06:04:47 -05:00
|
|
|
METRIC_IDENTIFIER
|
|
|
|
|
NUMBER
|
|
|
|
|
RIGHT_BRACE
|
|
|
|
|
RIGHT_BRACKET
|
|
|
|
|
RIGHT_PAREN
|
|
|
|
|
SEMICOLON
|
|
|
|
|
SPACE
|
|
|
|
|
STRING
|
|
|
|
|
TIMES
|
2019-12-05 11:16:12 -05:00
|
|
|
|
2023-08-25 17:35:42 -04:00
|
|
|
// Histogram Descriptors.
|
|
|
|
|
%token histogramDescStart
|
|
|
|
|
%token <item>
|
|
|
|
|
SUM_DESC
|
|
|
|
|
COUNT_DESC
|
|
|
|
|
SCHEMA_DESC
|
|
|
|
|
OFFSET_DESC
|
|
|
|
|
NEGATIVE_OFFSET_DESC
|
|
|
|
|
BUCKETS_DESC
|
|
|
|
|
NEGATIVE_BUCKETS_DESC
|
|
|
|
|
ZERO_BUCKET_DESC
|
|
|
|
|
ZERO_BUCKET_WIDTH_DESC
|
2024-05-08 07:58:24 -04:00
|
|
|
CUSTOM_VALUES_DESC
|
2024-07-31 03:53:05 -04:00
|
|
|
COUNTER_RESET_HINT_DESC
|
2023-08-25 17:35:42 -04:00
|
|
|
%token histogramDescEnd
|
|
|
|
|
|
2019-12-05 11:16:12 -05:00
|
|
|
// Operators.
|
2020-01-08 06:04:47 -05:00
|
|
|
%token operatorsStart
|
|
|
|
|
%token <item>
|
|
|
|
|
ADD
|
|
|
|
|
DIV
|
2020-09-09 06:10:02 -04:00
|
|
|
EQLC
|
2020-01-08 06:04:47 -05:00
|
|
|
EQL_REGEX
|
|
|
|
|
GTE
|
|
|
|
|
GTR
|
2025-03-26 18:54:18 -04:00
|
|
|
TRIM_UPPER
|
|
|
|
|
TRIM_LOWER
|
2020-01-08 06:04:47 -05:00
|
|
|
LAND
|
|
|
|
|
LOR
|
|
|
|
|
LSS
|
|
|
|
|
LTE
|
|
|
|
|
LUNLESS
|
|
|
|
|
MOD
|
|
|
|
|
MUL
|
|
|
|
|
NEQ
|
|
|
|
|
NEQ_REGEX
|
|
|
|
|
POW
|
|
|
|
|
SUB
|
2021-01-20 05:57:39 -05:00
|
|
|
AT
|
2021-08-24 19:22:14 -04:00
|
|
|
ATAN2
|
2019-12-05 11:16:12 -05:00
|
|
|
%token operatorsEnd
|
|
|
|
|
|
|
|
|
|
// Aggregators.
|
2020-01-08 06:04:47 -05:00
|
|
|
%token aggregatorsStart
|
|
|
|
|
%token <item>
|
|
|
|
|
AVG
|
|
|
|
|
BOTTOMK
|
|
|
|
|
COUNT
|
|
|
|
|
COUNT_VALUES
|
2020-06-30 10:51:18 -04:00
|
|
|
GROUP
|
2020-01-08 06:04:47 -05:00
|
|
|
MAX
|
|
|
|
|
MIN
|
|
|
|
|
QUANTILE
|
|
|
|
|
STDDEV
|
|
|
|
|
STDVAR
|
|
|
|
|
SUM
|
|
|
|
|
TOPK
|
feat: add limitk() and limit_ratio() operators (#12503)
* rebase 2024-07-01, picks previous renaming to `limitk()` and `limit_ratio()`
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* gofumpt -d -extra
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* more lint fixes
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* more lint fixes+
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* put limitk() and limit_ratio() behind --enable-feature=promql-experimental-functions
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* EnableExperimentalFunctions for TestConcurrentRangeQueries() also
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* use testutil.RequireEqual to fix tests, WIP equivalent thingie for require.Contains
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* lint fix
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* moar linting
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* rebase 2024-06-19
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* re-add limit(2, metric) testing for N=2 common series subset
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* move `ratio = param` to default switch case, for better readability
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* gofumpt -d -extra util/testutil/cmp.go
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* early break when reaching k elems in limitk(), should have always been so (!)
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* small typo fix
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* no-change small break-loop rearrange for readability
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* remove IsNan(ratio) condition in switch-case, already handled as input validation
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* no-change adding some comments
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* no-change simplify fullMatrix() helper functions used for tests
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* add `limitk(-1, metric)` testcase, which is handled as any k < 1 case
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* engine_test.go: no-change create `requireCommonSeries() helper func (moving code into it) for readability
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* rebase 2024-06-21
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* engine_test.go: HAPPY NOW about its code -> reorg, create and use simpleRangeQuery() function, less lines and more readable ftW \o/
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* move limitk(), limit_ratio() testing to promql/promqltest/testdata/limit.test
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* remove stale leftover after moving tests from engine_test.go to testdata/
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* fix flaky `limit_ratio(0.5, ...)` test case
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* Update promql/engine.go
Co-authored-by: Julius Volz <julius.volz@gmail.com>
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* Update promql/engine.go
Co-authored-by: Julius Volz <julius.volz@gmail.com>
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* Update promql/engine.go
Co-authored-by: Julius Volz <julius.volz@gmail.com>
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* fix AddRatioSample() implementation to use a single conditional (instead of switch/case + fallback return)
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* docs/querying/operators.md: document r < 0
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* add negative limit_ratio() example to docs/querying/examples.md
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* move more extensive docu examples to docs/querying/operators.md
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* typo
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* small docu fix for poor-mans-normality-check, add it to limit.test ;)
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* limit.test: expand "Poor man's normality check" to whole eval range
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* restore mistakenly removed existing small comment
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* expand poors-man-normality-check case(s)
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* Revert "expand poors-man-normality-check case(s)"
This reverts commit f69e1603b2ebe69c0a100197cfbcf6f81644b564, indeed too
flaky 0:)
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* remove humor from docs/querying/operators.md
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* fix signoff
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* add web/ui missing changes
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* expand limit_ratio test cases, cross-fingering they'll not be flaky
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* remove flaky test
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* add missing warnings.Merge(ws) in instant-query return shortcut
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* add missing LimitK||LimitRatio case to codemirror-promql/src/parser/parser.ts
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* fix ui-lint
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* actually fix returned warnings :]
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
---------
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
Co-authored-by: Julius Volz <julius.volz@gmail.com>
2024-07-03 16:18:57 -04:00
|
|
|
LIMITK
|
|
|
|
|
LIMIT_RATIO
|
2019-12-05 11:16:12 -05:00
|
|
|
%token aggregatorsEnd
|
|
|
|
|
|
|
|
|
|
// Keywords.
|
2020-01-08 06:04:47 -05:00
|
|
|
%token keywordsStart
|
|
|
|
|
%token <item>
|
|
|
|
|
BOOL
|
|
|
|
|
BY
|
|
|
|
|
GROUP_LEFT
|
|
|
|
|
GROUP_RIGHT
|
2025-12-03 12:46:35 -05:00
|
|
|
FILL
|
|
|
|
|
FILL_LEFT
|
|
|
|
|
FILL_RIGHT
|
2020-01-08 06:04:47 -05:00
|
|
|
IGNORING
|
|
|
|
|
OFFSET
|
2025-09-25 05:34:59 -04:00
|
|
|
SMOOTHED
|
|
|
|
|
ANCHORED
|
2020-01-08 06:04:47 -05:00
|
|
|
ON
|
|
|
|
|
WITHOUT
|
2019-12-05 11:16:12 -05:00
|
|
|
%token keywordsEnd
|
|
|
|
|
|
2021-02-09 11:03:16 -05:00
|
|
|
// Preprocessors.
|
|
|
|
|
%token preprocessorStart
|
|
|
|
|
%token <item>
|
|
|
|
|
START
|
|
|
|
|
END
|
2025-06-25 11:39:27 -04:00
|
|
|
STEP
|
2025-12-10 10:16:08 -05:00
|
|
|
RANGE
|
2026-05-19 05:41:16 -04:00
|
|
|
MAX_OF
|
|
|
|
|
MIN_OF
|
2021-02-09 11:03:16 -05:00
|
|
|
%token preprocessorEnd
|
|
|
|
|
|
2024-07-31 03:53:05 -04:00
|
|
|
// Counter reset hints.
|
|
|
|
|
%token counterResetHintsStart
|
|
|
|
|
%token <item>
|
|
|
|
|
UNKNOWN_COUNTER_RESET
|
|
|
|
|
COUNTER_RESET
|
|
|
|
|
NOT_COUNTER_RESET
|
|
|
|
|
GAUGE_TYPE
|
|
|
|
|
%token counterResetHintsEnd
|
2019-12-05 11:16:12 -05:00
|
|
|
|
|
|
|
|
// Start symbols for the generated parser.
|
2020-01-08 06:04:47 -05:00
|
|
|
%token startSymbolsStart
|
|
|
|
|
%token
|
|
|
|
|
START_METRIC
|
|
|
|
|
START_SERIES_DESCRIPTION
|
|
|
|
|
START_EXPRESSION
|
|
|
|
|
START_METRIC_SELECTOR
|
2019-12-05 11:16:12 -05:00
|
|
|
%token startSymbolsEnd
|
|
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
|
|
|
|
|
// Type definitions for grammar rules.
|
2020-01-14 11:12:15 -05:00
|
|
|
%type <matchers> label_match_list
|
2019-12-05 11:16:12 -05:00
|
|
|
%type <matcher> label_matcher
|
2026-05-19 05:41:16 -04:00
|
|
|
%type <item> aggregate_op grouping_label match_op maybe_label metric_identifier unary_op at_modifier_preprocessors string_identifier counter_reset_hint max_of_min_of
|
2022-03-09 17:14:58 -05:00
|
|
|
%type <labels> label_set metric
|
|
|
|
|
%type <lblList> label_set_list
|
2020-01-08 06:04:47 -05:00
|
|
|
%type <label> label_set_item
|
|
|
|
|
%type <strings> grouping_label_list grouping_labels maybe_grouping_labels
|
|
|
|
|
%type <series> series_item series_values
|
2023-08-25 17:35:42 -04:00
|
|
|
%type <histogram> histogram_series_value
|
|
|
|
|
%type <descriptors> histogram_desc_map histogram_desc_item
|
|
|
|
|
%type <bucket_set> bucket_set bucket_set_list
|
|
|
|
|
%type <int> int
|
2019-12-21 03:44:12 -05:00
|
|
|
%type <uint> uint
|
2021-01-20 05:57:39 -05:00
|
|
|
%type <float> number series_value signed_number signed_or_unsigned_number
|
2025-12-03 12:46:35 -05:00
|
|
|
%type <node> step_invariant_expr aggregate_expr aggregate_modifier bin_modifier fill_modifiers binary_expr bool_modifier expr function_call function_call_args function_call_body group_modifiers fill_value label_matchers matrix_selector number_duration_literal offset_expr anchored_expr smoothed_expr on_or_ignoring paren_expr string_literal subquery_expr unary_expr vector_selector duration_expr paren_duration_expr positive_duration_expr offset_duration_expr
|
2019-12-16 08:58:47 -05:00
|
|
|
|
2019-12-05 11:16:12 -05:00
|
|
|
%start start
|
|
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
// Operators are listed with increasing precedence.
|
|
|
|
|
%left LOR
|
|
|
|
|
%left LAND LUNLESS
|
2025-03-26 18:54:18 -04:00
|
|
|
%left EQLC GTE GTR LSS LTE NEQ TRIM_UPPER TRIM_LOWER
|
2020-01-08 06:04:47 -05:00
|
|
|
%left ADD SUB
|
2021-08-24 19:22:14 -04:00
|
|
|
%left MUL DIV MOD ATAN2
|
2020-01-08 06:04:47 -05:00
|
|
|
%right POW
|
|
|
|
|
|
|
|
|
|
// Offset modifiers do not have associativity.
|
|
|
|
|
%nonassoc OFFSET
|
|
|
|
|
|
|
|
|
|
// This ensures that it is always attempted to parse range or subquery selectors when a left
|
|
|
|
|
// bracket is encountered.
|
|
|
|
|
%right LEFT_BRACKET
|
|
|
|
|
|
2019-12-05 11:16:12 -05:00
|
|
|
%%
|
|
|
|
|
|
2020-01-17 10:16:58 -05:00
|
|
|
start :
|
2020-01-08 06:04:47 -05:00
|
|
|
START_METRIC metric
|
|
|
|
|
{ yylex.(*parser).generatedParserResult = $2 }
|
2019-12-21 03:44:12 -05:00
|
|
|
| START_SERIES_DESCRIPTION series_description
|
2020-01-08 06:04:47 -05:00
|
|
|
| START_EXPRESSION /* empty */ EOF
|
2023-09-14 12:57:31 -04:00
|
|
|
{ yylex.(*parser).addParseErrf(posrange.PositionRange{}, "no expression found in input")}
|
2020-01-08 06:04:47 -05:00
|
|
|
| START_EXPRESSION expr
|
|
|
|
|
{ yylex.(*parser).generatedParserResult = $2 }
|
2020-01-17 10:16:58 -05:00
|
|
|
| START_METRIC_SELECTOR vector_selector
|
2020-01-08 06:04:47 -05:00
|
|
|
{ yylex.(*parser).generatedParserResult = $2 }
|
2019-12-21 03:44:12 -05:00
|
|
|
| start EOF
|
2019-12-16 08:58:47 -05:00
|
|
|
| error /* If none of the more detailed error messages are triggered, we fall back to this. */
|
2019-12-18 12:36:43 -05:00
|
|
|
{ yylex.(*parser).unexpected("","") }
|
2019-12-05 11:16:12 -05:00
|
|
|
;
|
|
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
expr :
|
|
|
|
|
aggregate_expr
|
|
|
|
|
| binary_expr
|
|
|
|
|
| function_call
|
|
|
|
|
| matrix_selector
|
2024-03-04 08:57:28 -05:00
|
|
|
| number_duration_literal
|
2020-01-08 06:04:47 -05:00
|
|
|
| offset_expr
|
2025-09-25 05:34:59 -04:00
|
|
|
| anchored_expr
|
|
|
|
|
| smoothed_expr
|
2020-01-08 06:04:47 -05:00
|
|
|
| paren_expr
|
|
|
|
|
| string_literal
|
|
|
|
|
| subquery_expr
|
|
|
|
|
| unary_expr
|
|
|
|
|
| vector_selector
|
2021-01-20 05:57:39 -05:00
|
|
|
| step_invariant_expr
|
2025-03-27 09:39:23 -04:00
|
|
|
| duration_expr
|
2020-01-08 06:04:47 -05:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Aggregations.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
aggregate_expr : aggregate_op aggregate_modifier function_call_body
|
2025-08-13 09:52:52 -04:00
|
|
|
{ $$ = yylex.(*parser).newAggregateExpr($1, $2, $3, false) }
|
2020-01-08 06:04:47 -05:00
|
|
|
| aggregate_op function_call_body aggregate_modifier
|
2025-08-13 09:52:52 -04:00
|
|
|
{ $$ = yylex.(*parser).newAggregateExpr($1, $3, $2, false) }
|
2020-01-08 06:04:47 -05:00
|
|
|
| aggregate_op function_call_body
|
2025-08-13 09:52:52 -04:00
|
|
|
{ $$ = yylex.(*parser).newAggregateExpr($1, &AggregateExpr{}, $2, true) }
|
2020-01-08 06:04:47 -05:00
|
|
|
| aggregate_op error
|
2021-01-20 05:57:39 -05:00
|
|
|
{
|
|
|
|
|
yylex.(*parser).unexpected("aggregation","");
|
2025-08-13 09:52:52 -04:00
|
|
|
$$ = yylex.(*parser).newAggregateExpr($1, &AggregateExpr{}, Expressions{}, false)
|
2020-03-05 03:03:38 -05:00
|
|
|
}
|
2020-01-08 06:04:47 -05:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
aggregate_modifier:
|
|
|
|
|
BY grouping_labels
|
|
|
|
|
{
|
|
|
|
|
$$ = &AggregateExpr{
|
|
|
|
|
Grouping: $2,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
| WITHOUT grouping_labels
|
|
|
|
|
{
|
|
|
|
|
$$ = &AggregateExpr{
|
|
|
|
|
Grouping: $2,
|
|
|
|
|
Without: true,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Binary expressions.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// Operator precedence only works if each of those is listed separately.
|
|
|
|
|
binary_expr : expr ADD bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
2021-08-24 19:22:14 -04:00
|
|
|
| expr ATAN2 bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
2020-01-08 06:04:47 -05:00
|
|
|
| expr DIV bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
2020-09-09 06:10:02 -04:00
|
|
|
| expr EQLC bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
2020-01-08 06:04:47 -05:00
|
|
|
| expr GTE bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
|
|
|
|
| expr GTR bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
2025-03-26 18:54:18 -04:00
|
|
|
| expr TRIM_UPPER bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
|
|
|
|
| expr TRIM_LOWER bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
2020-01-08 06:04:47 -05:00
|
|
|
| expr LAND bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
|
|
|
|
| expr LOR bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
|
|
|
|
| expr LSS bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
|
|
|
|
| expr LTE bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
|
|
|
|
| expr LUNLESS bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
|
|
|
|
| expr MOD bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
|
|
|
|
| expr MUL bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
|
|
|
|
| expr NEQ bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
|
|
|
|
| expr POW bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
|
|
|
|
| expr SUB bin_modifier expr { $$ = yylex.(*parser).newBinaryExpression($1, $2, $3, $4) }
|
|
|
|
|
;
|
|
|
|
|
|
2020-01-17 10:16:58 -05:00
|
|
|
// Using left recursion for the modifier rules, helps to keep the parser stack small and
|
2023-08-25 17:35:42 -04:00
|
|
|
// reduces allocations.
|
2025-12-03 12:46:35 -05:00
|
|
|
bin_modifier : fill_modifiers;
|
2020-01-08 06:04:47 -05:00
|
|
|
|
|
|
|
|
bool_modifier : /* empty */
|
|
|
|
|
{ $$ = &BinaryExpr{
|
|
|
|
|
VectorMatching: &VectorMatching{Card: CardOneToOne},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
| BOOL
|
|
|
|
|
{ $$ = &BinaryExpr{
|
|
|
|
|
VectorMatching: &VectorMatching{Card: CardOneToOne},
|
|
|
|
|
ReturnBool: true,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
on_or_ignoring : bool_modifier IGNORING grouping_labels
|
|
|
|
|
{
|
|
|
|
|
$$ = $1
|
|
|
|
|
$$.(*BinaryExpr).VectorMatching.MatchingLabels = $3
|
2020-01-17 10:16:58 -05:00
|
|
|
}
|
2020-01-08 06:04:47 -05:00
|
|
|
| bool_modifier ON grouping_labels
|
|
|
|
|
{
|
|
|
|
|
$$ = $1
|
|
|
|
|
$$.(*BinaryExpr).VectorMatching.MatchingLabels = $3
|
|
|
|
|
$$.(*BinaryExpr).VectorMatching.On = true
|
2020-01-17 10:16:58 -05:00
|
|
|
}
|
2020-01-08 06:04:47 -05:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
group_modifiers: bool_modifier /* empty */
|
|
|
|
|
| on_or_ignoring /* empty */
|
|
|
|
|
| on_or_ignoring GROUP_LEFT maybe_grouping_labels
|
|
|
|
|
{
|
|
|
|
|
$$ = $1
|
|
|
|
|
$$.(*BinaryExpr).VectorMatching.Card = CardManyToOne
|
|
|
|
|
$$.(*BinaryExpr).VectorMatching.Include = $3
|
|
|
|
|
}
|
|
|
|
|
| on_or_ignoring GROUP_RIGHT maybe_grouping_labels
|
|
|
|
|
{
|
|
|
|
|
$$ = $1
|
|
|
|
|
$$.(*BinaryExpr).VectorMatching.Card = CardOneToMany
|
|
|
|
|
$$.(*BinaryExpr).VectorMatching.Include = $3
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2025-12-03 12:46:35 -05:00
|
|
|
fill_modifiers: group_modifiers /* empty */
|
|
|
|
|
/* Only fill() */
|
|
|
|
|
| group_modifiers FILL fill_value
|
|
|
|
|
{
|
|
|
|
|
$$ = $1
|
|
|
|
|
fill := $3.(*NumberLiteral).Val
|
|
|
|
|
$$.(*BinaryExpr).VectorMatching.FillValues.LHS = &fill
|
|
|
|
|
$$.(*BinaryExpr).VectorMatching.FillValues.RHS = &fill
|
|
|
|
|
}
|
|
|
|
|
/* Only fill_left() */
|
|
|
|
|
| group_modifiers FILL_LEFT fill_value
|
|
|
|
|
{
|
|
|
|
|
$$ = $1
|
|
|
|
|
fill := $3.(*NumberLiteral).Val
|
|
|
|
|
$$.(*BinaryExpr).VectorMatching.FillValues.LHS = &fill
|
|
|
|
|
}
|
|
|
|
|
/* Only fill_right() */
|
|
|
|
|
| group_modifiers FILL_RIGHT fill_value
|
|
|
|
|
{
|
|
|
|
|
$$ = $1
|
|
|
|
|
fill := $3.(*NumberLiteral).Val
|
|
|
|
|
$$.(*BinaryExpr).VectorMatching.FillValues.RHS = &fill
|
|
|
|
|
}
|
|
|
|
|
/* fill_left() fill_right() */
|
|
|
|
|
| group_modifiers FILL_LEFT fill_value FILL_RIGHT fill_value
|
|
|
|
|
{
|
|
|
|
|
$$ = $1
|
|
|
|
|
fill_left := $3.(*NumberLiteral).Val
|
|
|
|
|
fill_right := $5.(*NumberLiteral).Val
|
|
|
|
|
$$.(*BinaryExpr).VectorMatching.FillValues.LHS = &fill_left
|
|
|
|
|
$$.(*BinaryExpr).VectorMatching.FillValues.RHS = &fill_right
|
|
|
|
|
}
|
|
|
|
|
/* fill_right() fill_left() */
|
|
|
|
|
| group_modifiers FILL_RIGHT fill_value FILL_LEFT fill_value
|
|
|
|
|
{
|
|
|
|
|
fill_right := $3.(*NumberLiteral).Val
|
|
|
|
|
fill_left := $5.(*NumberLiteral).Val
|
|
|
|
|
$$.(*BinaryExpr).VectorMatching.FillValues.LHS = &fill_left
|
|
|
|
|
$$.(*BinaryExpr).VectorMatching.FillValues.RHS = &fill_right
|
|
|
|
|
}
|
|
|
|
|
;
|
2019-12-05 11:16:12 -05:00
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
grouping_labels : LEFT_PAREN grouping_label_list RIGHT_PAREN
|
|
|
|
|
{ $$ = $2 }
|
|
|
|
|
| LEFT_PAREN grouping_label_list COMMA RIGHT_PAREN
|
|
|
|
|
{ $$ = $2 }
|
|
|
|
|
| LEFT_PAREN RIGHT_PAREN
|
|
|
|
|
{ $$ = []string{} }
|
|
|
|
|
| error
|
2020-01-16 10:20:20 -05:00
|
|
|
{ yylex.(*parser).unexpected("grouping opts", "\"(\""); $$ = nil }
|
2020-01-08 06:04:47 -05:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
grouping_label_list:
|
|
|
|
|
grouping_label_list COMMA grouping_label
|
|
|
|
|
{ $$ = append($1, $3.Val) }
|
|
|
|
|
| grouping_label
|
|
|
|
|
{ $$ = []string{$1.Val} }
|
|
|
|
|
| grouping_label_list error
|
2020-01-16 10:20:20 -05:00
|
|
|
{ yylex.(*parser).unexpected("grouping opts", "\",\" or \")\""); $$ = $1 }
|
2020-01-08 06:04:47 -05:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
grouping_label : maybe_label
|
|
|
|
|
{
|
2025-08-18 04:09:00 -04:00
|
|
|
if !model.UTF8Validation.IsValidLabelName($1.Val) {
|
2025-01-10 15:19:45 -05:00
|
|
|
yylex.(*parser).addParseErrf($1.PositionRange(),"invalid label name for grouping: %q", $1.Val)
|
2024-08-01 10:07:08 -04:00
|
|
|
}
|
|
|
|
|
$$ = $1
|
|
|
|
|
}
|
|
|
|
|
| STRING {
|
2025-01-10 15:19:45 -05:00
|
|
|
unquoted := yylex.(*parser).unquoteString($1.Val)
|
2025-08-18 04:09:00 -04:00
|
|
|
if !model.UTF8Validation.IsValidLabelName(unquoted) {
|
2025-01-10 15:19:45 -05:00
|
|
|
yylex.(*parser).addParseErrf($1.PositionRange(),"invalid label name for grouping: %q", unquoted)
|
2020-01-08 06:04:47 -05:00
|
|
|
}
|
|
|
|
|
$$ = $1
|
2024-08-01 10:07:08 -04:00
|
|
|
$$.Pos++
|
2025-01-10 15:19:45 -05:00
|
|
|
$$.Val = unquoted
|
2020-01-08 06:04:47 -05:00
|
|
|
}
|
|
|
|
|
| error
|
2020-01-16 10:20:20 -05:00
|
|
|
{ yylex.(*parser).unexpected("grouping opts", "label"); $$ = Item{} }
|
2020-01-08 06:04:47 -05:00
|
|
|
;
|
|
|
|
|
|
2025-12-03 12:46:35 -05:00
|
|
|
fill_value : LEFT_PAREN number_duration_literal RIGHT_PAREN
|
|
|
|
|
{
|
|
|
|
|
$$ = $2.(*NumberLiteral)
|
|
|
|
|
}
|
|
|
|
|
| LEFT_PAREN unary_op number_duration_literal RIGHT_PAREN
|
|
|
|
|
{
|
|
|
|
|
nl := $3.(*NumberLiteral)
|
|
|
|
|
if $2.Typ == SUB {
|
|
|
|
|
nl.Val *= -1
|
|
|
|
|
}
|
|
|
|
|
nl.PosRange.Start = $2.Pos
|
|
|
|
|
$$ = nl
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
/*
|
|
|
|
|
* Function calls.
|
|
|
|
|
*/
|
2020-01-17 10:16:58 -05:00
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
function_call : IDENTIFIER function_call_body
|
|
|
|
|
{
|
2023-03-22 05:02:10 -04:00
|
|
|
fn, exist := getFunction($1.Val, yylex.(*parser).functions)
|
2020-01-08 06:04:47 -05:00
|
|
|
if !exist{
|
2020-01-17 10:16:58 -05:00
|
|
|
yylex.(*parser).addParseErrf($1.PositionRange(),"unknown function with name %q", $1.Val)
|
|
|
|
|
}
|
2026-01-30 11:06:24 -05:00
|
|
|
if fn != nil && fn.Experimental && !yylex.(*parser).options.EnableExperimentalFunctions {
|
2023-11-07 17:37:37 -05:00
|
|
|
yylex.(*parser).addParseErrf($1.PositionRange(),"function %q is not enabled", $1.Val)
|
|
|
|
|
}
|
2020-01-08 06:04:47 -05:00
|
|
|
$$ = &Call{
|
|
|
|
|
Func: fn,
|
|
|
|
|
Args: $2.(Expressions),
|
2023-09-14 12:57:31 -04:00
|
|
|
PosRange: posrange.PositionRange{
|
2020-01-14 11:12:15 -05:00
|
|
|
Start: $1.Pos,
|
2025-08-05 04:48:08 -04:00
|
|
|
End: yylex.(*parser).lastClosing,
|
2020-01-14 11:12:15 -05:00
|
|
|
},
|
2020-01-08 06:04:47 -05:00
|
|
|
}
|
|
|
|
|
}
|
2026-01-16 11:48:49 -05:00
|
|
|
| at_modifier_preprocessors function_call_body
|
|
|
|
|
{
|
|
|
|
|
fn, exist := getFunction($1.Val, yylex.(*parser).functions)
|
|
|
|
|
if !exist{
|
|
|
|
|
yylex.(*parser).addParseErrf($1.PositionRange(),"unknown function with name %q", $1.Val)
|
|
|
|
|
}
|
|
|
|
|
if fn != nil && fn.Experimental && !yylex.(*parser).options.EnableExperimentalFunctions {
|
|
|
|
|
yylex.(*parser).addParseErrf($1.PositionRange(),"function %q is not enabled", $1.Val)
|
|
|
|
|
}
|
|
|
|
|
$$ = &Call{
|
|
|
|
|
Func: fn,
|
|
|
|
|
Args: $2.(Expressions),
|
|
|
|
|
PosRange: posrange.PositionRange{
|
|
|
|
|
Start: $1.PositionRange().Start,
|
|
|
|
|
End: yylex.(*parser).lastClosing,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
| STEP function_call_body
|
|
|
|
|
{
|
|
|
|
|
fn, exist := getFunction($1.Val, yylex.(*parser).functions)
|
|
|
|
|
if !exist{
|
|
|
|
|
yylex.(*parser).addParseErrf($1.PositionRange(),"unknown function with name %q", $1.Val)
|
|
|
|
|
}
|
|
|
|
|
if fn != nil && fn.Experimental && !yylex.(*parser).options.EnableExperimentalFunctions {
|
|
|
|
|
yylex.(*parser).addParseErrf($1.PositionRange(),"function %q is not enabled", $1.Val)
|
|
|
|
|
}
|
|
|
|
|
$$ = &Call{
|
|
|
|
|
Func: fn,
|
|
|
|
|
Args: $2.(Expressions),
|
|
|
|
|
PosRange: posrange.PositionRange{
|
|
|
|
|
Start: $1.PositionRange().Start,
|
|
|
|
|
End: yylex.(*parser).lastClosing,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
| RANGE function_call_body
|
|
|
|
|
{
|
|
|
|
|
fn, exist := getFunction($1.Val, yylex.(*parser).functions)
|
|
|
|
|
if !exist{
|
|
|
|
|
yylex.(*parser).addParseErrf($1.PositionRange(),"unknown function with name %q", $1.Val)
|
|
|
|
|
}
|
|
|
|
|
if fn != nil && fn.Experimental && !yylex.(*parser).options.EnableExperimentalFunctions {
|
|
|
|
|
yylex.(*parser).addParseErrf($1.PositionRange(),"function %q is not enabled", $1.Val)
|
|
|
|
|
}
|
|
|
|
|
$$ = &Call{
|
|
|
|
|
Func: fn,
|
|
|
|
|
Args: $2.(Expressions),
|
|
|
|
|
PosRange: posrange.PositionRange{
|
|
|
|
|
Start: $1.PositionRange().Start,
|
2026-05-13 11:47:21 -04:00
|
|
|
End: yylex.(*parser).lastClosing,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-05-19 05:41:16 -04:00
|
|
|
| max_of_min_of function_call_body
|
2026-05-13 11:47:21 -04:00
|
|
|
{
|
|
|
|
|
fn, exist := getFunction($1.Val, yylex.(*parser).functions)
|
|
|
|
|
if !exist{
|
|
|
|
|
yylex.(*parser).addParseErrf($1.PositionRange(),"unknown function with name %q", $1.Val)
|
|
|
|
|
}
|
|
|
|
|
if fn != nil && fn.Experimental && !yylex.(*parser).options.EnableExperimentalFunctions {
|
|
|
|
|
yylex.(*parser).addParseErrf($1.PositionRange(),"function %q is not enabled", $1.Val)
|
|
|
|
|
}
|
|
|
|
|
$$ = &Call{
|
|
|
|
|
Func: fn,
|
|
|
|
|
Args: $2.(Expressions),
|
|
|
|
|
PosRange: posrange.PositionRange{
|
|
|
|
|
Start: $1.PositionRange().Start,
|
2026-01-16 11:48:49 -05:00
|
|
|
End: yylex.(*parser).lastClosing,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-01-08 06:04:47 -05:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
function_call_body: LEFT_PAREN function_call_args RIGHT_PAREN
|
|
|
|
|
{ $$ = $2 }
|
|
|
|
|
| LEFT_PAREN RIGHT_PAREN
|
|
|
|
|
{$$ = Expressions{}}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
function_call_args: function_call_args COMMA expr
|
|
|
|
|
{ $$ = append($1.(Expressions), $3.(Expr)) }
|
2020-01-17 10:16:58 -05:00
|
|
|
| expr
|
2020-01-08 06:04:47 -05:00
|
|
|
{ $$ = Expressions{$1.(Expr)} }
|
2020-01-16 10:20:20 -05:00
|
|
|
| function_call_args COMMA
|
|
|
|
|
{
|
2020-01-17 10:16:58 -05:00
|
|
|
yylex.(*parser).addParseErrf($2.PositionRange(), "trailing commas not allowed in function call args")
|
2020-01-16 10:20:20 -05:00
|
|
|
$$ = $1
|
|
|
|
|
}
|
2020-01-08 06:04:47 -05:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Expressions inside parentheses.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
paren_expr : LEFT_PAREN expr RIGHT_PAREN
|
2025-08-05 04:48:08 -04:00
|
|
|
{ $$ = &ParenExpr{Expr: $2.(Expr), PosRange: mergeRanges(&$1, &$3)} }
|
2020-01-08 06:04:47 -05:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Offset modifiers.
|
|
|
|
|
*/
|
|
|
|
|
|
2025-03-20 08:15:20 -04:00
|
|
|
positive_duration_expr : duration_expr
|
2020-01-08 06:04:47 -05:00
|
|
|
{
|
2025-03-27 09:39:23 -04:00
|
|
|
if numLit, ok := $1.(*NumberLiteral); ok {
|
|
|
|
|
if numLit.Val <= 0 {
|
|
|
|
|
yylex.(*parser).addParseErrf(numLit.PositionRange(), "duration must be greater than 0")
|
|
|
|
|
$$ = &NumberLiteral{Val: 0} // Return 0 on error.
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
$$ = $1
|
|
|
|
|
break
|
2025-03-20 08:15:20 -04:00
|
|
|
}
|
2025-03-27 09:39:23 -04:00
|
|
|
$$ = $1
|
2025-03-20 08:15:20 -04:00
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2025-06-10 10:43:27 -04:00
|
|
|
offset_expr: expr OFFSET offset_duration_expr
|
2025-03-20 08:15:20 -04:00
|
|
|
{
|
2025-03-27 09:39:23 -04:00
|
|
|
if numLit, ok := $3.(*NumberLiteral); ok {
|
2025-04-24 02:34:56 -04:00
|
|
|
yylex.(*parser).addOffset($1, time.Duration(math.Round(numLit.Val*float64(time.Second))))
|
2024-03-04 08:57:28 -05:00
|
|
|
$$ = $1
|
2025-03-27 09:39:23 -04:00
|
|
|
break
|
2021-02-14 20:53:44 -05:00
|
|
|
}
|
2025-03-27 09:39:23 -04:00
|
|
|
yylex.(*parser).addOffsetExpr($1, $3.(*DurationExpr))
|
|
|
|
|
$$ = $1
|
2020-01-08 06:04:47 -05:00
|
|
|
}
|
|
|
|
|
| expr OFFSET error
|
2025-12-10 10:16:08 -05:00
|
|
|
{ yylex.(*parser).unexpected("offset", "number, duration, step(), or range()"); $$ = $1 }
|
2020-01-08 06:04:47 -05:00
|
|
|
;
|
2025-03-20 08:15:20 -04:00
|
|
|
|
2025-09-25 05:34:59 -04:00
|
|
|
/*
|
|
|
|
|
* Anchored and smoothed modifiers
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
anchored_expr: expr ANCHORED
|
|
|
|
|
{
|
|
|
|
|
yylex.(*parser).setAnchored($1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
smoothed_expr: expr SMOOTHED
|
|
|
|
|
{
|
|
|
|
|
yylex.(*parser).setSmoothed($1)
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-20 05:57:39 -05:00
|
|
|
/*
|
|
|
|
|
* @ modifiers.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
step_invariant_expr: expr AT signed_or_unsigned_number
|
|
|
|
|
{
|
|
|
|
|
yylex.(*parser).setTimestamp($1, $3)
|
|
|
|
|
$$ = $1
|
|
|
|
|
}
|
2021-02-09 11:03:16 -05:00
|
|
|
| expr AT at_modifier_preprocessors LEFT_PAREN RIGHT_PAREN
|
|
|
|
|
{
|
|
|
|
|
yylex.(*parser).setAtModifierPreprocessor($1, $3)
|
|
|
|
|
$$ = $1
|
|
|
|
|
}
|
2021-01-20 05:57:39 -05:00
|
|
|
| expr AT error
|
|
|
|
|
{ yylex.(*parser).unexpected("@", "timestamp"); $$ = $1 }
|
|
|
|
|
;
|
2020-01-08 06:04:47 -05:00
|
|
|
|
2021-02-09 11:03:16 -05:00
|
|
|
at_modifier_preprocessors: START | END;
|
|
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
/*
|
|
|
|
|
* Subquery and range selectors.
|
|
|
|
|
*/
|
|
|
|
|
|
2025-03-20 08:15:20 -04:00
|
|
|
matrix_selector : expr LEFT_BRACKET positive_duration_expr RIGHT_BRACKET
|
2020-01-08 06:04:47 -05:00
|
|
|
{
|
2020-01-15 15:01:49 -05:00
|
|
|
var errMsg string
|
2020-01-08 06:04:47 -05:00
|
|
|
vs, ok := $1.(*VectorSelector)
|
|
|
|
|
if !ok{
|
2020-01-15 15:01:49 -05:00
|
|
|
errMsg = "ranges only allowed for vector selectors"
|
2021-01-20 05:57:39 -05:00
|
|
|
} else if vs.OriginalOffset != 0{
|
2020-01-15 15:01:49 -05:00
|
|
|
errMsg = "no offset modifiers allowed before range"
|
2021-01-20 05:57:39 -05:00
|
|
|
} else if vs.Timestamp != nil {
|
|
|
|
|
errMsg = "no @ modifiers allowed before range"
|
2020-01-08 06:04:47 -05:00
|
|
|
}
|
2020-01-15 15:01:49 -05:00
|
|
|
|
|
|
|
|
if errMsg != ""{
|
|
|
|
|
errRange := mergeRanges(&$2, &$4)
|
2025-01-18 07:21:51 -05:00
|
|
|
yylex.(*parser).addParseErrf(errRange, "%s", errMsg)
|
2020-01-08 06:04:47 -05:00
|
|
|
}
|
2020-01-15 15:01:49 -05:00
|
|
|
|
2025-03-27 09:39:23 -04:00
|
|
|
var rangeNl time.Duration
|
|
|
|
|
if numLit, ok := $3.(*NumberLiteral); ok {
|
2025-04-24 02:34:56 -04:00
|
|
|
rangeNl = time.Duration(math.Round(numLit.Val*float64(time.Second)))
|
2025-03-27 09:39:23 -04:00
|
|
|
}
|
|
|
|
|
rangeExpr, _ := $3.(*DurationExpr)
|
2020-01-08 06:04:47 -05:00
|
|
|
$$ = &MatrixSelector{
|
2020-01-17 10:16:58 -05:00
|
|
|
VectorSelector: $1.(Expr),
|
2025-03-27 09:39:23 -04:00
|
|
|
Range: rangeNl,
|
|
|
|
|
RangeExpr: rangeExpr,
|
2020-01-14 11:12:15 -05:00
|
|
|
EndPos: yylex.(*parser).lastClosing,
|
2020-01-08 06:04:47 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2025-03-20 08:15:20 -04:00
|
|
|
subquery_expr : expr LEFT_BRACKET positive_duration_expr COLON positive_duration_expr RIGHT_BRACKET
|
2020-01-08 06:04:47 -05:00
|
|
|
{
|
2025-03-27 09:39:23 -04:00
|
|
|
var rangeNl time.Duration
|
|
|
|
|
var stepNl time.Duration
|
|
|
|
|
if numLit, ok := $3.(*NumberLiteral); ok {
|
2025-04-24 02:34:56 -04:00
|
|
|
rangeNl = time.Duration(math.Round(numLit.Val*float64(time.Second)))
|
2025-03-27 09:39:23 -04:00
|
|
|
}
|
|
|
|
|
rangeExpr, _ := $3.(*DurationExpr)
|
|
|
|
|
if numLit, ok := $5.(*NumberLiteral); ok {
|
2025-04-24 02:34:56 -04:00
|
|
|
stepNl = time.Duration(math.Round(numLit.Val*float64(time.Second)))
|
2025-03-27 09:39:23 -04:00
|
|
|
}
|
|
|
|
|
stepExpr, _ := $5.(*DurationExpr)
|
2020-01-08 06:04:47 -05:00
|
|
|
$$ = &SubqueryExpr{
|
|
|
|
|
Expr: $1.(Expr),
|
2025-03-27 09:39:23 -04:00
|
|
|
Range: rangeNl,
|
|
|
|
|
RangeExpr: rangeExpr,
|
|
|
|
|
Step: stepNl,
|
|
|
|
|
StepExpr: stepExpr,
|
2020-01-14 11:12:15 -05:00
|
|
|
EndPos: $6.Pos + 1,
|
2020-01-08 06:04:47 -05:00
|
|
|
}
|
|
|
|
|
}
|
2025-03-20 08:15:20 -04:00
|
|
|
| expr LEFT_BRACKET positive_duration_expr COLON RIGHT_BRACKET
|
2025-03-27 09:39:23 -04:00
|
|
|
{
|
|
|
|
|
var rangeNl time.Duration
|
|
|
|
|
if numLit, ok := $3.(*NumberLiteral); ok {
|
2025-04-24 02:34:56 -04:00
|
|
|
rangeNl = time.Duration(math.Round(numLit.Val*float64(time.Second)))
|
2025-03-27 09:39:23 -04:00
|
|
|
}
|
|
|
|
|
rangeExpr, _ := $3.(*DurationExpr)
|
|
|
|
|
$$ = &SubqueryExpr{
|
|
|
|
|
Expr: $1.(Expr),
|
|
|
|
|
Range: rangeNl,
|
|
|
|
|
RangeExpr: rangeExpr,
|
|
|
|
|
EndPos: $5.Pos + 1,
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-03-20 08:15:20 -04:00
|
|
|
| expr LEFT_BRACKET positive_duration_expr COLON positive_duration_expr error
|
2020-01-16 10:20:20 -05:00
|
|
|
{ yylex.(*parser).unexpected("subquery selector", "\"]\""); $$ = $1 }
|
2025-03-20 08:15:20 -04:00
|
|
|
| expr LEFT_BRACKET positive_duration_expr COLON error
|
2025-12-10 10:16:08 -05:00
|
|
|
{ yylex.(*parser).unexpected("subquery selector", "number, duration, step(), range(), or \"]\""); $$ = $1 }
|
2025-03-20 08:15:20 -04:00
|
|
|
| expr LEFT_BRACKET positive_duration_expr error
|
2020-01-16 10:20:20 -05:00
|
|
|
{ yylex.(*parser).unexpected("subquery or range", "\":\" or \"]\""); $$ = $1 }
|
2020-01-08 06:04:47 -05:00
|
|
|
| expr LEFT_BRACKET error
|
2025-12-10 10:16:08 -05:00
|
|
|
{ yylex.(*parser).unexpected("subquery or range selector", "number, duration, step(), or range()"); $$ = $1 }
|
2020-01-08 06:04:47 -05:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Unary expressions.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
unary_expr :
|
2023-08-25 17:35:42 -04:00
|
|
|
/* Gives the rule the same precedence as MUL. This aligns with mathematical conventions. */
|
2020-01-17 10:16:58 -05:00
|
|
|
unary_op expr %prec MUL
|
2020-01-08 06:04:47 -05:00
|
|
|
{
|
|
|
|
|
if nl, ok := $2.(*NumberLiteral); ok {
|
|
|
|
|
if $1.Typ == SUB {
|
|
|
|
|
nl.Val *= -1
|
|
|
|
|
}
|
2020-01-14 11:12:15 -05:00
|
|
|
nl.PosRange.Start = $1.Pos
|
2020-01-08 06:04:47 -05:00
|
|
|
$$ = nl
|
|
|
|
|
} else {
|
2020-01-14 11:12:15 -05:00
|
|
|
$$ = &UnaryExpr{Op: $1.Typ, Expr: $2.(Expr), StartPos: $1.Pos}
|
2020-01-08 06:04:47 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Vector selectors.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
vector_selector: metric_identifier label_matchers
|
2020-01-17 10:16:58 -05:00
|
|
|
{
|
2020-01-14 11:12:15 -05:00
|
|
|
vs := $2.(*VectorSelector)
|
2020-01-17 10:16:58 -05:00
|
|
|
vs.PosRange = mergeRanges(&$1, vs)
|
2020-01-14 11:12:15 -05:00
|
|
|
vs.Name = $1.Val
|
|
|
|
|
yylex.(*parser).assembleVectorSelector(vs)
|
|
|
|
|
$$ = vs
|
|
|
|
|
}
|
2020-01-17 10:16:58 -05:00
|
|
|
| metric_identifier
|
|
|
|
|
{
|
2020-01-14 11:12:15 -05:00
|
|
|
vs := &VectorSelector{
|
|
|
|
|
Name: $1.Val,
|
|
|
|
|
LabelMatchers: []*labels.Matcher{},
|
|
|
|
|
PosRange: $1.PositionRange(),
|
|
|
|
|
}
|
|
|
|
|
yylex.(*parser).assembleVectorSelector(vs)
|
|
|
|
|
$$ = vs
|
|
|
|
|
}
|
2020-01-08 06:04:47 -05:00
|
|
|
| label_matchers
|
2020-01-17 10:16:58 -05:00
|
|
|
{
|
2020-01-14 11:12:15 -05:00
|
|
|
vs := $1.(*VectorSelector)
|
|
|
|
|
yylex.(*parser).assembleVectorSelector(vs)
|
|
|
|
|
$$ = vs
|
|
|
|
|
}
|
2020-01-08 06:04:47 -05:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
label_matchers : LEFT_BRACE label_match_list RIGHT_BRACE
|
2020-01-14 11:12:15 -05:00
|
|
|
{
|
|
|
|
|
$$ = &VectorSelector{
|
|
|
|
|
LabelMatchers: $2,
|
|
|
|
|
PosRange: mergeRanges(&$1, &$3),
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-12-16 08:58:47 -05:00
|
|
|
| LEFT_BRACE label_match_list COMMA RIGHT_BRACE
|
2020-01-14 11:12:15 -05:00
|
|
|
{
|
|
|
|
|
$$ = &VectorSelector{
|
|
|
|
|
LabelMatchers: $2,
|
|
|
|
|
PosRange: mergeRanges(&$1, &$4),
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-12-05 11:16:12 -05:00
|
|
|
| LEFT_BRACE RIGHT_BRACE
|
2020-01-14 11:12:15 -05:00
|
|
|
{
|
|
|
|
|
$$ = &VectorSelector{
|
|
|
|
|
LabelMatchers: []*labels.Matcher{},
|
|
|
|
|
PosRange: mergeRanges(&$1, &$2),
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-12-05 11:16:12 -05:00
|
|
|
;
|
|
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
label_match_list: label_match_list COMMA label_matcher
|
2020-01-17 10:16:58 -05:00
|
|
|
{
|
2020-01-16 10:20:20 -05:00
|
|
|
if $1 != nil{
|
|
|
|
|
$$ = append($1, $3)
|
|
|
|
|
} else {
|
|
|
|
|
$$ = $1
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-12-16 08:58:47 -05:00
|
|
|
| label_matcher
|
|
|
|
|
{ $$ = []*labels.Matcher{$1}}
|
|
|
|
|
| label_match_list error
|
2020-01-16 10:20:20 -05:00
|
|
|
{ yylex.(*parser).unexpected("label matching", "\",\" or \"}\""); $$ = $1 }
|
2019-12-16 08:58:47 -05:00
|
|
|
;
|
|
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
label_matcher : IDENTIFIER match_op STRING
|
2024-02-15 14:25:12 -05:00
|
|
|
{ $$ = yylex.(*parser).newLabelMatcher($1, $2, $3); }
|
|
|
|
|
| string_identifier match_op STRING
|
|
|
|
|
{ $$ = yylex.(*parser).newLabelMatcher($1, $2, $3); }
|
|
|
|
|
| string_identifier
|
|
|
|
|
{ $$ = yylex.(*parser).newMetricNameMatcher($1); }
|
|
|
|
|
| string_identifier match_op error
|
|
|
|
|
{ yylex.(*parser).unexpected("label matching", "string"); $$ = nil}
|
2019-12-05 11:16:12 -05:00
|
|
|
| IDENTIFIER match_op error
|
2020-01-16 10:20:20 -05:00
|
|
|
{ yylex.(*parser).unexpected("label matching", "string"); $$ = nil}
|
2020-01-17 10:16:58 -05:00
|
|
|
| IDENTIFIER error
|
|
|
|
|
{ yylex.(*parser).unexpected("label matching", "label matching operator"); $$ = nil }
|
2019-12-16 08:58:47 -05:00
|
|
|
| error
|
2020-01-16 10:20:20 -05:00
|
|
|
{ yylex.(*parser).unexpected("label matching", "identifier or \"}\""); $$ = nil}
|
2019-12-05 11:16:12 -05:00
|
|
|
;
|
2020-01-17 10:16:58 -05:00
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
/*
|
|
|
|
|
* Metric descriptions.
|
|
|
|
|
*/
|
2019-12-05 11:16:12 -05:00
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
metric : metric_identifier label_set
|
2023-03-22 11:46:02 -04:00
|
|
|
{ b := labels.NewBuilder($2); b.Set(labels.MetricName, $1.Val); $$ = b.Labels() }
|
2020-01-17 10:16:58 -05:00
|
|
|
| label_set
|
2019-12-16 11:38:18 -05:00
|
|
|
{$$ = $1}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
|
2026-05-19 05:41:16 -04:00
|
|
|
metric_identifier: AVG | BOTTOMK | BY | COUNT | COUNT_VALUES | FILL | FILL_LEFT | FILL_RIGHT | GROUP | IDENTIFIER | LAND | LOR | LUNLESS | MAX | METRIC_IDENTIFIER | MIN | OFFSET | QUANTILE | STDDEV | STDVAR | SUM | TOPK | WITHOUT | START | END | LIMITK | LIMIT_RATIO | STEP | RANGE | ANCHORED | SMOOTHED | MAX_OF | MIN_OF;
|
2020-01-08 06:04:47 -05:00
|
|
|
|
|
|
|
|
label_set : LEFT_BRACE label_set_list RIGHT_BRACE
|
2019-12-16 08:58:47 -05:00
|
|
|
{ $$ = labels.New($2...) }
|
|
|
|
|
| LEFT_BRACE label_set_list COMMA RIGHT_BRACE
|
|
|
|
|
{ $$ = labels.New($2...) }
|
|
|
|
|
| LEFT_BRACE RIGHT_BRACE
|
|
|
|
|
{ $$ = labels.New() }
|
2019-12-16 11:38:18 -05:00
|
|
|
| /* empty */
|
|
|
|
|
{ $$ = labels.New() }
|
2019-12-16 08:58:47 -05:00
|
|
|
;
|
|
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
label_set_list : label_set_list COMMA label_set_item
|
2019-12-16 08:58:47 -05:00
|
|
|
{ $$ = append($1, $3) }
|
|
|
|
|
| label_set_item
|
|
|
|
|
{ $$ = []labels.Label{$1} }
|
|
|
|
|
| label_set_list error
|
2020-01-16 10:20:20 -05:00
|
|
|
{ yylex.(*parser).unexpected("label set", "\",\" or \"}\"", ); $$ = $1 }
|
2020-01-17 10:16:58 -05:00
|
|
|
|
2019-12-16 08:58:47 -05:00
|
|
|
;
|
|
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
label_set_item : IDENTIFIER EQL STRING
|
2020-01-17 10:16:58 -05:00
|
|
|
{ $$ = labels.Label{Name: $1.Val, Value: yylex.(*parser).unquoteString($3.Val) } }
|
2024-09-19 14:34:28 -04:00
|
|
|
| string_identifier EQL STRING
|
|
|
|
|
{ $$ = labels.Label{Name: $1.Val, Value: yylex.(*parser).unquoteString($3.Val) } }
|
2024-12-03 12:33:10 -05:00
|
|
|
| string_identifier
|
|
|
|
|
{ $$ = labels.Label{Name: labels.MetricName, Value: $1.Val} }
|
2019-12-16 08:58:47 -05:00
|
|
|
| IDENTIFIER EQL error
|
2020-01-16 10:20:20 -05:00
|
|
|
{ yylex.(*parser).unexpected("label set", "string"); $$ = labels.Label{}}
|
2024-09-19 14:34:28 -04:00
|
|
|
| string_identifier EQL error
|
|
|
|
|
{ yylex.(*parser).unexpected("label set", "string"); $$ = labels.Label{}}
|
2019-12-16 08:58:47 -05:00
|
|
|
| IDENTIFIER error
|
2020-01-16 10:20:20 -05:00
|
|
|
{ yylex.(*parser).unexpected("label set", "\"=\""); $$ = labels.Label{}}
|
2019-12-16 08:58:47 -05:00
|
|
|
| error
|
2020-01-16 10:20:20 -05:00
|
|
|
{ yylex.(*parser).unexpected("label set", "identifier or \"}\""); $$ = labels.Label{} }
|
2019-12-16 08:58:47 -05:00
|
|
|
;
|
|
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
/*
|
2023-08-25 17:35:42 -04:00
|
|
|
* Series descriptions:
|
|
|
|
|
* A separate language that is used to generate series values promtool.
|
|
|
|
|
* It is included in the promQL parser, because it shares common functionality, such as parsing a metric.
|
|
|
|
|
* The syntax is described in https://prometheus.io/docs/prometheus/latest/configuration/unit_testing_rules/#series
|
2020-01-08 06:04:47 -05:00
|
|
|
*/
|
2019-12-18 09:18:52 -05:00
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
series_description: metric series_values
|
2019-12-21 03:44:12 -05:00
|
|
|
{
|
|
|
|
|
yylex.(*parser).generatedParserResult = &seriesDescription{
|
|
|
|
|
labels: $1,
|
|
|
|
|
values: $2,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
series_values : /*empty*/
|
2020-02-03 12:48:27 -05:00
|
|
|
{ $$ = []SequenceValue{} }
|
2019-12-21 03:44:12 -05:00
|
|
|
| series_values SPACE series_item
|
|
|
|
|
{ $$ = append($1, $3...) }
|
|
|
|
|
| series_values SPACE
|
|
|
|
|
{ $$ = $1 }
|
|
|
|
|
| error
|
2020-01-16 10:20:20 -05:00
|
|
|
{ yylex.(*parser).unexpected("series values", ""); $$ = nil }
|
2019-12-21 03:44:12 -05:00
|
|
|
;
|
|
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
series_item : BLANK
|
2020-02-03 12:48:27 -05:00
|
|
|
{ $$ = []SequenceValue{{Omitted: true}}}
|
2019-12-21 03:44:12 -05:00
|
|
|
| BLANK TIMES uint
|
|
|
|
|
{
|
2020-02-03 12:48:27 -05:00
|
|
|
$$ = []SequenceValue{}
|
2019-12-21 03:44:12 -05:00
|
|
|
for i:=uint64(0); i < $3; i++{
|
2020-02-03 12:48:27 -05:00
|
|
|
$$ = append($$, SequenceValue{Omitted: true})
|
2019-12-21 03:44:12 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
| series_value
|
2020-02-03 12:48:27 -05:00
|
|
|
{ $$ = []SequenceValue{{Value: $1}}}
|
2019-12-21 03:44:12 -05:00
|
|
|
| series_value TIMES uint
|
|
|
|
|
{
|
2020-02-03 12:48:27 -05:00
|
|
|
$$ = []SequenceValue{}
|
2023-08-25 17:35:42 -04:00
|
|
|
// Add an additional value for time 0, which we ignore in tests.
|
2019-12-21 03:44:12 -05:00
|
|
|
for i:=uint64(0); i <= $3; i++{
|
2020-02-03 12:48:27 -05:00
|
|
|
$$ = append($$, SequenceValue{Value: $1})
|
2019-12-21 03:44:12 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
| series_value signed_number TIMES uint
|
|
|
|
|
{
|
2020-02-03 12:48:27 -05:00
|
|
|
$$ = []SequenceValue{}
|
2023-08-25 17:35:42 -04:00
|
|
|
// Add an additional value for time 0, which we ignore in tests.
|
2019-12-21 03:44:12 -05:00
|
|
|
for i:=uint64(0); i <= $4; i++{
|
2020-02-03 12:48:27 -05:00
|
|
|
$$ = append($$, SequenceValue{Value: $1})
|
2019-12-21 03:44:12 -05:00
|
|
|
$1 += $2
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-25 17:35:42 -04:00
|
|
|
// Histogram descriptions (part of unit testing).
|
|
|
|
|
| histogram_series_value
|
|
|
|
|
{
|
2025-12-19 13:02:08 -05:00
|
|
|
$$ = []SequenceValue{yylex.(*parser).newHistogramSequenceValue($1)}
|
2023-08-25 17:35:42 -04:00
|
|
|
}
|
|
|
|
|
| histogram_series_value TIMES uint
|
|
|
|
|
{
|
|
|
|
|
$$ = []SequenceValue{}
|
|
|
|
|
// Add an additional value for time 0, which we ignore in tests.
|
2025-12-19 13:02:08 -05:00
|
|
|
sv := yylex.(*parser).newHistogramSequenceValue($1)
|
2023-08-25 17:35:42 -04:00
|
|
|
for i:=uint64(0); i <= $3; i++{
|
2025-12-19 13:02:08 -05:00
|
|
|
$$ = append($$, sv)
|
2023-08-25 17:35:42 -04:00
|
|
|
//$1 += $2
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
| histogram_series_value ADD histogram_series_value TIMES uint
|
|
|
|
|
{
|
|
|
|
|
val, err := yylex.(*parser).histogramsIncreaseSeries($1,$3,$5)
|
|
|
|
|
if err != nil {
|
|
|
|
|
yylex.(*parser).addSemanticError(err)
|
|
|
|
|
}
|
|
|
|
|
$$ = val
|
|
|
|
|
}
|
|
|
|
|
| histogram_series_value SUB histogram_series_value TIMES uint
|
|
|
|
|
{
|
|
|
|
|
val, err := yylex.(*parser).histogramsDecreaseSeries($1,$3,$5)
|
|
|
|
|
if err != nil {
|
|
|
|
|
yylex.(*parser).addSemanticError(err)
|
|
|
|
|
}
|
|
|
|
|
$$ = val
|
|
|
|
|
}
|
2020-01-08 06:04:47 -05:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
series_value : IDENTIFIER
|
|
|
|
|
{
|
|
|
|
|
if $1.Val != "stale" {
|
|
|
|
|
yylex.(*parser).unexpected("series values", "number or \"stale\"")
|
|
|
|
|
}
|
|
|
|
|
$$ = math.Float64frombits(value.StaleNaN)
|
|
|
|
|
}
|
|
|
|
|
| number
|
|
|
|
|
| signed_number
|
|
|
|
|
;
|
|
|
|
|
|
2023-08-25 17:35:42 -04:00
|
|
|
histogram_series_value
|
|
|
|
|
: OPEN_HIST histogram_desc_map SPACE CLOSE_HIST
|
|
|
|
|
{
|
|
|
|
|
$$ = yylex.(*parser).buildHistogramFromMap(&$2)
|
|
|
|
|
}
|
|
|
|
|
| OPEN_HIST histogram_desc_map CLOSE_HIST
|
|
|
|
|
{
|
|
|
|
|
$$ = yylex.(*parser).buildHistogramFromMap(&$2)
|
|
|
|
|
}
|
|
|
|
|
| OPEN_HIST SPACE CLOSE_HIST
|
|
|
|
|
{
|
|
|
|
|
m := yylex.(*parser).newMap()
|
|
|
|
|
$$ = yylex.(*parser).buildHistogramFromMap(&m)
|
|
|
|
|
}
|
|
|
|
|
| OPEN_HIST CLOSE_HIST
|
|
|
|
|
{
|
|
|
|
|
m := yylex.(*parser).newMap()
|
|
|
|
|
$$ = yylex.(*parser).buildHistogramFromMap(&m)
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
histogram_desc_map
|
|
|
|
|
: histogram_desc_map SPACE histogram_desc_item
|
|
|
|
|
{
|
|
|
|
|
$$ = *(yylex.(*parser).mergeMaps(&$1,&$3))
|
|
|
|
|
}
|
|
|
|
|
| histogram_desc_item
|
|
|
|
|
{
|
|
|
|
|
$$ = $1
|
|
|
|
|
}
|
|
|
|
|
| histogram_desc_map error {
|
|
|
|
|
yylex.(*parser).unexpected("histogram description", "histogram description key, e.g. buckets:[5 10 7]")
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
histogram_desc_item
|
|
|
|
|
: SCHEMA_DESC COLON int
|
|
|
|
|
{
|
|
|
|
|
$$ = yylex.(*parser).newMap()
|
|
|
|
|
$$["schema"] = $3
|
|
|
|
|
}
|
|
|
|
|
| SUM_DESC COLON signed_or_unsigned_number
|
|
|
|
|
{
|
|
|
|
|
$$ = yylex.(*parser).newMap()
|
|
|
|
|
$$["sum"] = $3
|
|
|
|
|
}
|
2024-09-09 00:29:29 -04:00
|
|
|
| COUNT_DESC COLON signed_or_unsigned_number
|
2023-08-25 17:35:42 -04:00
|
|
|
{
|
|
|
|
|
$$ = yylex.(*parser).newMap()
|
|
|
|
|
$$["count"] = $3
|
|
|
|
|
}
|
2024-09-09 00:29:29 -04:00
|
|
|
| ZERO_BUCKET_DESC COLON signed_or_unsigned_number
|
2023-08-25 17:35:42 -04:00
|
|
|
{
|
|
|
|
|
$$ = yylex.(*parser).newMap()
|
|
|
|
|
$$["z_bucket"] = $3
|
|
|
|
|
}
|
|
|
|
|
| ZERO_BUCKET_WIDTH_DESC COLON number
|
|
|
|
|
{
|
|
|
|
|
$$ = yylex.(*parser).newMap()
|
|
|
|
|
$$["z_bucket_w"] = $3
|
|
|
|
|
}
|
2024-05-08 07:58:24 -04:00
|
|
|
| CUSTOM_VALUES_DESC COLON bucket_set
|
|
|
|
|
{
|
|
|
|
|
$$ = yylex.(*parser).newMap()
|
|
|
|
|
$$["custom_values"] = $3
|
|
|
|
|
}
|
2023-08-25 17:35:42 -04:00
|
|
|
| BUCKETS_DESC COLON bucket_set
|
|
|
|
|
{
|
|
|
|
|
$$ = yylex.(*parser).newMap()
|
|
|
|
|
$$["buckets"] = $3
|
|
|
|
|
}
|
|
|
|
|
| OFFSET_DESC COLON int
|
|
|
|
|
{
|
|
|
|
|
$$ = yylex.(*parser).newMap()
|
|
|
|
|
$$["offset"] = $3
|
|
|
|
|
}
|
|
|
|
|
| NEGATIVE_BUCKETS_DESC COLON bucket_set
|
|
|
|
|
{
|
|
|
|
|
$$ = yylex.(*parser).newMap()
|
|
|
|
|
$$["n_buckets"] = $3
|
|
|
|
|
}
|
|
|
|
|
| NEGATIVE_OFFSET_DESC COLON int
|
|
|
|
|
{
|
|
|
|
|
$$ = yylex.(*parser).newMap()
|
|
|
|
|
$$["n_offset"] = $3
|
|
|
|
|
}
|
2024-07-31 03:53:05 -04:00
|
|
|
| COUNTER_RESET_HINT_DESC COLON counter_reset_hint
|
|
|
|
|
{
|
|
|
|
|
$$ = yylex.(*parser).newMap()
|
|
|
|
|
$$["counter_reset_hint"] = $3
|
|
|
|
|
}
|
2023-08-25 17:35:42 -04:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
bucket_set : LEFT_BRACKET bucket_set_list SPACE RIGHT_BRACKET
|
|
|
|
|
{
|
|
|
|
|
$$ = $2
|
|
|
|
|
}
|
|
|
|
|
| LEFT_BRACKET bucket_set_list RIGHT_BRACKET
|
|
|
|
|
{
|
|
|
|
|
$$ = $2
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2024-09-09 00:29:29 -04:00
|
|
|
bucket_set_list : bucket_set_list SPACE signed_or_unsigned_number
|
2023-08-25 17:35:42 -04:00
|
|
|
{
|
|
|
|
|
$$ = append($1, $3)
|
|
|
|
|
}
|
2024-09-09 00:29:29 -04:00
|
|
|
| signed_or_unsigned_number
|
2023-08-25 17:35:42 -04:00
|
|
|
{
|
|
|
|
|
$$ = []float64{$1}
|
|
|
|
|
}
|
|
|
|
|
| bucket_set_list error
|
|
|
|
|
;
|
2020-01-08 06:04:47 -05:00
|
|
|
|
2024-07-31 03:53:05 -04:00
|
|
|
counter_reset_hint : UNKNOWN_COUNTER_RESET | COUNTER_RESET | NOT_COUNTER_RESET | GAUGE_TYPE;
|
2020-01-08 06:04:47 -05:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Keyword lists.
|
|
|
|
|
*/
|
|
|
|
|
|
feat: add limitk() and limit_ratio() operators (#12503)
* rebase 2024-07-01, picks previous renaming to `limitk()` and `limit_ratio()`
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* gofumpt -d -extra
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* more lint fixes
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* more lint fixes+
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* put limitk() and limit_ratio() behind --enable-feature=promql-experimental-functions
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* EnableExperimentalFunctions for TestConcurrentRangeQueries() also
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* use testutil.RequireEqual to fix tests, WIP equivalent thingie for require.Contains
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* lint fix
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* moar linting
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* rebase 2024-06-19
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* re-add limit(2, metric) testing for N=2 common series subset
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* move `ratio = param` to default switch case, for better readability
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* gofumpt -d -extra util/testutil/cmp.go
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* early break when reaching k elems in limitk(), should have always been so (!)
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* small typo fix
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* no-change small break-loop rearrange for readability
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* remove IsNan(ratio) condition in switch-case, already handled as input validation
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* no-change adding some comments
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* no-change simplify fullMatrix() helper functions used for tests
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* add `limitk(-1, metric)` testcase, which is handled as any k < 1 case
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* engine_test.go: no-change create `requireCommonSeries() helper func (moving code into it) for readability
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* rebase 2024-06-21
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* engine_test.go: HAPPY NOW about its code -> reorg, create and use simpleRangeQuery() function, less lines and more readable ftW \o/
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* move limitk(), limit_ratio() testing to promql/promqltest/testdata/limit.test
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* remove stale leftover after moving tests from engine_test.go to testdata/
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* fix flaky `limit_ratio(0.5, ...)` test case
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* Update promql/engine.go
Co-authored-by: Julius Volz <julius.volz@gmail.com>
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* Update promql/engine.go
Co-authored-by: Julius Volz <julius.volz@gmail.com>
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* Update promql/engine.go
Co-authored-by: Julius Volz <julius.volz@gmail.com>
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* fix AddRatioSample() implementation to use a single conditional (instead of switch/case + fallback return)
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* docs/querying/operators.md: document r < 0
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* add negative limit_ratio() example to docs/querying/examples.md
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* move more extensive docu examples to docs/querying/operators.md
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* typo
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* small docu fix for poor-mans-normality-check, add it to limit.test ;)
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* limit.test: expand "Poor man's normality check" to whole eval range
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* restore mistakenly removed existing small comment
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* expand poors-man-normality-check case(s)
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* Revert "expand poors-man-normality-check case(s)"
This reverts commit f69e1603b2ebe69c0a100197cfbcf6f81644b564, indeed too
flaky 0:)
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* remove humor from docs/querying/operators.md
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* fix signoff
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* add web/ui missing changes
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* expand limit_ratio test cases, cross-fingering they'll not be flaky
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* remove flaky test
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* add missing warnings.Merge(ws) in instant-query return shortcut
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* add missing LimitK||LimitRatio case to codemirror-promql/src/parser/parser.ts
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* fix ui-lint
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
* actually fix returned warnings :]
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
---------
Signed-off-by: JuanJo Ciarlante <juanjosec@gmail.com>
Co-authored-by: Julius Volz <julius.volz@gmail.com>
2024-07-03 16:18:57 -04:00
|
|
|
aggregate_op : AVG | BOTTOMK | COUNT | COUNT_VALUES | GROUP | MAX | MIN | QUANTILE | STDDEV | STDVAR | SUM | TOPK | LIMITK | LIMIT_RATIO;
|
2020-01-08 06:04:47 -05:00
|
|
|
|
2023-08-25 17:35:42 -04:00
|
|
|
// Inside of grouping options label names can be recognized as keywords by the lexer. This is a list of keywords that could also be a label name.
|
2026-05-19 05:41:16 -04:00
|
|
|
maybe_label : AVG | BOOL | BOTTOMK | BY | COUNT | COUNT_VALUES | GROUP | GROUP_LEFT | GROUP_RIGHT | FILL | FILL_LEFT | FILL_RIGHT | IDENTIFIER | IGNORING | LAND | LOR | LUNLESS | MAX | METRIC_IDENTIFIER | MIN | OFFSET | ON | QUANTILE | STDDEV | STDVAR | SUM | TOPK | START | END | ATAN2 | LIMITK | LIMIT_RATIO | STEP | RANGE | ANCHORED | SMOOTHED | MAX_OF | MIN_OF;
|
2020-01-08 06:04:47 -05:00
|
|
|
|
|
|
|
|
unary_op : ADD | SUB;
|
|
|
|
|
|
|
|
|
|
match_op : EQL | NEQ | EQL_REGEX | NEQ_REGEX ;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Literals.
|
|
|
|
|
*/
|
|
|
|
|
|
2024-03-04 08:57:28 -05:00
|
|
|
number_duration_literal : NUMBER
|
2020-01-14 11:12:15 -05:00
|
|
|
{
|
2024-03-04 08:57:28 -05:00
|
|
|
$$ = &NumberLiteral{
|
2020-01-14 11:12:15 -05:00
|
|
|
Val: yylex.(*parser).number($1.Val),
|
|
|
|
|
PosRange: $1.PositionRange(),
|
2024-03-04 08:57:28 -05:00
|
|
|
}
|
2020-01-14 11:12:15 -05:00
|
|
|
}
|
2024-03-04 08:57:28 -05:00
|
|
|
| DURATION
|
|
|
|
|
{
|
|
|
|
|
var err error
|
|
|
|
|
var dur time.Duration
|
|
|
|
|
dur, err = parseDuration($1.Val)
|
|
|
|
|
if err != nil {
|
|
|
|
|
yylex.(*parser).addParseErr($1.PositionRange(), err)
|
|
|
|
|
}
|
|
|
|
|
$$ = &NumberLiteral{
|
|
|
|
|
Val: dur.Seconds(),
|
|
|
|
|
PosRange: $1.PositionRange(),
|
2025-03-27 09:39:23 -04:00
|
|
|
Duration: true,
|
2024-03-04 08:57:28 -05:00
|
|
|
}
|
2020-01-14 11:12:15 -05:00
|
|
|
}
|
|
|
|
|
;
|
2020-01-08 06:04:47 -05:00
|
|
|
|
2024-03-14 14:48:51 -04:00
|
|
|
number : NUMBER
|
|
|
|
|
{
|
|
|
|
|
$$ = yylex.(*parser).number($1.Val)
|
|
|
|
|
}
|
|
|
|
|
| DURATION
|
|
|
|
|
{
|
|
|
|
|
var err error
|
|
|
|
|
var dur time.Duration
|
|
|
|
|
dur, err = parseDuration($1.Val)
|
|
|
|
|
if err != nil {
|
|
|
|
|
yylex.(*parser).addParseErr($1.PositionRange(), err)
|
|
|
|
|
}
|
|
|
|
|
$$ = dur.Seconds()
|
|
|
|
|
}
|
|
|
|
|
;
|
2020-01-08 06:04:47 -05:00
|
|
|
|
|
|
|
|
signed_number : ADD number { $$ = $2 }
|
|
|
|
|
| SUB number { $$ = -$2 }
|
|
|
|
|
;
|
|
|
|
|
|
2021-01-20 05:57:39 -05:00
|
|
|
signed_or_unsigned_number: number | signed_number ;
|
|
|
|
|
|
2020-01-08 06:04:47 -05:00
|
|
|
uint : NUMBER
|
2019-12-21 03:44:12 -05:00
|
|
|
{
|
|
|
|
|
var err error
|
|
|
|
|
$$, err = strconv.ParseUint($1.Val, 10, 64)
|
|
|
|
|
if err != nil {
|
2020-01-17 10:16:58 -05:00
|
|
|
yylex.(*parser).addParseErrf($1.PositionRange(), "invalid repetition in series values: %s", err)
|
2019-12-21 03:44:12 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
|
2023-08-25 17:35:42 -04:00
|
|
|
int : SUB uint { $$ = -int64($2) }
|
|
|
|
|
| uint { $$ = int64($1) }
|
|
|
|
|
;
|
|
|
|
|
|
2020-01-14 11:12:15 -05:00
|
|
|
string_literal : STRING
|
|
|
|
|
{
|
|
|
|
|
$$ = &StringLiteral{
|
|
|
|
|
Val: yylex.(*parser).unquoteString($1.Val),
|
|
|
|
|
PosRange: $1.PositionRange(),
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-15 14:25:12 -05:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
string_identifier : STRING
|
|
|
|
|
{
|
|
|
|
|
$$ = Item{
|
|
|
|
|
Typ: METRIC_IDENTIFIER,
|
|
|
|
|
Pos: $1.PositionRange().Start,
|
|
|
|
|
Val: yylex.(*parser).unquoteString($1.Val),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
;
|
2020-01-08 06:04:47 -05:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Wrappers for optional arguments.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
maybe_grouping_labels: /* empty */ { $$ = nil }
|
|
|
|
|
| grouping_labels
|
2019-12-21 03:44:12 -05:00
|
|
|
;
|
|
|
|
|
|
2025-03-20 08:15:20 -04:00
|
|
|
/*
|
|
|
|
|
* Duration expressions.
|
|
|
|
|
*/
|
|
|
|
|
|
2025-06-10 10:43:27 -04:00
|
|
|
// offset_duration_expr is needed to handle expressions like "foo offset -2^2" correctly.
|
|
|
|
|
// Without this rule, such expressions would be parsed as "foo offset (-2^2)" due to operator precedence.
|
|
|
|
|
// With this rule, they are parsed as "(foo offset -2)^2", which is the expected behavior without parentheses.
|
|
|
|
|
offset_duration_expr : number_duration_literal
|
|
|
|
|
{
|
|
|
|
|
nl := $1.(*NumberLiteral)
|
2026-05-22 11:29:46 -04:00
|
|
|
if durationLiteralOutOfRange(nl.Val) {
|
2025-06-10 10:43:27 -04:00
|
|
|
yylex.(*parser).addParseErrf(nl.PosRange, "duration out of range")
|
|
|
|
|
$$ = &NumberLiteral{Val: 0}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
$$ = nl
|
|
|
|
|
}
|
|
|
|
|
| unary_op number_duration_literal
|
|
|
|
|
{
|
|
|
|
|
nl := $2.(*NumberLiteral)
|
|
|
|
|
if $1.Typ == SUB {
|
|
|
|
|
nl.Val *= -1
|
|
|
|
|
}
|
2026-05-22 11:29:46 -04:00
|
|
|
if durationLiteralOutOfRange(nl.Val) {
|
2025-06-10 10:43:27 -04:00
|
|
|
yylex.(*parser).addParseErrf($1.PositionRange(), "duration out of range")
|
|
|
|
|
$$ = &NumberLiteral{Val: 0}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
nl.PosRange.Start = $1.Pos
|
|
|
|
|
$$ = nl
|
|
|
|
|
}
|
2025-06-25 11:39:27 -04:00
|
|
|
| STEP LEFT_PAREN RIGHT_PAREN
|
|
|
|
|
{
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
de := &DurationExpr{
|
|
|
|
|
Op: STEP,
|
2025-06-25 11:39:27 -04:00
|
|
|
StartPos: $1.PositionRange().Start,
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
EndPos: $3.PositionRange().End,
|
2025-06-25 11:39:27 -04:00
|
|
|
}
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
yylex.(*parser).experimentalDurationExpr(de)
|
|
|
|
|
$$ = de
|
2025-06-25 11:39:27 -04:00
|
|
|
}
|
2025-12-10 10:16:08 -05:00
|
|
|
| RANGE LEFT_PAREN RIGHT_PAREN
|
|
|
|
|
{
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
de := &DurationExpr{
|
|
|
|
|
Op: RANGE,
|
2025-12-10 10:16:08 -05:00
|
|
|
StartPos: $1.PositionRange().Start,
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
EndPos: $3.PositionRange().End,
|
2025-12-10 10:16:08 -05:00
|
|
|
}
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
yylex.(*parser).experimentalDurationExpr(de)
|
|
|
|
|
$$ = de
|
2025-12-10 10:16:08 -05:00
|
|
|
}
|
2025-06-25 11:39:27 -04:00
|
|
|
| unary_op STEP LEFT_PAREN RIGHT_PAREN
|
|
|
|
|
{
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
de := &DurationExpr{
|
2025-06-25 11:39:27 -04:00
|
|
|
Op: $1.Typ,
|
|
|
|
|
RHS: &DurationExpr{
|
|
|
|
|
Op: STEP,
|
|
|
|
|
StartPos: $2.PositionRange().Start,
|
|
|
|
|
EndPos: $4.PositionRange().End,
|
|
|
|
|
},
|
|
|
|
|
StartPos: $1.Pos,
|
|
|
|
|
}
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
yylex.(*parser).experimentalDurationExpr(de)
|
|
|
|
|
$$ = de
|
2025-06-25 11:39:27 -04:00
|
|
|
}
|
2025-12-10 10:16:08 -05:00
|
|
|
| unary_op RANGE LEFT_PAREN RIGHT_PAREN
|
|
|
|
|
{
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
de := &DurationExpr{
|
2025-12-10 10:16:08 -05:00
|
|
|
Op: $1.Typ,
|
|
|
|
|
RHS: &DurationExpr{
|
|
|
|
|
Op: RANGE,
|
|
|
|
|
StartPos: $2.PositionRange().Start,
|
|
|
|
|
EndPos: $4.PositionRange().End,
|
|
|
|
|
},
|
|
|
|
|
StartPos: $1.Pos,
|
|
|
|
|
}
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
yylex.(*parser).experimentalDurationExpr(de)
|
|
|
|
|
$$ = de
|
2025-12-10 10:16:08 -05:00
|
|
|
}
|
2026-05-19 05:41:16 -04:00
|
|
|
| max_of_min_of LEFT_PAREN duration_expr COMMA duration_expr RIGHT_PAREN
|
2025-06-25 11:39:27 -04:00
|
|
|
{
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
de := &DurationExpr{
|
2025-06-25 11:39:27 -04:00
|
|
|
Op: $1.Typ,
|
|
|
|
|
StartPos: $1.PositionRange().Start,
|
|
|
|
|
EndPos: $6.PositionRange().End,
|
|
|
|
|
LHS: $3.(Expr),
|
|
|
|
|
RHS: $5.(Expr),
|
|
|
|
|
}
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
yylex.(*parser).experimentalDurationExpr(de)
|
|
|
|
|
$$ = de
|
2025-06-25 11:39:27 -04:00
|
|
|
}
|
2026-05-19 05:41:16 -04:00
|
|
|
| unary_op max_of_min_of LEFT_PAREN duration_expr COMMA duration_expr RIGHT_PAREN
|
2025-06-25 11:39:27 -04:00
|
|
|
{
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
de := &DurationExpr{
|
2025-06-25 11:39:27 -04:00
|
|
|
Op: $1.Typ,
|
|
|
|
|
StartPos: $1.Pos,
|
|
|
|
|
EndPos: $6.PositionRange().End,
|
|
|
|
|
RHS: &DurationExpr{
|
|
|
|
|
Op: $2.Typ,
|
|
|
|
|
StartPos: $2.PositionRange().Start,
|
|
|
|
|
EndPos: $6.PositionRange().End,
|
|
|
|
|
LHS: $4.(Expr),
|
|
|
|
|
RHS: $6.(Expr),
|
|
|
|
|
},
|
|
|
|
|
}
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
yylex.(*parser).experimentalDurationExpr(de)
|
|
|
|
|
$$ = de
|
2025-06-25 11:39:27 -04:00
|
|
|
}
|
|
|
|
|
| unary_op LEFT_PAREN duration_expr RIGHT_PAREN %prec MUL
|
|
|
|
|
{
|
2026-05-22 11:29:46 -04:00
|
|
|
$$ = yylex.(*parser).applyUnaryOpToDurationExpr($1, $3.(Node), true)
|
2025-06-25 11:39:27 -04:00
|
|
|
}
|
2025-06-10 10:43:27 -04:00
|
|
|
| duration_expr
|
|
|
|
|
;
|
2025-12-03 12:46:35 -05:00
|
|
|
|
2026-05-19 05:41:16 -04:00
|
|
|
max_of_min_of: MAX_OF | MIN_OF ;
|
2025-06-25 11:39:27 -04:00
|
|
|
|
2025-03-20 08:15:20 -04:00
|
|
|
duration_expr : number_duration_literal
|
|
|
|
|
{
|
2025-03-27 09:39:23 -04:00
|
|
|
nl := $1.(*NumberLiteral)
|
2026-05-22 11:29:46 -04:00
|
|
|
if durationLiteralOutOfRange(nl.Val) {
|
2025-03-27 09:39:23 -04:00
|
|
|
yylex.(*parser).addParseErrf(nl.PosRange, "duration out of range")
|
2025-03-20 08:15:20 -04:00
|
|
|
$$ = &NumberLiteral{Val: 0}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
$$ = nl
|
2025-03-27 09:39:23 -04:00
|
|
|
}
|
|
|
|
|
| unary_op duration_expr %prec MUL
|
|
|
|
|
{
|
2026-05-22 11:29:46 -04:00
|
|
|
$$ = yylex.(*parser).applyUnaryOpToDurationExpr($1, $2.(Node), false)
|
2025-03-27 09:39:23 -04:00
|
|
|
}
|
2025-03-20 08:15:20 -04:00
|
|
|
| duration_expr ADD duration_expr
|
2025-03-27 09:39:23 -04:00
|
|
|
{
|
2026-05-13 03:29:32 -04:00
|
|
|
yylex.(*parser).experimentalDurationExpr($1.(Expr))
|
2025-03-27 09:39:23 -04:00
|
|
|
$$ = &DurationExpr{Op: ADD, LHS: $1.(Expr), RHS: $3.(Expr)}
|
|
|
|
|
}
|
2025-03-20 08:15:20 -04:00
|
|
|
| duration_expr SUB duration_expr
|
2025-03-27 09:39:23 -04:00
|
|
|
{
|
2026-05-13 03:29:32 -04:00
|
|
|
yylex.(*parser).experimentalDurationExpr($1.(Expr))
|
2025-03-27 09:39:23 -04:00
|
|
|
$$ = &DurationExpr{Op: SUB, LHS: $1.(Expr), RHS: $3.(Expr)}
|
|
|
|
|
}
|
2025-03-20 08:15:20 -04:00
|
|
|
| duration_expr MUL duration_expr
|
2025-03-27 09:39:23 -04:00
|
|
|
{
|
2026-05-13 03:29:32 -04:00
|
|
|
yylex.(*parser).experimentalDurationExpr($1.(Expr))
|
2025-03-27 09:39:23 -04:00
|
|
|
$$ = &DurationExpr{Op: MUL, LHS: $1.(Expr), RHS: $3.(Expr)}
|
|
|
|
|
}
|
2025-03-20 08:15:20 -04:00
|
|
|
| duration_expr DIV duration_expr
|
2025-03-27 09:39:23 -04:00
|
|
|
{
|
2026-05-13 03:29:32 -04:00
|
|
|
yylex.(*parser).experimentalDurationExpr($1.(Expr))
|
2025-03-27 09:39:23 -04:00
|
|
|
if nl, ok := $3.(*NumberLiteral); ok && nl.Val == 0 {
|
|
|
|
|
yylex.(*parser).addParseErrf($2.PositionRange(), "division by zero")
|
|
|
|
|
$$ = &NumberLiteral{Val: 0}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
$$ = &DurationExpr{Op: DIV, LHS: $1.(Expr), RHS: $3.(Expr)}
|
|
|
|
|
}
|
2025-03-20 08:15:20 -04:00
|
|
|
| duration_expr MOD duration_expr
|
2025-03-27 09:39:23 -04:00
|
|
|
{
|
2026-05-13 03:29:32 -04:00
|
|
|
yylex.(*parser).experimentalDurationExpr($1.(Expr))
|
2025-03-27 09:39:23 -04:00
|
|
|
if nl, ok := $3.(*NumberLiteral); ok && nl.Val == 0 {
|
|
|
|
|
yylex.(*parser).addParseErrf($2.PositionRange(), "modulo by zero")
|
|
|
|
|
$$ = &NumberLiteral{Val: 0}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
$$ = &DurationExpr{Op: MOD, LHS: $1.(Expr), RHS: $3.(Expr)}
|
|
|
|
|
}
|
2025-03-20 08:15:20 -04:00
|
|
|
| duration_expr POW duration_expr
|
2025-03-27 09:39:23 -04:00
|
|
|
{
|
2026-05-13 03:29:32 -04:00
|
|
|
yylex.(*parser).experimentalDurationExpr($1.(Expr))
|
2025-03-27 09:39:23 -04:00
|
|
|
$$ = &DurationExpr{Op: POW, LHS: $1.(Expr), RHS: $3.(Expr)}
|
|
|
|
|
}
|
2025-06-25 11:39:27 -04:00
|
|
|
| STEP LEFT_PAREN RIGHT_PAREN
|
|
|
|
|
{
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
de := &DurationExpr{
|
2025-06-25 11:39:27 -04:00
|
|
|
Op: STEP,
|
|
|
|
|
StartPos: $1.PositionRange().Start,
|
2025-07-01 05:46:03 -04:00
|
|
|
EndPos: $3.PositionRange().End,
|
2025-06-25 11:39:27 -04:00
|
|
|
}
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
yylex.(*parser).experimentalDurationExpr(de)
|
|
|
|
|
$$ = de
|
2025-06-25 11:39:27 -04:00
|
|
|
}
|
2025-12-10 10:16:08 -05:00
|
|
|
| RANGE LEFT_PAREN RIGHT_PAREN
|
|
|
|
|
{
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
de := &DurationExpr{
|
2025-12-10 10:16:08 -05:00
|
|
|
Op: RANGE,
|
|
|
|
|
StartPos: $1.PositionRange().Start,
|
|
|
|
|
EndPos: $3.PositionRange().End,
|
|
|
|
|
}
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
yylex.(*parser).experimentalDurationExpr(de)
|
|
|
|
|
$$ = de
|
2025-12-10 10:16:08 -05:00
|
|
|
}
|
2026-05-19 05:41:16 -04:00
|
|
|
| max_of_min_of LEFT_PAREN duration_expr COMMA duration_expr RIGHT_PAREN
|
2025-06-25 11:39:27 -04:00
|
|
|
{
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
de := &DurationExpr{
|
2025-06-25 11:39:27 -04:00
|
|
|
Op: $1.Typ,
|
|
|
|
|
StartPos: $1.PositionRange().Start,
|
2025-07-01 05:46:03 -04:00
|
|
|
EndPos: $6.PositionRange().End,
|
2025-06-25 11:39:27 -04:00
|
|
|
LHS: $3.(Expr),
|
|
|
|
|
RHS: $5.(Expr),
|
|
|
|
|
}
|
promql: protect min(), max(), step(), and range() duration exprs with feature flag
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
2026-05-13 03:56:54 -04:00
|
|
|
yylex.(*parser).experimentalDurationExpr(de)
|
|
|
|
|
$$ = de
|
2025-06-25 11:39:27 -04:00
|
|
|
}
|
2025-03-20 08:15:20 -04:00
|
|
|
| paren_duration_expr
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
paren_duration_expr : LEFT_PAREN duration_expr RIGHT_PAREN
|
2025-12-03 12:46:35 -05:00
|
|
|
{
|
2026-05-13 03:29:32 -04:00
|
|
|
yylex.(*parser).experimentalDurationExpr($2.(Expr))
|
2025-03-27 09:39:23 -04:00
|
|
|
if durationExpr, ok := $2.(*DurationExpr); ok {
|
|
|
|
|
durationExpr.Wrapped = true
|
|
|
|
|
$$ = durationExpr
|
|
|
|
|
break
|
|
|
|
|
}
|
2025-12-03 12:46:35 -05:00
|
|
|
$$ = $2
|
2025-03-27 09:39:23 -04:00
|
|
|
}
|
2025-03-20 08:15:20 -04:00
|
|
|
;
|
|
|
|
|
|
2019-12-09 14:03:31 -05:00
|
|
|
%%
|