...

Source file src/github.com/emicklei/proto/oneof.go

Documentation: github.com/emicklei/proto

     1  // Copyright (c) 2017 Ernest Micklei
     2  //
     3  // MIT License
     4  //
     5  // Permission is hereby granted, free of charge, to any person obtaining
     6  // a copy of this software and associated documentation files (the
     7  // "Software"), to deal in the Software without restriction, including
     8  // without limitation the rights to use, copy, modify, merge, publish,
     9  // distribute, sublicense, and/or sell copies of the Software, and to
    10  // permit persons to whom the Software is furnished to do so, subject to
    11  // the following conditions:
    12  //
    13  // The above copyright notice and this permission notice shall be
    14  // included in all copies or substantial portions of the Software.
    15  //
    16  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    17  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    18  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    19  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    20  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    21  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    22  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    23  
    24  package proto
    25  
    26  import (
    27  	"text/scanner"
    28  )
    29  
    30  // Oneof is a field alternate.
    31  type Oneof struct {
    32  	Position scanner.Position
    33  	Comment  *Comment
    34  	Name     string
    35  	Elements []Visitee
    36  	Parent   Visitee
    37  }
    38  
    39  // addElement is part of elementContainer
    40  func (o *Oneof) addElement(v Visitee) {
    41  	v.parent(o)
    42  	o.Elements = append(o.Elements, v)
    43  }
    44  
    45  // elements is part of elementContainer
    46  func (o *Oneof) elements() []Visitee {
    47  	return o.Elements
    48  }
    49  
    50  // takeLastComment is part of elementContainer
    51  // removes and returns the last element of the list if it is a Comment.
    52  func (o *Oneof) takeLastComment(expectedOnLine int) (last *Comment) {
    53  	last, o.Elements = takeLastCommentIfEndsOnLine(o.Elements, expectedOnLine)
    54  	return last
    55  }
    56  
    57  // parse expects:
    58  // oneofName "{" { oneofField | emptyStatement } "}"
    59  func (o *Oneof) parse(p *Parser) error {
    60  	pos, tok, lit := p.next()
    61  	if tok != tIDENT {
    62  		if !isKeyword(tok) {
    63  			return p.unexpected(lit, "oneof identifier", o)
    64  		}
    65  	}
    66  	o.Name = lit
    67  	consumeCommentFor(p, o)
    68  	pos, tok, lit = p.next()
    69  	if tok != tLEFTCURLY {
    70  		return p.unexpected(lit, "oneof opening {", o)
    71  	}
    72  	for {
    73  		pos, tok, lit = p.nextTypeName()
    74  		switch tok {
    75  		case tCOMMENT:
    76  			if com := mergeOrReturnComment(o.elements(), lit, pos); com != nil { // not merged?
    77  				o.addElement(com)
    78  			}
    79  		case tIDENT:
    80  			f := newOneOfField()
    81  			f.Position = pos
    82  			f.Comment, o.Elements = takeLastCommentIfEndsOnLine(o.elements(), pos.Line-1) // TODO call takeLastComment instead?
    83  			f.Type = lit
    84  			if err := parseFieldAfterType(f.Field, p, f); err != nil {
    85  				return err
    86  			}
    87  			o.addElement(f)
    88  		case tGROUP:
    89  			g := new(Group)
    90  			g.Position = pos
    91  			g.Comment, o.Elements = takeLastCommentIfEndsOnLine(o.elements(), pos.Line-1)
    92  			if err := g.parse(p); err != nil {
    93  				return err
    94  			}
    95  			o.addElement(g)
    96  		case tOPTION:
    97  			opt := new(Option)
    98  			opt.Position = pos
    99  			opt.Comment, o.Elements = takeLastCommentIfEndsOnLine(o.elements(), pos.Line-1)
   100  			if err := opt.parse(p); err != nil {
   101  				return err
   102  			}
   103  			o.addElement(opt)
   104  		case tSEMICOLON:
   105  			maybeScanInlineComment(p, o)
   106  			// continue
   107  		default:
   108  			goto done
   109  		}
   110  	}
   111  done:
   112  	if tok != tRIGHTCURLY {
   113  		return p.unexpected(lit, "oneof closing }", o)
   114  	}
   115  	return nil
   116  }
   117  
   118  // Accept dispatches the call to the visitor.
   119  func (o *Oneof) Accept(v Visitor) {
   120  	v.VisitOneof(o)
   121  }
   122  
   123  // Doc is part of Documented
   124  func (o *Oneof) Doc() *Comment {
   125  	return o.Comment
   126  }
   127  
   128  // OneOfField is part of Oneof.
   129  type OneOfField struct {
   130  	*Field
   131  }
   132  
   133  func newOneOfField() *OneOfField { return &OneOfField{Field: new(Field)} }
   134  
   135  // Accept dispatches the call to the visitor.
   136  func (o *OneOfField) Accept(v Visitor) {
   137  	v.VisitOneofField(o)
   138  }
   139  
   140  // Doc is part of Documented
   141  // Note: although Doc() is defined on Field, it must be implemented here as well.
   142  func (o *OneOfField) Doc() *Comment {
   143  	return o.Comment
   144  }
   145  
   146  func (o *Oneof) parent(v Visitee) { o.Parent = v }
   147  

View as plain text