...

Source file src/github.com/emicklei/proto/proto.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  // Proto represents a .proto definition
    27  type Proto struct {
    28  	Filename string
    29  	Elements []Visitee
    30  }
    31  
    32  // Accept dispatches the call to the visitor.
    33  func (proto *Proto) Accept(v Visitor) {
    34  	// As Proto is not (yet) a Visitee, we enumerate its elements instead
    35  	//v.VisitProto(proto)
    36  	for _, each := range proto.Elements {
    37  		each.Accept(v)
    38  	}
    39  }
    40  
    41  // addElement is part of elementContainer
    42  func (proto *Proto) addElement(v Visitee) {
    43  	v.parent(proto)
    44  	proto.Elements = append(proto.Elements, v)
    45  }
    46  
    47  // elements is part of elementContainer
    48  func (proto *Proto) elements() []Visitee {
    49  	return proto.Elements
    50  }
    51  
    52  // takeLastComment is part of elementContainer
    53  // removes and returns the last element of the list if it is a Comment.
    54  func (proto *Proto) takeLastComment(expectedOnLine int) (last *Comment) {
    55  	last, proto.Elements = takeLastCommentIfEndsOnLine(proto.Elements, expectedOnLine)
    56  	return
    57  }
    58  
    59  // parse parsers a complete .proto definition source.
    60  func (proto *Proto) parse(p *Parser) error {
    61  	for {
    62  		pos, tok, lit := p.next()
    63  		switch {
    64  		case isComment(lit):
    65  			if com := mergeOrReturnComment(proto.Elements, lit, pos); com != nil { // not merged?
    66  				proto.Elements = append(proto.Elements, com)
    67  			}
    68  		case tOPTION == tok:
    69  			o := new(Option)
    70  			o.Position = pos
    71  			o.Comment, proto.Elements = takeLastCommentIfEndsOnLine(proto.Elements, pos.Line-1)
    72  			if err := o.parse(p); err != nil {
    73  				return err
    74  			}
    75  			proto.addElement(o)
    76  		case tSYNTAX == tok:
    77  			s := new(Syntax)
    78  			s.Position = pos
    79  			s.Comment, proto.Elements = takeLastCommentIfEndsOnLine(proto.Elements, pos.Line-1)
    80  			if err := s.parse(p); err != nil {
    81  				return err
    82  			}
    83  			proto.addElement(s)
    84  		case tIMPORT == tok:
    85  			im := new(Import)
    86  			im.Position = pos
    87  			im.Comment, proto.Elements = takeLastCommentIfEndsOnLine(proto.Elements, pos.Line-1)
    88  			if err := im.parse(p); err != nil {
    89  				return err
    90  			}
    91  			proto.addElement(im)
    92  		case tENUM == tok:
    93  			enum := new(Enum)
    94  			enum.Position = pos
    95  			enum.Comment, proto.Elements = takeLastCommentIfEndsOnLine(proto.Elements, pos.Line-1)
    96  			if err := enum.parse(p); err != nil {
    97  				return err
    98  			}
    99  			proto.addElement(enum)
   100  		case tSERVICE == tok:
   101  			service := new(Service)
   102  			service.Position = pos
   103  			service.Comment, proto.Elements = takeLastCommentIfEndsOnLine(proto.Elements, pos.Line-1)
   104  			err := service.parse(p)
   105  			if err != nil {
   106  				return err
   107  			}
   108  			proto.addElement(service)
   109  		case tPACKAGE == tok:
   110  			pkg := new(Package)
   111  			pkg.Position = pos
   112  			pkg.Comment, proto.Elements = takeLastCommentIfEndsOnLine(proto.Elements, pos.Line-1)
   113  			if err := pkg.parse(p); err != nil {
   114  				return err
   115  			}
   116  			proto.addElement(pkg)
   117  		case tMESSAGE == tok:
   118  			msg := new(Message)
   119  			msg.Position = pos
   120  			msg.Comment, proto.Elements = takeLastCommentIfEndsOnLine(proto.Elements, pos.Line-1)
   121  			if err := msg.parse(p); err != nil {
   122  				return err
   123  			}
   124  			proto.addElement(msg)
   125  		// BEGIN proto2
   126  		case tEXTEND == tok:
   127  			msg := new(Message)
   128  			msg.Position = pos
   129  			msg.Comment, proto.Elements = takeLastCommentIfEndsOnLine(proto.Elements, pos.Line-1)
   130  			msg.IsExtend = true
   131  			if err := msg.parse(p); err != nil {
   132  				return err
   133  			}
   134  			proto.addElement(msg)
   135  		// END proto2
   136  		case tSEMICOLON == tok:
   137  			maybeScanInlineComment(p, proto)
   138  			// continue
   139  		case tEOF == tok:
   140  			goto done
   141  		default:
   142  			return p.unexpected(lit, ".proto element {comment|option|import|syntax|enum|service|package|message}", p)
   143  		}
   144  	}
   145  done:
   146  	return nil
   147  }
   148  
   149  func (proto *Proto) parent(v Visitee) {}
   150  
   151  // elementContainer unifies types that have elements.
   152  type elementContainer interface {
   153  	addElement(v Visitee)
   154  	elements() []Visitee
   155  	takeLastComment(expectedOnLine int) *Comment
   156  }
   157  

View as plain text