go-common/app/admin/ep/melloi/service/proto/oneof.go

141 lines
3.8 KiB
Go
Raw Normal View History

2019-04-22 10:49:16 +00:00
// Copyright (c) 2017 Ernest Micklei
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package proto
import (
"text/scanner"
)
// Oneof is a field alternate.
type Oneof struct {
Position scanner.Position
Comment *Comment
Name string
Elements []Visitee
Parent Visitee
}
// addElement is part of elementContainer
func (o *Oneof) addElement(v Visitee) {
v.parent(o)
o.Elements = append(o.Elements, v)
}
// elements is part of elementContainer
func (o *Oneof) elements() []Visitee {
return o.Elements
}
// takeLastComment is part of elementContainer
// removes and returns the last element of the list if it is a Comment.
func (o *Oneof) takeLastComment(expectedOnLine int) (last *Comment) {
last, o.Elements = takeLastCommentIfEndsOnLine(o.Elements, expectedOnLine)
return last
}
// parse expects:
// oneofName "{" { oneofField | emptyStatement } "}"
func (o *Oneof) parse(p *Parser) error {
pos, tok, lit := p.next()
if tok != tIDENT {
if !isKeyword(tok) {
return p.unexpected(lit, "oneof identifier", o)
}
}
o.Name = lit
pos, tok, lit = p.next()
if tok != tLEFTCURLY {
return p.unexpected(lit, "oneof opening {", o)
}
for {
pos, tok, lit = p.nextTypeName()
switch tok {
case tCOMMENT:
if com := mergeOrReturnComment(o.elements(), lit, pos); com != nil { // not merged?
o.addElement(com)
}
case tIDENT:
f := newOneOfField()
f.Position = pos
f.Comment, o.Elements = takeLastCommentIfEndsOnLine(o.elements(), pos.Line-1) // TODO call takeLastComment instead?
f.Type = lit
if err := parseFieldAfterType(f.Field, p); err != nil {
return err
}
o.addElement(f)
case tGROUP:
g := new(Group)
g.Position = pos
g.Comment, o.Elements = takeLastCommentIfEndsOnLine(o.elements(), pos.Line-1)
if err := g.parse(p); err != nil {
return err
}
o.addElement(g)
case tOPTION:
opt := new(Option)
opt.Position = pos
opt.Comment, o.Elements = takeLastCommentIfEndsOnLine(o.elements(), pos.Line-1)
if err := opt.parse(p); err != nil {
return err
}
o.addElement(opt)
case tSEMICOLON:
maybeScanInlineComment(p, o)
// continue
default:
goto done
}
}
done:
if tok != tRIGHTCURLY {
return p.unexpected(lit, "oneof closing }", o)
}
return nil
}
// Accept dispatches the call to the visitor.
func (o *Oneof) Accept(v Visitor) {
v.VisitOneof(o)
}
// OneOfField is part of Oneof.
type OneOfField struct {
*Field
}
func newOneOfField() *OneOfField { return &OneOfField{Field: new(Field)} }
// Accept dispatches the call to the visitor.
func (o *OneOfField) Accept(v Visitor) {
v.VisitOneofField(o)
}
// Doc is part of Documented
// Note: although Doc() is defined on Field, it must be implemented here as well.
func (o *OneOfField) Doc() *Comment {
return o.Comment
}
func (o *Oneof) parent(v Visitee) { o.Parent = v }