...
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 Message struct {
32 Position scanner.Position
33 Comment *Comment
34 Name string
35 IsExtend bool
36 Elements []Visitee
37 Parent Visitee
38 }
39
40 func (m *Message) groupName() string {
41 if m.IsExtend {
42 return "extend"
43 }
44 return "message"
45 }
46
47
48 func (m *Message) parse(p *Parser) error {
49 _, tok, lit := p.nextIdentifier()
50 if tok != tIDENT {
51 if !isKeyword(tok) {
52 return p.unexpected(lit, m.groupName()+" identifier", m)
53 }
54 }
55 m.Name = lit
56 consumeCommentFor(p, m)
57 _, tok, lit = p.next()
58 if tok != tLEFTCURLY {
59 return p.unexpected(lit, m.groupName()+" opening {", m)
60 }
61 return parseMessageBody(p, m)
62 }
63
64
65 func parseMessageBody(p *Parser, c elementContainer) error {
66 var (
67 pos scanner.Position
68 tok token
69 lit string
70 )
71 for {
72 pos, tok, lit = p.next()
73 switch {
74 case isComment(lit):
75 if com := mergeOrReturnComment(c.elements(), lit, pos); com != nil {
76 c.addElement(com)
77 }
78 case tENUM == tok:
79 e := new(Enum)
80 e.Position = pos
81 e.Comment = c.takeLastComment(pos.Line - 1)
82 if err := e.parse(p); err != nil {
83 return err
84 }
85 c.addElement(e)
86 case tMESSAGE == tok:
87 msg := new(Message)
88 msg.Position = pos
89 msg.Comment = c.takeLastComment(pos.Line - 1)
90 if err := msg.parse(p); err != nil {
91 return err
92 }
93 c.addElement(msg)
94 case tOPTION == tok:
95 o := new(Option)
96 o.Position = pos
97 o.Comment = c.takeLastComment(pos.Line - 1)
98 if err := o.parse(p); err != nil {
99 return err
100 }
101 c.addElement(o)
102 case tONEOF == tok:
103 o := new(Oneof)
104 o.Position = pos
105 o.Comment = c.takeLastComment(pos.Line - 1)
106 if err := o.parse(p); err != nil {
107 return err
108 }
109 c.addElement(o)
110 case tMAP == tok:
111 f := newMapField()
112 f.Position = pos
113 f.Comment = c.takeLastComment(pos.Line - 1)
114 if err := f.parse(p); err != nil {
115 return err
116 }
117 c.addElement(f)
118 case tRESERVED == tok:
119 r := new(Reserved)
120 r.Position = pos
121 r.Comment = c.takeLastComment(pos.Line - 1)
122 if err := r.parse(p); err != nil {
123 return err
124 }
125 c.addElement(r)
126
127 case tOPTIONAL == tok || tREPEATED == tok || tREQUIRED == tok:
128
129 prevTok := tok
130 pos, tok, lit = p.next()
131 if tGROUP == tok {
132 g := new(Group)
133 g.Position = pos
134 g.Comment = c.takeLastComment(pos.Line - 1)
135 g.Optional = prevTok == tOPTIONAL
136 g.Repeated = prevTok == tREPEATED
137 g.Required = prevTok == tREQUIRED
138 if err := g.parse(p); err != nil {
139 return err
140 }
141 c.addElement(g)
142 } else {
143
144 p.nextPut(pos, tok, lit)
145 f := newNormalField()
146 f.Type = lit
147 f.Position = pos
148 f.Comment = c.takeLastComment(pos.Line - 1)
149 f.Optional = prevTok == tOPTIONAL
150 f.Repeated = prevTok == tREPEATED
151 f.Required = prevTok == tREQUIRED
152 if err := f.parse(p); err != nil {
153 return err
154 }
155 c.addElement(f)
156 }
157 case tGROUP == tok:
158 g := new(Group)
159 g.Position = pos
160 g.Comment = c.takeLastComment(pos.Line - 1)
161 if err := g.parse(p); err != nil {
162 return err
163 }
164 c.addElement(g)
165 case tEXTENSIONS == tok:
166 e := new(Extensions)
167 e.Position = pos
168 e.Comment = c.takeLastComment(pos.Line - 1)
169 if err := e.parse(p); err != nil {
170 return err
171 }
172 c.addElement(e)
173 case tEXTEND == tok:
174 e := new(Message)
175 e.Position = pos
176 e.Comment = c.takeLastComment(pos.Line - 1)
177 e.IsExtend = true
178 if err := e.parse(p); err != nil {
179 return err
180 }
181 c.addElement(e)
182
183 case tRIGHTCURLY == tok || tEOF == tok:
184 goto done
185 case tSEMICOLON == tok:
186 maybeScanInlineComment(p, c)
187
188 default:
189
190 p.nextPut(pos, tok, lit)
191 f := newNormalField()
192 f.Position = pos
193 f.Comment = c.takeLastComment(pos.Line - 1)
194 if err := f.parse(p); err != nil {
195 return err
196 }
197 c.addElement(f)
198 }
199 }
200 done:
201 if tok != tRIGHTCURLY {
202 return p.unexpected(lit, "extend|message|group closing }", c)
203 }
204 return nil
205 }
206
207
208 func (m *Message) Accept(v Visitor) {
209 v.VisitMessage(m)
210 }
211
212
213 func (m *Message) addElement(v Visitee) {
214 v.parent(m)
215 m.Elements = append(m.Elements, v)
216 }
217
218
219 func (m *Message) elements() []Visitee {
220 return m.Elements
221 }
222
223 func (m *Message) takeLastComment(expectedOnLine int) (last *Comment) {
224 last, m.Elements = takeLastCommentIfEndsOnLine(m.Elements, expectedOnLine)
225 return
226 }
227
228
229 func (m *Message) Doc() *Comment {
230 return m.Comment
231 }
232
233 func (m *Message) parent(v Visitee) { m.Parent = v }
234
View as plain text