diff --git a/rules/lexer.l b/rules/lexer.l index 2972fa7be..8f4663029 100644 --- a/rules/lexer.l +++ b/rules/lexer.l @@ -9,6 +9,7 @@ import ( D [0-9] L [a-zA-Z_:] +U [smhdwy] %x S_COMMENTS @@ -30,6 +31,7 @@ AVG|SUM|MAX|MIN { yylval.str = yytext; return AGGR_OP } [+\-] { yylval.str = yytext; return ADDITIVE_OP } [*/%] { yylval.str = yytext; return MULT_OP } +{D}+{U} { yylval.str = yytext; return DURATION } {L}({L}|{D})+ { yylval.str = yytext; return IDENTIFIER } \-?{D}+(\.{D}*)? { num, err := strconv.ParseFloat(yytext, 32); diff --git a/rules/lexer.l.go b/rules/lexer.l.go index 3de45a3af..a6e6876af 100644 --- a/rules/lexer.l.go +++ b/rules/lexer.l.go @@ -397,6 +397,20 @@ var yyrules []yyrule = []yyrule{{regexp.MustCompile("[^\\n]"), nil, []yystartcon return yyactionreturn{MULT_OP, yyRT_USER_RETURN} } return yyactionreturn{0, yyRT_FALLTHROUGH} +}}, {regexp.MustCompile("([0-9])+([smhdwy])"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { + defer func() { + if r := recover(); r != nil { + if r != "yyREJECT" { + panic(r) + } + yyar.returnType = yyRT_REJECT + } + }() + { + yylval.str = yytext + return yyactionreturn{DURATION, yyRT_USER_RETURN} + } + return yyactionreturn{0, yyRT_FALLTHROUGH} }}, {regexp.MustCompile("([a-zA-Z_:])(([a-zA-Z_:])|([0-9]))+"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { defer func() { if r := recover(); r != nil { diff --git a/rules/parser.y b/rules/parser.y index 10f32ae12..69b1d093c 100644 --- a/rules/parser.y +++ b/rules/parser.y @@ -22,7 +22,7 @@ */ %token START_RULES START_EXPRESSION -%token IDENTIFIER STRING +%token IDENTIFIER STRING DURATION %token NUMBER %token PERMANENT GROUP_OP %token AGGR_OP CMP_OP ADDITIVE_OP MULT_OP @@ -100,7 +100,7 @@ rule_expr : '(' rule_expr ')' $$, err = NewFunctionCall($1, []ast.Node{}) if err != nil { yylex.Error(err.Error()); return 1 } } - | rule_expr '[' STRING ']' + | rule_expr '[' DURATION ']' { var err error $$, err = NewMatrix($1, $3) @@ -112,7 +112,7 @@ rule_expr : '(' rule_expr ')' $$, err = NewVectorAggregation($1, $3, $5) if err != nil { yylex.Error(err.Error()); return 1 } } - /* Yacc can only attach associativity to terminals, so we + /* Yacc can only attach associativity to terminals, so we * have to list all operators here. */ | rule_expr ADDITIVE_OP rule_expr { diff --git a/rules/parser.y.go b/rules/parser.y.go index 05d4bea89..f1712842c 100644 --- a/rules/parser.y.go +++ b/rules/parser.y.go @@ -22,19 +22,21 @@ const START_RULES = 57346 const START_EXPRESSION = 57347 const IDENTIFIER = 57348 const STRING = 57349 -const NUMBER = 57350 -const PERMANENT = 57351 -const GROUP_OP = 57352 -const AGGR_OP = 57353 -const CMP_OP = 57354 -const ADDITIVE_OP = 57355 -const MULT_OP = 57356 +const DURATION = 57350 +const NUMBER = 57351 +const PERMANENT = 57352 +const GROUP_OP = 57353 +const AGGR_OP = 57354 +const CMP_OP = 57355 +const ADDITIVE_OP = 57356 +const MULT_OP = 57357 var yyToknames = []string{ "START_RULES", "START_EXPRESSION", "IDENTIFIER", "STRING", + "DURATION", "NUMBER", "PERMANENT", "GROUP_OP", @@ -74,27 +76,27 @@ const yyLast = 84 var yyAct = []int{ 32, 36, 31, 16, 6, 17, 15, 16, 18, 40, - 14, 14, 19, 46, 14, 54, 25, 26, 27, 8, - 33, 10, 21, 38, 9, 20, 17, 15, 16, 17, - 15, 16, 7, 30, 28, 14, 39, 22, 14, 8, - 33, 10, 15, 16, 9, 48, 49, 21, 53, 8, - 14, 10, 7, 58, 9, 57, 42, 37, 41, 43, - 44, 47, 7, 45, 52, 13, 50, 24, 35, 59, + 14, 14, 21, 46, 14, 20, 25, 26, 27, 8, + 33, 54, 10, 38, 22, 9, 19, 17, 15, 16, + 17, 15, 16, 7, 30, 28, 14, 8, 33, 14, + 10, 15, 16, 9, 47, 48, 49, 21, 53, 14, + 39, 7, 8, 37, 58, 10, 57, 42, 9, 41, + 43, 44, 52, 13, 45, 35, 7, 24, 50, 59, 56, 37, 23, 2, 3, 11, 5, 4, 1, 12, 34, 51, 55, 29, } var yyPact = []int{ - 69, -1000, -1000, 43, 56, -1000, 17, 43, 6, 18, - -1000, -1000, 66, -1000, 60, 43, 43, 43, 14, -1000, - 13, 51, 43, 31, -13, -11, -10, 29, -1000, 38, - -1000, -1000, 17, -1000, 42, -1000, -1000, 48, -7, 46, - -1000, -1000, 33, -1000, 65, 59, 54, 43, -1000, -1000, - -1000, -1000, -4, 17, 64, 35, -1000, -1000, 63, -1000, + 69, -1000, -1000, 46, 53, -1000, 17, 46, -5, 4, + -1000, -1000, 66, -1000, 59, 46, 46, 46, 14, -1000, + 13, 47, 46, 30, -14, -12, -11, 27, -1000, 38, + -1000, -1000, 17, -1000, 42, -1000, -1000, 48, -8, 28, + -1000, -1000, 31, -1000, 65, 61, 51, 46, -1000, -1000, + -1000, -1000, 1, 17, 64, 35, -1000, -1000, 63, -1000, } var yyPgo = []int{ - 0, 83, 82, 81, 1, 80, 12, 0, 2, 79, + 0, 83, 82, 81, 1, 80, 26, 0, 2, 79, 78, 77, 76, 75, } var yyR1 = []int{ @@ -113,12 +115,12 @@ var yyR2 = []int{ } var yyChk = []int{ - -1000, -10, 4, 5, -11, -12, -7, 19, 6, 11, - 8, -13, -9, 9, 21, 13, 14, 12, -7, -6, - 19, 16, 19, 6, 7, -7, -7, -7, 20, -1, - 20, -8, -7, 7, -5, 17, -4, 6, -7, -6, - 22, 20, 18, 17, 18, 15, 20, 15, -8, -4, - 7, -3, 10, -7, 19, -2, 6, 20, 18, 6, + -1000, -10, 4, 5, -11, -12, -7, 20, 6, 12, + 9, -13, -9, 10, 22, 14, 15, 13, -7, -6, + 20, 17, 20, 6, 8, -7, -7, -7, 21, -1, + 21, -8, -7, 7, -5, 18, -4, 6, -7, -6, + 23, 21, 19, 18, 19, 16, 21, 16, -8, -4, + 7, -3, 11, -7, 20, -2, 6, 21, 19, 6, } var yyDef = []int{ @@ -135,20 +137,20 @@ var yyTok1 = []int{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19, 20, 3, 3, 18, 3, 3, 3, 3, 3, + 20, 21, 3, 3, 19, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 15, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 16, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 21, 3, 22, 3, 3, 3, 3, 3, 3, + 3, 22, 3, 23, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 16, 3, 17, + 3, 3, 3, 17, 3, 18, } var yyTok2 = []int{ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, + 12, 13, 14, 15, } var yyTok3 = []int{ 0, diff --git a/rules/rules_test.go b/rules/rules_test.go index 60da8f761..1893e34ec 100644 --- a/rules/rules_test.go +++ b/rules/rules_test.go @@ -105,7 +105,7 @@ var expressionTests = []struct { "http_requests{job='app-server'} => 5200 @[%v]", }, }, { - expr: "rate(http_requests['25m'])", + expr: "delta(http_requests[25m], 1)", output: []string{ "http_requests{group='canary',instance='0',job='api-server'} => 150 @[%v]", "http_requests{group='canary',instance='0',job='app-server'} => 350 @[%v]", @@ -121,7 +121,10 @@ var expressionTests = []struct { expr: "", shouldFail: true, }, { - expr: "http_requests[1m]", + expr: "1 - http_requests", + shouldFail: true, + }, { + expr: "http_requests['1m']", shouldFail: true, }, }