%{ package rules import "fmt" import "github.com/matttproud/prometheus/model" import "github.com/matttproud/prometheus/rules/ast" %} %union { num model.SampleValue str string ruleNode ast.Node ruleNodeSlice []ast.Node boolean bool labelNameSlice []model.LabelName labelSet model.LabelSet } %token IDENTIFIER STRING %token NUMBER %token PERMANENT GROUP_OP %token AGGR_OP CMP_OP ADDITIVE_OP MULT_OP %type func_arg_list %type label_list grouping_opts %type label_assign label_assign_list rule_labels %type rule_expr func_arg %type qualifier %right '=' %left CMP_OP %left ADDITIVE_OP %left MULT_OP %start rules_stat_list %% rules_stat_list : /* empty */ | rules_stat_list rules_stat ; rules_stat : qualifier IDENTIFIER rule_labels '=' rule_expr { rule, err := CreateRule($2, $3, $5, $1) if err != nil { yylex.Error(err.Error()); return 1 } addRule(rule) } ; qualifier : /* empty */ { $$ = false } | PERMANENT { $$ = true } ; rule_labels : /* empty */ { $$ = model.LabelSet{} } | '{' label_assign_list '}' { $$ = $2 } | '{' '}' { $$ = model.LabelSet{} } label_assign_list : label_assign { $$ = $1 } | label_assign_list ',' label_assign { for k, v := range $3 { $$[k] = v } } ; label_assign : IDENTIFIER '=' STRING { $$ = model.LabelSet{ model.LabelName($1): model.LabelValue($3) } } ; rule_expr : '(' rule_expr ')' { $$ = $2 } | IDENTIFIER rule_labels { $2["name"] = model.LabelValue($1); $$ = ast.NewVectorLiteral($2) } | IDENTIFIER '(' func_arg_list ')' { var err error $$, err = NewFunctionCall($1, $3) if err != nil { yylex.Error(err.Error()); return 1 } } | IDENTIFIER '(' ')' { var err error $$, err = NewFunctionCall($1, []ast.Node{}) if err != nil { yylex.Error(err.Error()); return 1 } } | AGGR_OP '(' rule_expr ')' grouping_opts { var err error $$, err = NewVectorAggregation($1, $3, $5) if err != nil { yylex.Error(err.Error()); return 1 } } /* Yacc can only attach associativity to terminals, so we * have to list all operators here. */ | rule_expr ADDITIVE_OP rule_expr { var err error $$, err = NewArithExpr($2, $1, $3) if err != nil { yylex.Error(err.Error()); return 1 } } | rule_expr MULT_OP rule_expr { var err error $$, err = NewArithExpr($2, $1, $3) if err != nil { yylex.Error(err.Error()); return 1 } } | rule_expr CMP_OP rule_expr { var err error $$, err = NewArithExpr($2, $1, $3) if err != nil { yylex.Error(err.Error()); return 1 } } | NUMBER { $$ = ast.NewScalarLiteral($1)} ; grouping_opts : { $$ = []model.LabelName{} } | GROUP_OP '(' label_list ')' { $$ = $3 } ; label_list : IDENTIFIER { $$ = []model.LabelName{model.LabelName($1)} } | label_list ',' IDENTIFIER { $$ = append($$, model.LabelName($3)) } ; func_arg_list : func_arg { $$ = []ast.Node{$1} } | func_arg_list ',' func_arg { $$ = append($$, $3) } ; func_arg : rule_expr { $$ = $1 } | rule_expr '[' STRING ']' { var err error $$, err = NewMatrix($1, $3) if err != nil { yylex.Error(err.Error()); return 1 } } | STRING { $$ = ast.NewStringLiteral($1) } ; %%