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)35 func (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