diff --git a/rules/Makefile b/rules/Makefile index bf8fc3899..489f1e9ec 100644 --- a/rules/Makefile +++ b/rules/Makefile @@ -17,7 +17,8 @@ parser.y.go: parser.y go tool yacc -o parser.y.go -v "" parser.y lexer.l.go: parser.y.go lexer.l - golex lexer.l + # This is golex from https://github.com/cznic/golex. + golex -o="lexer.l.go" lexer.l clean: rm lexer.l.go parser.y.go diff --git a/rules/lexer.l b/rules/lexer.l index 16d9c786f..55b68c42b 100644 --- a/rules/lexer.l +++ b/rules/lexer.l @@ -1,25 +1,53 @@ -/* Copyright 2013 Prometheus Team - * 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. */ +// Copyright 2013 Prometheus Team +// 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 rules import ( + "fmt" "strconv" "strings" clientmodel "github.com/prometheus/client_golang/model" ) + +// Lex is called by the parser generated by "go tool yacc" to obtain each +// token. The method is opened before the matching rules block and closed at +// the end of the file. +func (lexer *RulesLexer) Lex(lval *yySymType) int { + // Internal lexer states. + const ( + S_INITIAL = iota + S_COMMENTS + ) + + // We simulate multiple start symbols for closely-related grammars via dummy tokens. See + // http://www.gnu.org/software/bison/manual/html_node/Multiple-start_002dsymbols.html + // Reason: we want to be able to parse lists of named rules as well as single expressions. + if lexer.startToken != 0 { + startToken := lexer.startToken + lexer.startToken = 0 + return startToken + } + + c := lexer.current + currentState := 0 + + if lexer.empty { + c, lexer.empty = lexer.getChar(), false + } + %} D [0-9] @@ -28,44 +56,50 @@ U [smhdwy] %x S_COMMENTS +%yyc c +%yyn c = lexer.getChar() +%yyt currentState + %% -. { yypos++; REJECT } -\n { yyline++; yypos = 1; REJECT } + lexer.buf = lexer.buf[:0] // The code before the first rule executed before every scan cycle (rule #0 / state 0 action) -"/*" { BEGIN(S_COMMENTS) } -"*/" { BEGIN(0) } -. { /* ignore chars within multi-line comments */ } +"/*" currentState = S_COMMENTS +"*/" currentState = S_INITIAL +.|\n /* ignore chars within multi-line comments */ -\/\/[^\r\n]*\n { /* gobble up one-line comments */ } +\/\/[^\r\n]*\n /* gobble up one-line comments */ -ALERT|alert { return ALERT } -IF|if { return IF } -FOR|for { return FOR } -WITH|with { return WITH } +ALERT|alert return ALERT +IF|if return IF +FOR|for return FOR +WITH|with return WITH -PERMANENT|permanent { return PERMANENT } -BY|by { return GROUP_OP } -AVG|SUM|MAX|MIN|COUNT { yylval.str = yytext; return AGGR_OP } -avg|sum|max|min|count { yylval.str = strings.ToUpper(yytext); return AGGR_OP } -\<|>|AND|OR|and|or { yylval.str = strings.ToUpper(yytext); return CMP_OP } -==|!=|>=|<= { yylval.str = yytext; return CMP_OP } -[+\-] { yylval.str = yytext; return ADDITIVE_OP } -[*/%] { yylval.str = yytext; return MULT_OP } +PERMANENT|permanent return PERMANENT +BY|by return GROUP_OP +AVG|SUM|MAX|MIN|COUNT lval.str = lexer.token(); return AGGR_OP +avg|sum|max|min|count lval.str = strings.ToUpper(lexer.token()); return AGGR_OP +\<|>|AND|OR|and|or lval.str = strings.ToUpper(lexer.token()); return CMP_OP +==|!=|>=|<= lval.str = lexer.token(); return CMP_OP +[+\-] lval.str = lexer.token(); return ADDITIVE_OP +[*/%] lval.str = lexer.token(); return MULT_OP -{D}+{U} { yylval.str = yytext; return DURATION } -{L}({L}|{D})* { yylval.str = yytext; return IDENTIFIER } +{D}+{U} lval.str = lexer.token(); return DURATION +{L}({L}|{D})* lval.str = lexer.token(); return IDENTIFIER -\-?{D}+(\.{D}*)? { num, err := strconv.ParseFloat(yytext, 64); - if (err != nil && err.(*strconv.NumError).Err == strconv.ErrSyntax) { - panic("Invalid float") - } - yylval.num = clientmodel.SampleValue(num) - return NUMBER } +\-?{D}+(\.{D}*)? num, err := strconv.ParseFloat(lexer.token(), 64); + if (err != nil && err.(*strconv.NumError).Err == strconv.ErrSyntax) { + panic("Invalid float") + } + lval.num = clientmodel.SampleValue(num) + return NUMBER -\"(\\.|[^\\"])*\" { yylval.str = yytext[1:len(yytext) - 1]; return STRING } -\'(\\.|[^\\'])*\' { yylval.str = yytext[1:len(yytext) - 1]; return STRING } +\"(\\.|[^\\"])*\" lval.str = lexer.token()[1:len(lexer.token()) - 1]; return STRING +\'(\\.|[^\\'])*\' lval.str = lexer.token()[1:len(lexer.token()) - 1]; return STRING -[{}\[\]()=,] { return int(yytext[0]) } -. { /* don't print any remaining chars (whitespace) */ } -\n { /* don't print any remaining chars (whitespace) */ } +[{}\[\]()=,] return int(lexer.buf[0]) +[\t\n\r ] /* gobble up any whitespace */ %% + + lexer.empty = true + return int(c) +} diff --git a/rules/lexer.l.go b/rules/lexer.l.go index b3ca39c3e..d8b435d64 100644 --- a/rules/lexer.l.go +++ b/rules/lexer.l.go @@ -1,585 +1,1233 @@ -// Generated by golex package rules import ( - "bufio" - "io" - "os" - "regexp" - "sort" -) -import ( - "strconv" - "strings" + "fmt" + "strconv" + "strings" - clientmodel "github.com/prometheus/client_golang/model" + clientmodel "github.com/prometheus/client_golang/model" ) -var yyin io.Reader = os.Stdin -var yyout io.Writer = os.Stdout +func (lexer *RulesLexer) Lex(lval *yySymType) int { + // Internal lexer states. + const ( + S_INITIAL = iota + S_COMMENTS + ) -type yyrule struct { - regexp *regexp.Regexp - trailing *regexp.Regexp - startConds []yystartcondition - sol bool - action func() yyactionreturn + // We simulate multiple start symbols for closely-related grammars via dummy tokens. See + // http://www.gnu.org/software/bison/manual/html_node/Multiple-start_002dsymbols.html + // Reason: we want to be able to parse lists of named rules as well as single expressions. + if lexer.startToken != 0 { + startToken := lexer.startToken + lexer.startToken = 0 + return startToken + } + + c := lexer.current + currentState := 0 + + if lexer.empty { + c, lexer.empty = lexer.getChar(), false + } + + + +yystate0: + + lexer.buf = lexer.buf[:0] // The code before the first rule executed before every scan cycle (rule #0 / state 0 action) + +switch yyt := currentState; yyt { +default: +panic(fmt.Errorf(`invalid start condition %d`, yyt)) +case 0: // start condition: INITIAL +goto yystart1 +case 1: // start condition: S_COMMENTS +goto yystart97 } -type yyactionreturn struct { - userReturn int - returnType yyactionreturntype +goto yystate1 // silence unused label error +yystate1: +c = lexer.getChar() +yystart1: +switch { +default: +goto yyabort +case c == '!': +goto yystate3 +case c == '"': +goto yystate5 +case c == '%' || c == '*': +goto yystate8 +case c == '(' || c == ')' || c == ',' || c == '[' || c == ']' || c == '{' || c == '}': +goto yystate12 +case c == '+': +goto yystate13 +case c == '-': +goto yystate14 +case c == '/': +goto yystate17 +case c == ':' || c == 'D' || c == 'E' || c == 'G' || c == 'H' || c >= 'J' && c <= 'L' || c == 'N' || c == 'Q' || c == 'R' || c >= 'T' && c <= 'V' || c >= 'X' && c <= 'Z' || c == '_' || c == 'd' || c == 'e' || c == 'g' || c == 'h' || c >= 'j' && c <= 'l' || c == 'n' || c == 'q' || c == 'r' || c >= 't' && c <= 'v' || c >= 'x' && c <= 'z': +goto yystate23 +case c == '<' || c == '>': +goto yystate24 +case c == '=': +goto yystate25 +case c == 'A': +goto yystate26 +case c == 'B': +goto yystate35 +case c == 'C': +goto yystate37 +case c == 'F': +goto yystate41 +case c == 'I': +goto yystate44 +case c == 'M': +goto yystate46 +case c == 'O': +goto yystate49 +case c == 'P': +goto yystate50 +case c == 'S': +goto yystate59 +case c == 'W': +goto yystate61 +case c == '\'': +goto yystate9 +case c == '\t' || c == '\n' || c == '\r' || c == ' ': +goto yystate2 +case c == 'a': +goto yystate65 +case c == 'b': +goto yystate72 +case c == 'c': +goto yystate73 +case c == 'f': +goto yystate77 +case c == 'i': +goto yystate79 +case c == 'm': +goto yystate80 +case c == 'o': +goto yystate83 +case c == 'p': +goto yystate84 +case c == 's': +goto yystate92 +case c == 'w': +goto yystate94 +case c >= '0' && c <= '9': +goto yystate21 } -type yyactionreturntype int +yystate2: +c = lexer.getChar() +goto yyrule23 -const ( - yyRT_FALLTHROUGH yyactionreturntype = iota - yyRT_USER_RETURN - yyRT_REJECT -) - -var yydata string = "" -var yyorig string -var yyorigidx int - -var yytext string = "" -var yytextrepl bool = true - -func yymore() { - yytextrepl = false +yystate3: +c = lexer.getChar() +switch { +default: +goto yyabort +case c == '=': +goto yystate4 } -func yyBEGIN(state yystartcondition) { - YY_START = state +yystate4: +c = lexer.getChar() +goto yyrule14 + +yystate5: +c = lexer.getChar() +switch { +default: +goto yyabort +case c == '"': +goto yystate6 +case c == '\\': +goto yystate7 +case c >= '\x01' && c <= '!' || c >= '#' && c <= '[' || c >= ']' && c <= 'ÿ': +goto yystate5 } -func yyECHO() { - yyout.Write([]byte(yytext)) +yystate6: +c = lexer.getChar() +goto yyrule20 + +yystate7: +c = lexer.getChar() +switch { +default: +goto yyabort +case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ': +goto yystate5 } -func yyREJECT() { - panic("yyREJECT") +yystate8: +c = lexer.getChar() +goto yyrule16 + +yystate9: +c = lexer.getChar() +switch { +default: +goto yyabort +case c == '\'': +goto yystate10 +case c == '\\': +goto yystate11 +case c >= '\x01' && c <= '&' || c >= '(' && c <= '[' || c >= ']' && c <= 'ÿ': +goto yystate9 } -var yylessed int +yystate10: +c = lexer.getChar() +goto yyrule21 -func yyless(n int) { - yylessed = len(yytext) - n +yystate11: +c = lexer.getChar() +switch { +default: +goto yyabort +case c >= '\x01' && c <= '\t' || c >= '\v' && c <= 'ÿ': +goto yystate9 } -func unput(c uint8) { - yyorig = yyorig[:yyorigidx] + string(c) + yyorig[yyorigidx:] - yydata = yydata[:len(yytext)-yylessed] + string(c) + yydata[len(yytext)-yylessed:] +yystate12: +c = lexer.getChar() +goto yyrule22 + +yystate13: +c = lexer.getChar() +goto yyrule15 + +yystate14: +c = lexer.getChar() +switch { +default: +goto yyrule15 +case c >= '0' && c <= '9': +goto yystate15 } -func input() int { - if len(yyorig) <= yyorigidx { - return EOF - } - c := yyorig[yyorigidx] - yyorig = yyorig[:yyorigidx] + yyorig[yyorigidx+1:] - yydata = yydata[:len(yytext)-yylessed] + yydata[len(yytext)-yylessed+1:] - return int(c) +yystate15: +c = lexer.getChar() +switch { +default: +goto yyrule19 +case c == '.': +goto yystate16 +case c >= '0' && c <= '9': +goto yystate15 } -var EOF int = -1 - -type yystartcondition int - -var INITIAL yystartcondition = 0 -var YY_START yystartcondition = INITIAL - -type yylexMatch struct { - index int - matchFunc func() yyactionreturn - sortLen int - advLen int +yystate16: +c = lexer.getChar() +switch { +default: +goto yyrule19 +case c >= '0' && c <= '9': +goto yystate16 } -type yylexMatchList []yylexMatch - -func (ml yylexMatchList) Len() int { - return len(ml) +yystate17: +c = lexer.getChar() +switch { +default: +goto yyrule16 +case c == '*': +goto yystate18 +case c == '/': +goto yystate19 } -func (ml yylexMatchList) Less(i, j int) bool { - return ml[i].sortLen > ml[j].sortLen && ml[i].index > ml[j].index +yystate18: +c = lexer.getChar() +goto yyrule1 + +yystate19: +c = lexer.getChar() +switch { +default: +goto yyabort +case c == '\n': +goto yystate20 +case c >= '\x01' && c <= '\t' || c == '\v' || c == '\f' || c >= '\x0e' && c <= 'ÿ': +goto yystate19 } -func (ml yylexMatchList) Swap(i, j int) { - ml[i], ml[j] = ml[j], ml[i] +yystate20: +c = lexer.getChar() +goto yyrule4 + +yystate21: +c = lexer.getChar() +switch { +default: +goto yyrule19 +case c == '.': +goto yystate16 +case c == 'd' || c == 'h' || c == 'm' || c == 's' || c == 'w' || c == 'y': +goto yystate22 +case c >= '0' && c <= '9': +goto yystate21 } -func yylex() int { - reader := bufio.NewReader(yyin) +yystate22: +c = lexer.getChar() +goto yyrule17 - for { - line, err := reader.ReadString('\n') - if len(line) == 0 && err == io.EOF { - break - } - - yydata += line - } - - yyorig = yydata - yyorigidx = 0 - - yyactioninline(yyBEGIN) - - for len(yydata) > 0 { - matches := yylexMatchList(make([]yylexMatch, 0, 6)) - excl := yystartconditionexclmap[YY_START] - - for i, v := range yyrules { - sol := yyorigidx == 0 || yyorig[yyorigidx-1] == '\n' - - if v.sol && !sol { - continue - } - - // Check start conditions. - ok := false - - // YY_START or '*' must feature in v.startConds - for _, c := range v.startConds { - if c == YY_START || c == -1 { - ok = true - break - } - } - - if !excl { - // If v.startConds is empty, this is also acceptable. - if len(v.startConds) == 0 { - ok = true - } - } - - if !ok { - continue - } - - idxs := v.regexp.FindStringIndex(yydata) - if idxs != nil && idxs[0] == 0 { - // Check the trailing context, if any. - checksOk := true - sortLen := idxs[1] - advLen := idxs[1] - - if v.trailing != nil { - tridxs := v.trailing.FindStringIndex(yydata[idxs[1]:]) - if tridxs == nil || tridxs[0] != 0 { - checksOk = false - } else { - sortLen += tridxs[1] - } - } - - if checksOk { - matches = append(matches, yylexMatch{i, v.action, sortLen, advLen}) - } - } - } - - if yytextrepl { - yytext = "" - } - - sort.Sort(matches) - - tryMatch: - if len(matches) == 0 { - yytext += yydata[:1] - yydata = yydata[1:] - yyorigidx += 1 - - yyout.Write([]byte(yytext)) - } else { - m := matches[0] - yytext += yydata[:m.advLen] - yyorigidx += m.advLen - - yytextrepl, yylessed = true, 0 - ar := m.matchFunc() - - if ar.returnType != yyRT_REJECT { - yydata = yydata[m.advLen-yylessed:] - yyorigidx -= yylessed - } - - switch ar.returnType { - case yyRT_FALLTHROUGH: - // Do nothing. - case yyRT_USER_RETURN: - return ar.userReturn - case yyRT_REJECT: - matches = matches[1:] - yytext = yytext[:len(yytext)-m.advLen] - yyorigidx -= m.advLen - goto tryMatch - } - } - } - - return 0 +yystate23: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 } -var S_COMMENTS yystartcondition = 1024 -var yystartconditionexclmap = map[yystartcondition]bool{S_COMMENTS: true} -var yyrules []yyrule = []yyrule{{regexp.MustCompile("[^\\n]"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - yypos++ - yyREJECT() - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("\\n"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - yyline++ - yypos = 1 - yyREJECT() - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("/\\*"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - yyBEGIN(S_COMMENTS) - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("\\*/"), nil, []yystartcondition{S_COMMENTS}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - yyBEGIN(0) - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("[^\\n]"), nil, []yystartcondition{S_COMMENTS}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("\\/\\/[^\\r\\n]*\\n"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("ALERT|alert"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - return yyactionreturn{ALERT, yyRT_USER_RETURN} - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("IF|if"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - return yyactionreturn{IF, yyRT_USER_RETURN} - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("FOR|for"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - return yyactionreturn{FOR, yyRT_USER_RETURN} - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("WITH|with"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - return yyactionreturn{WITH, yyRT_USER_RETURN} - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("PERMANENT|permanent"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - return yyactionreturn{PERMANENT, yyRT_USER_RETURN} - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("BY|by"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - return yyactionreturn{GROUP_OP, yyRT_USER_RETURN} - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("AVG|SUM|MAX|MIN|COUNT"), 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{AGGR_OP, yyRT_USER_RETURN} - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("avg|sum|max|min|count"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - yylval.str = strings.ToUpper(yytext) - return yyactionreturn{AGGR_OP, yyRT_USER_RETURN} - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("\\<|>|AND|OR|and|or"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - yylval.str = strings.ToUpper(yytext) - return yyactionreturn{CMP_OP, yyRT_USER_RETURN} - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("==|!=|>=|<="), 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{CMP_OP, yyRT_USER_RETURN} - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("[+\\-]"), 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{ADDITIVE_OP, yyRT_USER_RETURN} - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("[*/%]"), 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{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 { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - yylval.str = yytext - return yyactionreturn{IDENTIFIER, yyRT_USER_RETURN} - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("\\-?([0-9])+(\\.([0-9])*)?"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - num, err := strconv.ParseFloat(yytext, 64) - if err != nil && err.(*strconv.NumError).Err == strconv.ErrSyntax { - panic("Invalid float") - } - yylval.num = clientmodel.SampleValue(num) - return yyactionreturn{NUMBER, yyRT_USER_RETURN} - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("\\\"(\\\\[^\\n]|[^\\\\\"])*\\\""), 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[1 : len(yytext)-1] - return yyactionreturn{STRING, yyRT_USER_RETURN} - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("\\'(\\\\[^\\n]|[^\\\\'])*\\'"), 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[1 : len(yytext)-1] - return yyactionreturn{STRING, yyRT_USER_RETURN} - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("[{}\\[\\]()=,]"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - return yyactionreturn{int(yytext[0]), yyRT_USER_RETURN} - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("[^\\n]"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}, {regexp.MustCompile("\\n"), nil, []yystartcondition{}, false, func() (yyar yyactionreturn) { - defer func() { - if r := recover(); r != nil { - if r != "yyREJECT" { - panic(r) - } - yyar.returnType = yyRT_REJECT - } - }() - { - } - return yyactionreturn{0, yyRT_FALLTHROUGH} -}}} +yystate24: +c = lexer.getChar() +switch { +default: +goto yyrule13 +case c == '=': +goto yystate4 +} -func yyactioninline(BEGIN func(yystartcondition)) {} +yystate25: +c = lexer.getChar() +switch { +default: +goto yyrule22 +case c == '=': +goto yystate4 +} + +yystate26: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'L': +goto yystate27 +case c == 'N': +goto yystate31 +case c == 'V': +goto yystate33 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'K' || c == 'M' || c >= 'O' && c <= 'U' || c >= 'W' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate27: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'E': +goto yystate28 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate28: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'R': +goto yystate29 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate29: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'T': +goto yystate30 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate30: +c = lexer.getChar() +switch { +default: +goto yyrule5 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate31: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'D': +goto yystate32 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'C' || c >= 'E' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate32: +c = lexer.getChar() +switch { +default: +goto yyrule13 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate33: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'G': +goto yystate34 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'F' || c >= 'H' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate34: +c = lexer.getChar() +switch { +default: +goto yyrule11 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate35: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'Y': +goto yystate36 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'X' || c == 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate36: +c = lexer.getChar() +switch { +default: +goto yyrule10 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate37: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'O': +goto yystate38 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'N' || c >= 'P' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate38: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'U': +goto yystate39 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate39: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'N': +goto yystate40 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate40: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'T': +goto yystate34 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate41: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'O': +goto yystate42 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'N' || c >= 'P' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate42: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'R': +goto yystate43 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate43: +c = lexer.getChar() +switch { +default: +goto yyrule7 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate44: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'F': +goto yystate45 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'E' || c >= 'G' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate45: +c = lexer.getChar() +switch { +default: +goto yyrule6 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate46: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'A': +goto yystate47 +case c == 'I': +goto yystate48 +case c >= '0' && c <= ':' || c >= 'B' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate47: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'X': +goto yystate34 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'W' || c == 'Y' || c == 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate48: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'N': +goto yystate34 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate49: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'R': +goto yystate32 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate50: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'E': +goto yystate51 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate51: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'R': +goto yystate52 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Q' || c >= 'S' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate52: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'M': +goto yystate53 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'L' || c >= 'N' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate53: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'A': +goto yystate54 +case c >= '0' && c <= ':' || c >= 'B' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate54: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'N': +goto yystate55 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate55: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'E': +goto yystate56 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'D' || c >= 'F' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate56: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'N': +goto yystate57 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'M' || c >= 'O' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate57: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'T': +goto yystate58 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate58: +c = lexer.getChar() +switch { +default: +goto yyrule9 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate59: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'U': +goto yystate60 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'T' || c >= 'V' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate60: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'M': +goto yystate34 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'L' || c >= 'N' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate61: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'I': +goto yystate62 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'H' || c >= 'J' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate62: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'T': +goto yystate63 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'S' || c >= 'U' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate63: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'H': +goto yystate64 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'G' || c >= 'I' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate64: +c = lexer.getChar() +switch { +default: +goto yyrule8 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate65: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'l': +goto yystate66 +case c == 'n': +goto yystate69 +case c == 'v': +goto yystate70 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'k' || c == 'm' || c >= 'o' && c <= 'u' || c >= 'w' && c <= 'z': +goto yystate23 +} + +yystate66: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'e': +goto yystate67 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': +goto yystate23 +} + +yystate67: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'r': +goto yystate68 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': +goto yystate23 +} + +yystate68: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 't': +goto yystate30 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': +goto yystate23 +} + +yystate69: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'd': +goto yystate32 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'c' || c >= 'e' && c <= 'z': +goto yystate23 +} + +yystate70: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'g': +goto yystate71 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'f' || c >= 'h' && c <= 'z': +goto yystate23 +} + +yystate71: +c = lexer.getChar() +switch { +default: +goto yyrule12 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z': +goto yystate23 +} + +yystate72: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'y': +goto yystate36 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'x' || c == 'z': +goto yystate23 +} + +yystate73: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'o': +goto yystate74 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': +goto yystate23 +} + +yystate74: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'u': +goto yystate75 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 't' || c >= 'v' && c <= 'z': +goto yystate23 +} + +yystate75: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'n': +goto yystate76 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': +goto yystate23 +} + +yystate76: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 't': +goto yystate71 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': +goto yystate23 +} + +yystate77: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'o': +goto yystate78 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'n' || c >= 'p' && c <= 'z': +goto yystate23 +} + +yystate78: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'r': +goto yystate43 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': +goto yystate23 +} + +yystate79: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'f': +goto yystate45 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'e' || c >= 'g' && c <= 'z': +goto yystate23 +} + +yystate80: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'a': +goto yystate81 +case c == 'i': +goto yystate82 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'h' || c >= 'j' && c <= 'z': +goto yystate23 +} + +yystate81: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'x': +goto yystate71 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'w' || c == 'y' || c == 'z': +goto yystate23 +} + +yystate82: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'n': +goto yystate71 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': +goto yystate23 +} + +yystate83: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'r': +goto yystate32 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': +goto yystate23 +} + +yystate84: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'e': +goto yystate85 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': +goto yystate23 +} + +yystate85: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'r': +goto yystate86 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'q' || c >= 's' && c <= 'z': +goto yystate23 +} + +yystate86: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'm': +goto yystate87 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'l' || c >= 'n' && c <= 'z': +goto yystate23 +} + +yystate87: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'a': +goto yystate88 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'b' && c <= 'z': +goto yystate23 +} + +yystate88: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'n': +goto yystate89 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': +goto yystate23 +} + +yystate89: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'e': +goto yystate90 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'd' || c >= 'f' && c <= 'z': +goto yystate23 +} + +yystate90: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'n': +goto yystate91 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'm' || c >= 'o' && c <= 'z': +goto yystate23 +} + +yystate91: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 't': +goto yystate58 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': +goto yystate23 +} + +yystate92: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'u': +goto yystate93 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 't' || c >= 'v' && c <= 'z': +goto yystate23 +} + +yystate93: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'm': +goto yystate71 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'l' || c >= 'n' && c <= 'z': +goto yystate23 +} + +yystate94: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'i': +goto yystate95 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'h' || c >= 'j' && c <= 'z': +goto yystate23 +} + +yystate95: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 't': +goto yystate96 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 's' || c >= 'u' && c <= 'z': +goto yystate23 +} + +yystate96: +c = lexer.getChar() +switch { +default: +goto yyrule18 +case c == 'h': +goto yystate64 +case c >= '0' && c <= ':' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'g' || c >= 'i' && c <= 'z': +goto yystate23 +} + +goto yystate97 // silence unused label error +yystate97: +c = lexer.getChar() +yystart97: +switch { +default: +goto yyabort +case c == '*': +goto yystate99 +case c >= '\x01' && c <= ')' || c >= '+' && c <= 'ÿ': +goto yystate98 +} + +yystate98: +c = lexer.getChar() +goto yyrule3 + +yystate99: +c = lexer.getChar() +switch { +default: +goto yyrule3 +case c == '/': +goto yystate100 +} + +yystate100: +c = lexer.getChar() +goto yyrule2 + +yyrule1: // "/*" +{ + currentState = S_COMMENTS +goto yystate0 +} +yyrule2: // "*/" +{ + currentState = S_INITIAL +goto yystate0 +} +yyrule3: // .|\n +{ + /* ignore chars within multi-line comments */ +goto yystate0 +} +yyrule4: // \/\/[^\r\n]*\n +{ + /* gobble up one-line comments */ +goto yystate0 +} +yyrule5: // ALERT|alert +{ + return ALERT +} +yyrule6: // IF|if +{ + return IF +} +yyrule7: // FOR|for +{ + return FOR +} +yyrule8: // WITH|with +{ + return WITH +} +yyrule9: // PERMANENT|permanent +{ + return PERMANENT +} +yyrule10: // BY|by +{ + return GROUP_OP +} +yyrule11: // AVG|SUM|MAX|MIN|COUNT +{ + lval.str = lexer.token(); return AGGR_OP +goto yystate0 +} +yyrule12: // avg|sum|max|min|count +{ + lval.str = strings.ToUpper(lexer.token()); return AGGR_OP +goto yystate0 +} +yyrule13: // \<|>|AND|OR|and|or +{ + lval.str = strings.ToUpper(lexer.token()); return CMP_OP +goto yystate0 +} +yyrule14: // ==|!=|>=|<= +{ + lval.str = lexer.token(); return CMP_OP +goto yystate0 +} +yyrule15: // [+\-] +{ + lval.str = lexer.token(); return ADDITIVE_OP +goto yystate0 +} +yyrule16: // [*/%] +{ + lval.str = lexer.token(); return MULT_OP +goto yystate0 +} +yyrule17: // {D}+{U} +{ + lval.str = lexer.token(); return DURATION +goto yystate0 +} +yyrule18: // {L}({L}|{D})* +{ + lval.str = lexer.token(); return IDENTIFIER +goto yystate0 +} +yyrule19: // \-?{D}+(\.{D}*)? +{ + num, err := strconv.ParseFloat(lexer.token(), 64); + if (err != nil && err.(*strconv.NumError).Err == strconv.ErrSyntax) { + panic("Invalid float") + } + lval.num = clientmodel.SampleValue(num) + return NUMBER +} +yyrule20: // \"(\\.|[^\\"])*\" +{ + lval.str = lexer.token()[1:len(lexer.token()) - 1]; return STRING +goto yystate0 +} +yyrule21: // \'(\\.|[^\\'])*\' +{ + lval.str = lexer.token()[1:len(lexer.token()) - 1]; return STRING +goto yystate0 +} +yyrule22: // [{}\[\]()=,] +{ + return int(lexer.buf[0]) +} +yyrule23: // [\t\n\r ] +{ + /* gobble up any whitespace */ +goto yystate0 +} +panic("unreachable") + +goto yyabort // silence unused label error + +yyabort: // no lexem recognized + + lexer.empty = true + return int(c) +} diff --git a/rules/load.go b/rules/load.go index 7bd988e2f..1c211db0c 100644 --- a/rules/load.go +++ b/rules/load.go @@ -14,69 +14,87 @@ package rules import ( + "bufio" "errors" "fmt" - "github.com/prometheus/prometheus/rules/ast" "io" + "log" "os" "strings" - "sync" -) -// GoLex sadly needs these global variables for storing temporary token/parsing information. -var ( - yylval *yySymType // For storing extra token information, like the contents of a string. - yyline int // Line number within the current file or buffer. - yypos int // Character position within the current line. - parseMutex sync.Mutex // Mutex protecting the parsing-related global state defined above. + "github.com/prometheus/prometheus/rules/ast" ) type RulesLexer struct { - errors []string // Errors encountered during parsing. - startToken int // Dummy token to simulate multiple start symbols (see below). - parsedRules []Rule // Parsed full rules. - parsedExpr ast.Node // Parsed single expression. -} + // Errors encountered during parsing. + errors []string + // Dummy token to simulate multiple start symbols (see below). + startToken int + // Parsed full rules. + parsedRules []Rule + // Parsed single expression. + parsedExpr ast.Node -func (lexer *RulesLexer) Lex(lval *yySymType) int { - yylval = lval + // Current character. + current byte + // Current token buffer. + buf []byte + // Input text. + src *bufio.Reader + // Whether we have a current char. + empty bool - // We simulate multiple start symbols for closely-related grammars via dummy tokens. See - // http://www.gnu.org/software/bison/manual/html_node/Multiple-start_002dsymbols.html - // Reason: we want to be able to parse lists of named rules as well as single expressions. - if lexer.startToken != 0 { - startToken := lexer.startToken - lexer.startToken = 0 - return startToken - } - - tokenType := yylex() - return tokenType + // Current input line. + line int + // Current character position within the current input line. + pos int } func (lexer *RulesLexer) Error(errorStr string) { - err := fmt.Sprintf("Error parsing rules at line %v, char %v: %v", yyline, yypos, errorStr) + err := fmt.Sprintf("Error parsing rules at line %v, char %v: %v", lexer.line, lexer.pos, errorStr) lexer.errors = append(lexer.errors, err) } -func LoadFromReader(rulesReader io.Reader, singleExpr bool) (interface{}, error) { - parseMutex.Lock() - defer parseMutex.Unlock() +func (lexer *RulesLexer) getChar() byte { + if lexer.current != 0 { + lexer.buf = append(lexer.buf, lexer.current) + } + lexer.current = 0 + if b, err := lexer.src.ReadByte(); err == nil { + if b == '\n' { + lexer.line++ + lexer.pos = 0 + } else { + lexer.pos++ + } + lexer.current = b + } else if err != io.EOF { + log.Fatal(err) + } + return lexer.current +} - yyin = rulesReader - yypos = 1 - yyline = 1 - yydata = "" - yytext = "" +func (lexer *RulesLexer) token() string { + return string(lexer.buf) +} +func newRulesLexer(src io.Reader, singleExpr bool) *RulesLexer { lexer := &RulesLexer{ startToken: START_RULES, + src: bufio.NewReader(src), + pos: 1, + line: 1, } if singleExpr { lexer.startToken = START_EXPRESSION } + lexer.getChar() + return lexer +} +func LoadFromReader(rulesReader io.Reader, singleExpr bool) (interface{}, error) { + lexer := newRulesLexer(rulesReader, singleExpr) ret := yyParse(lexer) if ret != 0 && len(lexer.errors) == 0 { lexer.Error("Unknown parser error") diff --git a/rules/parser.y b/rules/parser.y index 30762132b..c579df75a 100644 --- a/rules/parser.y +++ b/rules/parser.y @@ -14,10 +14,10 @@ %{ package rules -import ( - clientmodel "github.com/prometheus/client_golang/model" + import ( + clientmodel "github.com/prometheus/client_golang/model" - import "github.com/prometheus/prometheus/rules/ast" + "github.com/prometheus/prometheus/rules/ast" ) %} diff --git a/rules/parser.y.go b/rules/parser.y.go index 3305933a8..c8dbad4d4 100644 --- a/rules/parser.y.go +++ b/rules/parser.y.go @@ -1,22 +1,25 @@ -//line parser.y:15 -package rules +//line parser.y:15 + package rules import __yyfmt__ "fmt" - //line parser.y:15 -import clientmodel "github.com/prometheus/client_golang/model" -import "github.com/prometheus/prometheus/rules/ast" + + import ( + clientmodel "github.com/prometheus/client_golang/model" -//line parser.y:21 + "github.com/prometheus/prometheus/rules/ast" + ) + +//line parser.y:24 type yySymType struct { - yys int - num clientmodel.SampleValue - str string - ruleNode ast.Node - ruleNodeSlice []ast.Node - boolean bool - labelNameSlice clientmodel.LabelNames - labelSet clientmodel.LabelSet + yys int + num clientmodel.SampleValue + str string + ruleNode ast.Node + ruleNodeSlice []ast.Node + boolean bool + labelNameSlice clientmodel.LabelNames + labelSet clientmodel.LabelSet } const START_RULES = 57346 @@ -61,7 +64,8 @@ const yyEofCode = 1 const yyErrCode = 2 const yyMaxDepth = 200 -//line parser.y:188 +//line parser.y:191 + //line yacctab:1 var yyExca = []int{ @@ -394,208 +398,134 @@ yydefault: switch yynt { case 5: - //line parser.y:66 - { - yylex.(*RulesLexer).parsedExpr = yyS[yypt-0].ruleNode - } + //line parser.y:69 + { yylex.(*RulesLexer).parsedExpr = yyS[yypt-0].ruleNode } case 6: - //line parser.y:70 + //line parser.y:73 { - rule, err := CreateRecordingRule(yyS[yypt-3].str, yyS[yypt-2].labelSet, yyS[yypt-0].ruleNode, yyS[yypt-4].boolean) - if err != nil { - yylex.Error(err.Error()) - return 1 - } - yylex.(*RulesLexer).parsedRules = append(yylex.(*RulesLexer).parsedRules, rule) - } + rule, err := CreateRecordingRule(yyS[yypt-3].str, yyS[yypt-2].labelSet, yyS[yypt-0].ruleNode, yyS[yypt-4].boolean) + if err != nil { yylex.Error(err.Error()); return 1 } + yylex.(*RulesLexer).parsedRules = append(yylex.(*RulesLexer).parsedRules, rule) + } case 7: - //line parser.y:76 + //line parser.y:79 { - rule, err := CreateAlertingRule(yyS[yypt-5].str, yyS[yypt-3].ruleNode, yyS[yypt-2].str, yyS[yypt-0].labelSet) - if err != nil { - yylex.Error(err.Error()) - return 1 - } - yylex.(*RulesLexer).parsedRules = append(yylex.(*RulesLexer).parsedRules, rule) - } + rule, err := CreateAlertingRule(yyS[yypt-5].str, yyS[yypt-3].ruleNode, yyS[yypt-2].str, yyS[yypt-0].labelSet) + if err != nil { yylex.Error(err.Error()); return 1 } + yylex.(*RulesLexer).parsedRules = append(yylex.(*RulesLexer).parsedRules, rule) + } case 8: - //line parser.y:84 - { - yyVAL.str = "0s" - } + //line parser.y:87 + { yyVAL.str = "0s" } case 9: - //line parser.y:86 - { - yyVAL.str = yyS[yypt-0].str - } + //line parser.y:89 + { yyVAL.str = yyS[yypt-0].str } case 10: - //line parser.y:90 - { - yyVAL.boolean = false - } + //line parser.y:93 + { yyVAL.boolean = false } case 11: - //line parser.y:92 - { - yyVAL.boolean = true - } + //line parser.y:95 + { yyVAL.boolean = true } case 12: - //line parser.y:96 - { - yyVAL.labelSet = clientmodel.LabelSet{} - } + //line parser.y:99 + { yyVAL.labelSet = clientmodel.LabelSet{} } case 13: - //line parser.y:98 - { - yyVAL.labelSet = yyS[yypt-1].labelSet - } + //line parser.y:101 + { yyVAL.labelSet = yyS[yypt-1].labelSet } case 14: - //line parser.y:100 - { - yyVAL.labelSet = clientmodel.LabelSet{} - } - case 15: //line parser.y:103 - { - yyVAL.labelSet = yyS[yypt-0].labelSet - } + { yyVAL.labelSet = clientmodel.LabelSet{} } + case 15: + //line parser.y:106 + { yyVAL.labelSet = yyS[yypt-0].labelSet } case 16: - //line parser.y:105 - { - for k, v := range yyS[yypt-0].labelSet { - yyVAL.labelSet[k] = v - } - } + //line parser.y:108 + { for k, v := range yyS[yypt-0].labelSet { yyVAL.labelSet[k] = v } } case 17: - //line parser.y:109 - { - yyVAL.labelSet = clientmodel.LabelSet{clientmodel.LabelName(yyS[yypt-2].str): clientmodel.LabelValue(yyS[yypt-0].str)} - } + //line parser.y:112 + { yyVAL.labelSet = clientmodel.LabelSet{ clientmodel.LabelName(yyS[yypt-2].str): clientmodel.LabelValue(yyS[yypt-0].str) } } case 18: - //line parser.y:114 - { - yyVAL.ruleNode = yyS[yypt-1].ruleNode - } + //line parser.y:117 + { yyVAL.ruleNode = yyS[yypt-1].ruleNode } case 19: - //line parser.y:116 - { - yyS[yypt-0].labelSet[clientmodel.MetricNameLabel] = clientmodel.LabelValue(yyS[yypt-1].str) - yyVAL.ruleNode = ast.NewVectorLiteral(yyS[yypt-0].labelSet) - } + //line parser.y:119 + { yyS[yypt-0].labelSet[clientmodel.MetricNameLabel] = clientmodel.LabelValue(yyS[yypt-1].str); yyVAL.ruleNode = ast.NewVectorLiteral(yyS[yypt-0].labelSet) } case 20: - //line parser.y:118 + //line parser.y:121 { - var err error - yyVAL.ruleNode, err = NewFunctionCall(yyS[yypt-3].str, yyS[yypt-1].ruleNodeSlice) - if err != nil { - yylex.Error(err.Error()) - return 1 - } - } + var err error + yyVAL.ruleNode, err = NewFunctionCall(yyS[yypt-3].str, yyS[yypt-1].ruleNodeSlice) + if err != nil { yylex.Error(err.Error()); return 1 } + } case 21: - //line parser.y:124 + //line parser.y:127 { - var err error - yyVAL.ruleNode, err = NewFunctionCall(yyS[yypt-2].str, []ast.Node{}) - if err != nil { - yylex.Error(err.Error()) - return 1 - } - } + var err error + yyVAL.ruleNode, err = NewFunctionCall(yyS[yypt-2].str, []ast.Node{}) + if err != nil { yylex.Error(err.Error()); return 1 } + } case 22: - //line parser.y:130 + //line parser.y:133 { - var err error - yyVAL.ruleNode, err = NewMatrix(yyS[yypt-3].ruleNode, yyS[yypt-1].str) - if err != nil { - yylex.Error(err.Error()) - return 1 - } - } + var err error + yyVAL.ruleNode, err = NewMatrix(yyS[yypt-3].ruleNode, yyS[yypt-1].str) + if err != nil { yylex.Error(err.Error()); return 1 } + } case 23: - //line parser.y:136 + //line parser.y:139 { - var err error - yyVAL.ruleNode, err = NewVectorAggregation(yyS[yypt-4].str, yyS[yypt-2].ruleNode, yyS[yypt-0].labelNameSlice) - if err != nil { - yylex.Error(err.Error()) - return 1 - } - } + var err error + yyVAL.ruleNode, err = NewVectorAggregation(yyS[yypt-4].str, yyS[yypt-2].ruleNode, yyS[yypt-0].labelNameSlice) + if err != nil { yylex.Error(err.Error()); return 1 } + } case 24: - //line parser.y:144 + //line parser.y:147 { - var err error - yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode) - if err != nil { - yylex.Error(err.Error()) - return 1 - } - } + var err error + yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode) + if err != nil { yylex.Error(err.Error()); return 1 } + } case 25: - //line parser.y:150 + //line parser.y:153 { - var err error - yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode) - if err != nil { - yylex.Error(err.Error()) - return 1 - } - } + var err error + yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode) + if err != nil { yylex.Error(err.Error()); return 1 } + } case 26: - //line parser.y:156 + //line parser.y:159 { - var err error - yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode) - if err != nil { - yylex.Error(err.Error()) - return 1 - } - } + var err error + yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode) + if err != nil { yylex.Error(err.Error()); return 1 } + } case 27: - //line parser.y:162 - { - yyVAL.ruleNode = ast.NewScalarLiteral(yyS[yypt-0].num) - } + //line parser.y:165 + { yyVAL.ruleNode = ast.NewScalarLiteral(yyS[yypt-0].num)} case 28: - //line parser.y:166 - { - yyVAL.labelNameSlice = clientmodel.LabelNames{} - } + //line parser.y:169 + { yyVAL.labelNameSlice = clientmodel.LabelNames{} } case 29: - //line parser.y:168 - { - yyVAL.labelNameSlice = yyS[yypt-1].labelNameSlice - } + //line parser.y:171 + { yyVAL.labelNameSlice = yyS[yypt-1].labelNameSlice } case 30: - //line parser.y:172 - { - yyVAL.labelNameSlice = clientmodel.LabelNames{clientmodel.LabelName(yyS[yypt-0].str)} - } + //line parser.y:175 + { yyVAL.labelNameSlice = clientmodel.LabelNames{clientmodel.LabelName(yyS[yypt-0].str)} } case 31: - //line parser.y:174 - { - yyVAL.labelNameSlice = append(yyVAL.labelNameSlice, clientmodel.LabelName(yyS[yypt-0].str)) - } + //line parser.y:177 + { yyVAL.labelNameSlice = append(yyVAL.labelNameSlice, clientmodel.LabelName(yyS[yypt-0].str)) } case 32: - //line parser.y:178 - { - yyVAL.ruleNodeSlice = []ast.Node{yyS[yypt-0].ruleNode} - } + //line parser.y:181 + { yyVAL.ruleNodeSlice = []ast.Node{yyS[yypt-0].ruleNode} } case 33: - //line parser.y:180 - { - yyVAL.ruleNodeSlice = append(yyVAL.ruleNodeSlice, yyS[yypt-0].ruleNode) - } + //line parser.y:183 + { yyVAL.ruleNodeSlice = append(yyVAL.ruleNodeSlice, yyS[yypt-0].ruleNode) } case 34: - //line parser.y:184 - { - yyVAL.ruleNode = yyS[yypt-0].ruleNode - } + //line parser.y:187 + { yyVAL.ruleNode = yyS[yypt-0].ruleNode } case 35: - //line parser.y:186 - { - yyVAL.ruleNode = ast.NewStringLiteral(yyS[yypt-0].str) - } + //line parser.y:189 + { yyVAL.ruleNode = ast.NewStringLiteral(yyS[yypt-0].str) } } goto yystack /* stack new state and value */ } diff --git a/rules/rules_test.go b/rules/rules_test.go index 5a63f8f75..502f40d56 100644 --- a/rules/rules_test.go +++ b/rules/rules_test.go @@ -123,6 +123,17 @@ func TestExpressions(t *testing.T) { }, fullRanges: 0, intervalRanges: 8, + }, { + expr: ` + // Test comment. + SUM(http_requests) BY /* comments shouldn't + have any effect */ (job) // another comment`, + output: []string{ + `http_requests{job="api-server"} => 1000 @[%v]`, + `http_requests{job="app-server"} => 2600 @[%v]`, + }, + fullRanges: 0, + intervalRanges: 8, }, { expr: `COUNT(http_requests) BY (job)`, output: []string{ @@ -448,7 +459,7 @@ var ruleTests = []struct { { inputFile: "syntax_error.rules", shouldFail: true, - errContains: "Error parsing rules at line 3", + errContains: "Error parsing rules at line 5", }, { inputFile: "non_vector.rules",