...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package proto
25
26 import (
27 "text/scanner"
28 )
29
30
31 type Enum struct {
32 Position scanner.Position
33 Comment *Comment
34 Name string
35 Elements []Visitee
36 Parent Visitee
37 }
38
39
40 func (e *Enum) Accept(v Visitor) {
41 v.VisitEnum(e)
42 }
43
44
45 func (e *Enum) Doc() *Comment {
46 return e.Comment
47 }
48
49
50 func (e *Enum) addElement(v Visitee) {
51 v.parent(e)
52 e.Elements = append(e.Elements, v)
53 }
54
55
56 func (e *Enum) elements() []Visitee {
57 return e.Elements
58 }
59
60
61
62 func (e *Enum) takeLastComment(expectedOnLine int) (last *Comment) {
63 last, e.Elements = takeLastCommentIfEndsOnLine(e.Elements, expectedOnLine)
64 return
65 }
66
67 func (e *Enum) parse(p *Parser) error {
68 pos, tok, lit := p.next()
69 if tok != tIDENT {
70 if !isKeyword(tok) {
71 return p.unexpected(lit, "enum identifier", e)
72 }
73 }
74 e.Name = lit
75 consumeCommentFor(p, e)
76 _, tok, lit = p.next()
77 if tok != tLEFTCURLY {
78 return p.unexpected(lit, "enum opening {", e)
79 }
80 for {
81 pos, tok, lit = p.next()
82 switch tok {
83 case tCOMMENT:
84 if com := mergeOrReturnComment(e.elements(), lit, pos); com != nil {
85 e.addElement(com)
86 }
87 case tOPTION:
88 v := new(Option)
89 v.Position = pos
90 v.Comment = e.takeLastComment(pos.Line)
91 err := v.parse(p)
92 if err != nil {
93 return err
94 }
95 e.addElement(v)
96 case tRIGHTCURLY, tEOF:
97 goto done
98 case tSEMICOLON:
99 maybeScanInlineComment(p, e)
100 case tRESERVED:
101 r := new(Reserved)
102 r.Position = pos
103 r.Comment = e.takeLastComment(pos.Line - 1)
104 if err := r.parse(p); err != nil {
105 return err
106 }
107 e.addElement(r)
108 default:
109 p.nextPut(pos, tok, lit)
110 f := new(EnumField)
111 f.Position = pos
112 f.Comment = e.takeLastComment(pos.Line - 1)
113 err := f.parse(p)
114 if err != nil {
115 return err
116 }
117 e.addElement(f)
118 }
119 }
120 done:
121 if tok != tRIGHTCURLY {
122 return p.unexpected(lit, "enum closing }", e)
123 }
124 return nil
125 }
126
127
128 func (e *Enum) parent(p Visitee) { e.Parent = p }
129
130
131 type EnumField struct {
132 Position scanner.Position
133 Comment *Comment
134 Name string
135 Integer int
136
137 ValueOption *Option
138 Elements []Visitee
139 InlineComment *Comment
140 Parent Visitee
141 }
142
143
144 func (f *EnumField) elements() []Visitee {
145 return f.Elements
146 }
147
148
149
150 func (f *EnumField) takeLastComment(expectedOnLine int) (last *Comment) {
151 last, f.Elements = takeLastCommentIfEndsOnLine(f.Elements, expectedOnLine)
152 return
153 }
154
155
156 func (f *EnumField) Accept(v Visitor) {
157 v.VisitEnumField(f)
158 }
159
160
161 func (f *EnumField) inlineComment(c *Comment) {
162 f.InlineComment = c
163 }
164
165
166 func (f *EnumField) Doc() *Comment {
167 return f.Comment
168 }
169
170 func (f *EnumField) parse(p *Parser) error {
171 _, tok, lit := p.nextIdentifier()
172 if tok != tIDENT {
173 if !isKeyword(tok) {
174 return p.unexpected(lit, "enum field identifier", f)
175 }
176 }
177 f.Name = lit
178 pos, tok, lit := p.next()
179 if tok != tEQUALS {
180 return p.unexpected(lit, "enum field =", f)
181 }
182 i, err := p.nextInteger()
183 if err != nil {
184 return p.unexpected(err.Error(), "enum field integer", f)
185 }
186 f.Integer = i
187 pos, tok, lit = p.next()
188 if tok == tLEFTSQUARE {
189 for {
190 o := new(Option)
191 o.Position = pos
192 o.IsEmbedded = true
193 err := o.parse(p)
194 if err != nil {
195 return err
196 }
197
198 f.ValueOption = o
199 f.addElement(o)
200 pos, tok, lit = p.next()
201 if tok == tCOMMA {
202 continue
203 }
204 if tok == tRIGHTSQUARE {
205 break
206 }
207 }
208 }
209 if tSEMICOLON == tok {
210 p.nextPut(pos, tok, lit)
211 }
212 return nil
213 }
214
215
216 func (f *EnumField) addElement(v Visitee) {
217 v.parent(f)
218 f.Elements = append(f.Elements, v)
219 }
220
221 func (f *EnumField) parent(v Visitee) { f.Parent = v }
222
223
224 func (f *EnumField) IsDeprecated() bool {
225 for _, each := range f.Elements {
226 if opt, ok := each.(*Option); ok {
227 if opt.Name == optionNameDeprecated {
228 return opt.Constant.Source == "true"
229 }
230 }
231 }
232 return false
233 }
234
View as plain text