1 %{ 2 // Copyright 2017 The Prometheus Authors 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package textparse 16 17 import ( 18 "fmt" 19 ) 20 21 const ( 22 sInit = iota 23 sComment 24 sMeta1 25 sMeta2 26 sLabels 27 sLValue 28 sValue 29 sTimestamp 30 ) 31 32 // Lex is called by the parser generated by "go tool yacc" to obtain each 33 // token. The method is opened before the matching rules block and closed at 34 // the end of the file. func(l * promlexer)35func (l *promlexer) Lex() token { 36 if l.i >= len(l.b) { 37 return tEOF 38 } 39 c := l.b[l.i] 40 l.start = l.i 41 42 %} 43 44 D [0-9] 45 L [a-zA-Z_] 46 M [a-zA-Z_:] 47 C [^\n] 48 49 %x sComment sMeta1 sMeta2 sLabels sLValue sValue sTimestamp 50 51 %yyc c 52 %yyn c = l.next() 53 %yyt l.state 54 55 56 %% 57 58 \0 return tEOF 59 \n l.state = sInit; return tLinebreak 60 <*>[ \t]+ return tWhitespace 61 62 #[ \t]+ l.state = sComment 63 # return l.consumeComment() 64 <sComment>HELP[\t ]+ l.state = sMeta1; return tHelp 65 <sComment>TYPE[\t ]+ l.state = sMeta1; return tType 66 <sMeta1>{M}({M}|{D})* l.state = sMeta2; return tMName 67 <sMeta2>{C}* l.state = sInit; return tText 68 69 {M}({M}|{D})* l.state = sValue; return tMName 70 <sValue>\{ l.state = sLabels; return tBraceOpen 71 <sLabels>{L}({L}|{D})* return tLName 72 <sLabels>\} l.state = sValue; return tBraceClose 73 <sLabels>= l.state = sLValue; return tEqual 74 <sLabels>, return tComma 75 <sLValue>\"(\\.|[^\\"])*\" l.state = sLabels; return tLValue 76 <sValue>[^{ \t\n]+ l.state = sTimestamp; return tValue 77 <sTimestamp>{D}+ return tTimestamp 78 <sTimestamp>\n l.state = sInit; return tLinebreak 79 80 %% 81 // Workaround to gobble up comments that started with a HELP or TYPE 82 // prefix. We just consume all characters until we reach a newline. 83 // This saves us from adding disproportionate complexity to the parser. 84 if l.state == sComment { 85 return l.consumeComment() 86 } 87 return tInvalid 88 } 89 90 func (l *promlexer) consumeComment() token { 91 for c := l.cur(); ; c = l.next() { 92 switch c { 93 case 0: 94 return tEOF 95 case '\n': 96 l.state = sInit 97 return tComment 98 } 99 } 100 } 101