mirror of
https://github.com/prometheus/prometheus.git
synced 2024-12-27 14:39:40 -08:00
1e0cd28bf6
* PromQL: Support trailing commas in grouping opts Fixes #6470 Signed-off-by: Tobias Guggenmos <tguggenm@redhat.com>
287 lines
8.3 KiB
Plaintext
287 lines
8.3 KiB
Plaintext
// 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.
|
|
|
|
%{
|
|
package promql
|
|
|
|
import (
|
|
"sort"
|
|
|
|
"github.com/prometheus/prometheus/pkg/labels"
|
|
)
|
|
%}
|
|
|
|
%union {
|
|
node Node
|
|
item Item
|
|
matchers []*labels.Matcher
|
|
matcher *labels.Matcher
|
|
label labels.Label
|
|
labels labels.Labels
|
|
strings []string
|
|
}
|
|
|
|
|
|
%token <item> ERROR
|
|
%token <item> EOF
|
|
%token <item> COMMENT
|
|
%token <item> IDENTIFIER
|
|
%token <item> METRIC_IDENTIFIER
|
|
%token <item> LEFT_PAREN
|
|
%token <item> RIGHT_PAREN
|
|
%token <item> LEFT_BRACE
|
|
%token <item> RIGHT_BRACE
|
|
%token <item> LEFT_BRACKET
|
|
%token <item> RIGHT_BRACKET
|
|
%token <item> COMMA
|
|
%token <item> ASSIGN
|
|
%token <item> COLON
|
|
%token <item> SEMICOLON
|
|
%token <item> STRING
|
|
%token <item> NUMBER
|
|
%token <item> DURATION
|
|
%token <item> BLANK
|
|
%token <item> TIMES
|
|
%token <item> SPACE
|
|
|
|
%token operatorsStart
|
|
// Operators.
|
|
%token <item> SUB
|
|
%token <item> ADD
|
|
%token <item> MUL
|
|
%token <item> MOD
|
|
%token <item> DIV
|
|
%token <item> LAND
|
|
%token <item> LOR
|
|
%token <item> LUNLESS
|
|
%token <item> EQL
|
|
%token <item> NEQ
|
|
%token <item> LTE
|
|
%token <item> LSS
|
|
%token <item> GTE
|
|
%token <item> GTR
|
|
%token <item> EQL_REGEX
|
|
%token <item> NEQ_REGEX
|
|
%token <item> POW
|
|
%token operatorsEnd
|
|
|
|
%token aggregatorsStart
|
|
// Aggregators.
|
|
%token <item> AVG
|
|
%token <item> COUNT
|
|
%token <item> SUM
|
|
%token <item> MIN
|
|
%token <item> MAX
|
|
%token <item> STDDEV
|
|
%token <item> STDVAR
|
|
%token <item> TOPK
|
|
%token <item> BOTTOMK
|
|
%token <item> COUNT_VALUES
|
|
%token <item> QUANTILE
|
|
%token aggregatorsEnd
|
|
|
|
%token keywordsStart
|
|
// Keywords.
|
|
%token <item> OFFSET
|
|
%token <item> BY
|
|
%token <item> WITHOUT
|
|
%token <item> ON
|
|
%token <item> IGNORING
|
|
%token <item> GROUP_LEFT
|
|
%token <item> GROUP_RIGHT
|
|
%token <item> BOOL
|
|
|
|
%token keywordsEnd
|
|
|
|
|
|
%token startSymbolsStart
|
|
// Start symbols for the generated parser.
|
|
%token START_LABELS
|
|
%token START_LABEL_SET
|
|
%token START_METRIC
|
|
%token START_GROUPING_LABELS
|
|
%token startSymbolsEnd
|
|
|
|
%type <matchers> label_matchers label_match_list
|
|
%type <matcher> label_matcher
|
|
|
|
%type <item> match_op metric_identifier grouping_label maybe_label
|
|
|
|
%type <labels> label_set_list label_set metric
|
|
%type <label> label_set_item
|
|
%type <strings> grouping_labels grouping_label_list
|
|
|
|
%start start
|
|
|
|
%%
|
|
|
|
start : START_LABELS label_matchers
|
|
{yylex.(*parser).generatedParserResult.(*VectorSelector).LabelMatchers = $2}
|
|
| START_LABEL_SET label_set
|
|
{ yylex.(*parser).generatedParserResult = $2 }
|
|
| START_METRIC metric
|
|
{ yylex.(*parser).generatedParserResult = $2 }
|
|
| START_GROUPING_LABELS grouping_labels
|
|
{ yylex.(*parser).generatedParserResult = $2 }
|
|
| error /* If none of the more detailed error messages are triggered, we fall back to this. */
|
|
{ yylex.(*parser).unexpected("","") }
|
|
;
|
|
|
|
|
|
label_matchers :
|
|
LEFT_BRACE label_match_list RIGHT_BRACE
|
|
{ $$ = $2 }
|
|
| LEFT_BRACE label_match_list COMMA RIGHT_BRACE
|
|
{ $$ = $2 }
|
|
| LEFT_BRACE RIGHT_BRACE
|
|
{ $$ = []*labels.Matcher{} }
|
|
|
|
;
|
|
|
|
label_match_list:
|
|
label_match_list COMMA label_matcher
|
|
{ $$ = append($1, $3)}
|
|
| label_matcher
|
|
{ $$ = []*labels.Matcher{$1}}
|
|
| label_match_list error
|
|
{ yylex.(*parser).unexpected("label matching", "\",\" or \"}\"") }
|
|
;
|
|
|
|
label_matcher :
|
|
IDENTIFIER match_op STRING
|
|
{ $$ = yylex.(*parser).newLabelMatcher($1, $2, $3) }
|
|
| IDENTIFIER match_op error
|
|
{ yylex.(*parser).unexpected("label matching", "string")}
|
|
| IDENTIFIER error
|
|
{ yylex.(*parser).unexpected("label matching", "label matching operator") }
|
|
| error
|
|
{ yylex.(*parser).unexpected("label matching", "identifier or \"}\"")}
|
|
;
|
|
|
|
match_op :
|
|
EQL {$$ =$1}
|
|
| NEQ {$$=$1}
|
|
| EQL_REGEX {$$=$1}
|
|
| NEQ_REGEX {$$=$1}
|
|
;
|
|
|
|
|
|
metric :
|
|
metric_identifier label_set
|
|
{ $$ = append($2, labels.Label{Name: labels.MetricName, Value: $1.Val}); sort.Sort($$) }
|
|
| label_set
|
|
{$$ = $1}
|
|
| error
|
|
{ yylex.(*parser).errorf("missing metric name or metric selector")}
|
|
;
|
|
|
|
metric_identifier
|
|
:
|
|
METRIC_IDENTIFIER {$$=$1}
|
|
| IDENTIFIER {$$=$1}
|
|
|
|
label_set :
|
|
LEFT_BRACE label_set_list RIGHT_BRACE
|
|
{ $$ = labels.New($2...) }
|
|
| LEFT_BRACE label_set_list COMMA RIGHT_BRACE
|
|
{ $$ = labels.New($2...) }
|
|
| LEFT_BRACE RIGHT_BRACE
|
|
{ $$ = labels.New() }
|
|
| /* empty */
|
|
{ $$ = labels.New() }
|
|
;
|
|
|
|
label_set_list :
|
|
label_set_list COMMA label_set_item
|
|
{ $$ = append($1, $3) }
|
|
| label_set_item
|
|
{ $$ = []labels.Label{$1} }
|
|
| label_set_list error
|
|
{ yylex.(*parser).unexpected("label set", "\",\" or \"}\"", ) }
|
|
|
|
;
|
|
|
|
label_set_item :
|
|
IDENTIFIER EQL STRING
|
|
{ $$ = labels.Label{Name: $1.Val, Value: yylex.(*parser).unquoteString($3.Val) } }
|
|
| IDENTIFIER EQL error
|
|
{ yylex.(*parser).unexpected("label set", "string")}
|
|
| IDENTIFIER error
|
|
{ yylex.(*parser).unexpected("label set", "\"=\"")}
|
|
| error
|
|
{ yylex.(*parser).unexpected("label set", "identifier or \"}\"") }
|
|
;
|
|
|
|
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
|
|
{ yylex.(*parser).unexpected("grouping opts", "\"(\"") }
|
|
;
|
|
|
|
|
|
grouping_label_list:
|
|
grouping_label_list COMMA grouping_label
|
|
{ $$ = append($1, $3.Val) }
|
|
| grouping_label
|
|
{ $$ = []string{$1.Val} }
|
|
| grouping_label_list error
|
|
{ yylex.(*parser).unexpected("grouping opts", "\",\" or \"}\"") }
|
|
;
|
|
|
|
grouping_label :
|
|
maybe_label
|
|
{
|
|
if !isLabel($1.Val) {
|
|
yylex.(*parser).unexpected("grouping opts", "label")
|
|
}
|
|
$$ = $1
|
|
}
|
|
| error
|
|
{ yylex.(*parser).unexpected("grouping opts", "label") }
|
|
;
|
|
|
|
|
|
/* inside of grouping options label names can be recognized as keywords by the lexer */
|
|
maybe_label :
|
|
IDENTIFIER
|
|
| METRIC_IDENTIFIER
|
|
| LAND
|
|
| LOR
|
|
| LUNLESS
|
|
| AVG
|
|
| COUNT
|
|
| SUM
|
|
| MIN
|
|
| MAX
|
|
| STDDEV
|
|
| STDVAR
|
|
| TOPK
|
|
| BOTTOMK
|
|
| COUNT_VALUES
|
|
| QUANTILE
|
|
| OFFSET
|
|
| BY
|
|
| ON
|
|
| IGNORING
|
|
| GROUP_LEFT
|
|
| GROUP_RIGHT
|
|
| BOOL
|
|
;
|
|
|
|
%%
|