/* Copyright 2013 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 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] L [a-zA-Z_] M [a-zA-Z_:] U [smhdwy] %x S_COMMENTS %yyc c %yyn c = lexer.getChar() %yyt currentState %% lexer.buf = lexer.buf[:0] // The code before the first rule executed before every scan cycle (rule #0 / state 0 action) "/*" currentState = S_COMMENTS "*/" currentState = S_INITIAL .|\n /* ignore chars within multi-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 SUMMARY|summary return SUMMARY DESCRIPTION|description return DESCRIPTION PERMANENT|permanent return PERMANENT BY|by return GROUP_OP KEEPING_EXTRA|keeping_extra return KEEPING_EXTRA 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} lval.str = lexer.token(); return DURATION {L}({L}|{D})* lval.str = lexer.token(); return IDENTIFIER {M}({M}|{D})* lval.str = lexer.token(); return METRICNAME \-?{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 \"(\\.|[^\\"])*\" lval.str = lexer.token()[1:len(lexer.token()) - 1]; return STRING \'(\\.|[^\\'])*\' lval.str = lexer.token()[1:len(lexer.token()) - 1]; return STRING [{}\[\]()=,] return int(lexer.buf[0]) [\t\n\r ] /* gobble up any whitespace */ %% lexer.empty = true return int(c) }