github.com/hoveychen/protoreflect@v1.4.7-0.20221103114119-0b4b3385ec76/desc/protoparse/proto.y (about)

     1  %{
     2  package protoparse
     3  
     4  //lint:file-ignore SA4006 generated parser has unused values
     5  
     6  import (
     7  	"fmt"
     8  	"math"
     9  	"unicode"
    10  
    11  	"github.com/hoveychen/protoreflect/desc/internal"
    12  )
    13  
    14  %}
    15  
    16  // fields inside this union end up as the fields in a structure known
    17  // as ${PREFIX}SymType, of which a reference is passed to the lexer.
    18  %union{
    19  	file      *fileNode
    20  	fileDecls []*fileElement
    21  	syn       *syntaxNode
    22  	pkg       *packageNode
    23  	imprt     *importNode
    24  	msg       *messageNode
    25  	msgDecls  []*messageElement
    26  	fld       *fieldNode
    27  	mapFld    *mapFieldNode
    28  	mapType   *mapTypeNode
    29  	grp       *groupNode
    30  	oo        *oneOfNode
    31  	ooDecls   []*oneOfElement
    32  	ext       *extensionRangeNode
    33  	resvd     *reservedNode
    34  	en        *enumNode
    35  	enDecls   []*enumElement
    36  	env       *enumValueNode
    37  	extend    *extendNode
    38  	extDecls  []*extendElement
    39  	svc       *serviceNode
    40  	svcDecls  []*serviceElement
    41  	mtd       *methodNode
    42  	rpcType   *rpcTypeNode
    43  	opts      []*optionNode
    44  	optNm     []*optionNamePartNode
    45  	cmpctOpts *compactOptionsNode
    46  	rngs      []*rangeNode
    47  	names     []*stringLiteralNode
    48  	sl        []valueNode
    49  	agg       []*aggregateEntryNode
    50  	aggName   *aggregateNameNode
    51  	v         valueNode
    52  	str       *stringLiteralNode
    53  	i         *negativeIntLiteralNode
    54  	ui        *intLiteralNode
    55  	f         *floatLiteralNode
    56  	id        *identNode
    57  	b         *basicNode
    58  	err       error
    59  }
    60  
    61  // any non-terminal which returns a value needs a type, which is
    62  // really a field name in the above union struct
    63  %type <file>      file
    64  %type <syn>       syntax
    65  %type <fileDecls> fileDecl fileDecls
    66  %type <imprt>     import
    67  %type <pkg>       package
    68  %type <opts>      option compactOption compactOptionDecls rpcOption rpcOptions
    69  %type <optNm>     optionName optionNameRest optionNameComponent
    70  %type <cmpctOpts> compactOptions
    71  %type <v>         constant scalarConstant aggregate
    72  %type <id>        name ident typeIdent keyType
    73  %type <aggName>   aggName
    74  %type <i>         negIntLit
    75  %type <ui>        intLit
    76  %type <f>         floatLit
    77  %type <sl>        constantList
    78  %type <agg>       aggFields aggField aggFieldEntry
    79  %type <fld>       field oneofField
    80  %type <oo>        oneof
    81  %type <grp>       group
    82  %type <mapFld>    mapField
    83  %type <mapType>   mapType
    84  %type <msg>       message
    85  %type <msgDecls>  messageItem messageBody
    86  %type <ooDecls>   oneofItem oneofBody
    87  %type <names>     fieldNames
    88  %type <resvd>     msgReserved enumReserved reservedNames
    89  %type <rngs>      tagRange tagRanges enumRange enumRanges
    90  %type <ext>       extensions
    91  %type <en>        enum
    92  %type <enDecls>   enumItem enumBody
    93  %type <env>       enumField
    94  %type <extend>    extend
    95  %type <extDecls>  extendItem extendBody
    96  %type <str>       stringLit
    97  %type <svc>       service
    98  %type <svcDecls>  serviceItem serviceBody
    99  %type <mtd>       rpc
   100  %type <rpcType>   rpcType
   101  
   102  // same for terminals
   103  %token <str> _STRING_LIT
   104  %token <ui>  _INT_LIT
   105  %token <f>   _FLOAT_LIT
   106  %token <id>  _NAME _FQNAME _TYPENAME
   107  %token <id>  _SYNTAX _IMPORT _WEAK _PUBLIC _PACKAGE _OPTION _TRUE _FALSE _INF _NAN _REPEATED _OPTIONAL _REQUIRED
   108  %token <id>  _DOUBLE _FLOAT _INT32 _INT64 _UINT32 _UINT64 _SINT32 _SINT64 _FIXED32 _FIXED64 _SFIXED32 _SFIXED64
   109  %token <id>  _BOOL _STRING _BYTES _GROUP _ONEOF _MAP _EXTENSIONS _TO _MAX _RESERVED _ENUM _MESSAGE _EXTEND
   110  %token <id>  _SERVICE _RPC _STREAM _RETURNS
   111  %token <err> _ERROR
   112  // we define all of these, even ones that aren't used, to improve error messages
   113  // so it shows the unexpected symbol instead of showing "$unk"
   114  %token <b>   '=' ';' ':' '{' '}' '\\' '/' '?' '.' ',' '>' '<' '+' '-' '(' ')' '[' ']' '*' '&' '^' '%' '$' '#' '@' '!' '~' '`'
   115  
   116  %%
   117  
   118  file : syntax {
   119  		$$ = &fileNode{syntax: $1}
   120  		$$.setRange($1, $1)
   121  		protolex.(*protoLex).res = $$
   122  	}
   123  	| fileDecls  {
   124  		$$ = &fileNode{decls: $1}
   125  		if len($1) > 0 {
   126  			$$.setRange($1[0], $1[len($1)-1])
   127  		}
   128  		protolex.(*protoLex).res = $$
   129  	}
   130  	| syntax fileDecls {
   131  		$$ = &fileNode{syntax: $1, decls: $2}
   132  		var end node
   133  		if len($2) > 0 {
   134  			end = $2[len($2)-1]
   135  		} else {
   136  			end = $1
   137  		}
   138  		$$.setRange($1, end)
   139  		protolex.(*protoLex).res = $$
   140  	}
   141  	| {
   142  	}
   143  
   144  fileDecls : fileDecls fileDecl {
   145  		$$ = append($1, $2...)
   146  	}
   147  	| fileDecl
   148  
   149  fileDecl : import {
   150  		$$ = []*fileElement{{imp: $1}}
   151  	}
   152  	| package {
   153  		$$ = []*fileElement{{pkg: $1}}
   154  	}
   155  	| option {
   156  		$$ = []*fileElement{{option: $1[0]}}
   157  	}
   158  	| message {
   159  		$$ = []*fileElement{{message: $1}}
   160  	}
   161  	| enum {
   162  		$$ = []*fileElement{{enum: $1}}
   163  	}
   164  	| extend {
   165  		$$ = []*fileElement{{extend: $1}}
   166  	}
   167  	| service {
   168  		$$ = []*fileElement{{service: $1}}
   169  	}
   170  	| ';' {
   171  		$$ = []*fileElement{{empty: $1}}
   172  	}
   173  	| error ';' {
   174  	}
   175  	| error {
   176  	}
   177  
   178  syntax : _SYNTAX '=' stringLit ';' {
   179  		if $3.val != "proto2" && $3.val != "proto3" {
   180  			lexError(protolex, $3.start(), "syntax value must be 'proto2' or 'proto3'")
   181  		}
   182  		$$ = &syntaxNode{syntax: $3}
   183  		$$.setRange($1, $4)
   184  	}
   185  
   186  import : _IMPORT stringLit ';' {
   187  		$$ = &importNode{ name: $2 }
   188  		$$.setRange($1, $3)
   189  	}
   190  	| _IMPORT _WEAK stringLit ';' {
   191  		$$ = &importNode{ name: $3, weak: true }
   192  		$$.setRange($1, $4)
   193  	}
   194  	| _IMPORT _PUBLIC stringLit ';' {
   195  		$$ = &importNode{ name: $3, public: true }
   196  		$$.setRange($1, $4)
   197  	}
   198  
   199  package : _PACKAGE ident ';' {
   200  		$$ = &packageNode{name: $2}
   201  		$$.setRange($1, $3)
   202  	}
   203  
   204  ident : name
   205  	| _FQNAME
   206  
   207  option : _OPTION optionName '=' constant ';' {
   208  		n := &optionNameNode{parts: $2}
   209  		n.setRange($2[0], $2[len($2)-1])
   210  		o := &optionNode{name: n, val: $4}
   211  		o.setRange($1, $5)
   212  		$$ = []*optionNode{o}
   213  	}
   214  
   215  optionName : ident {
   216  		$$ = toNameParts($1, 0)
   217  	}
   218  	| '(' typeIdent ')' {
   219  		p := &optionNamePartNode{text: $2, isExtension: true}
   220  		p.setRange($1, $3)
   221  		$$ = []*optionNamePartNode{p}
   222  	}
   223  	| '(' typeIdent ')' optionNameRest {
   224  		p := &optionNamePartNode{text: $2, isExtension: true}
   225  		p.setRange($1, $3)
   226  		ps := make([]*optionNamePartNode, 1, len($4)+1)
   227  		ps[0] = p
   228  		$$ = append(ps, $4...)
   229  	}
   230  
   231  optionNameRest : optionNameComponent
   232  	| optionNameComponent optionNameRest {
   233  		$$ = append($1, $2...)
   234  	}
   235  
   236  optionNameComponent : _TYPENAME {
   237  		$$ = toNameParts($1, 1 /* exclude leading dot */)
   238  	}
   239  	| '.' '(' typeIdent ')' {
   240  		p := &optionNamePartNode{text: $3, isExtension: true}
   241  		p.setRange($2, $4)
   242  		$$ = []*optionNamePartNode{p}
   243  	}
   244  
   245  constant : scalarConstant
   246  	| aggregate
   247  
   248  scalarConstant : stringLit {
   249  		$$ = $1
   250  	}
   251  	| intLit {
   252  		$$ = $1
   253  	}
   254  	| negIntLit {
   255  		$$ = $1
   256  	}
   257  	| floatLit {
   258  		$$ = $1
   259  	}
   260  	| name {
   261  		if $1.val == "true" {
   262  			$$ = &boolLiteralNode{identNode: $1, val: true}
   263  		} else if $1.val == "false" {
   264  			$$ = &boolLiteralNode{identNode: $1, val: false}
   265  		} else if $1.val == "inf" {
   266  			f := &floatLiteralNode{val: math.Inf(1)}
   267  			f.setRange($1, $1)
   268  			$$ = f
   269  		} else if $1.val == "nan" {
   270  			f := &floatLiteralNode{val: math.NaN()}
   271  			f.setRange($1, $1)
   272  			$$ = f
   273  		} else {
   274  			$$ = $1
   275  		}
   276  	}
   277  
   278  intLit : _INT_LIT
   279  	| '+' _INT_LIT {
   280  		$$ = $2
   281  	}
   282  
   283  negIntLit : '-' _INT_LIT {
   284  		if $2.val > math.MaxInt64 + 1 {
   285  			lexError(protolex, $2.start(), fmt.Sprintf("numeric constant %d would underflow (allowed range is %d to %d)", $2.val, int64(math.MinInt64), int64(math.MaxInt64)))
   286  		}
   287  		$$ = &negativeIntLiteralNode{val: -int64($2.val)}
   288  		$$.setRange($1, $2)
   289  	}
   290  
   291  floatLit : _FLOAT_LIT
   292  	| '-' _FLOAT_LIT {
   293  		$$ = &floatLiteralNode{val: -$2.val}
   294  		$$.setRange($1, $2)
   295  	}
   296  	| '+' _FLOAT_LIT {
   297  		$$ = &floatLiteralNode{val: $2.val}
   298  		$$.setRange($1, $2)
   299  	}
   300  	| '+' _INF {
   301  		$$ = &floatLiteralNode{val: math.Inf(1)}
   302  		$$.setRange($1, $2)
   303  	}
   304  	| '-' _INF {
   305  		$$ = &floatLiteralNode{val: math.Inf(-1)}
   306  		$$.setRange($1, $2)
   307  	}
   308  
   309  stringLit : _STRING_LIT
   310      | stringLit _STRING_LIT {
   311          $$ = &stringLiteralNode{val: $1.val + $2.val}
   312          $$.setRange($1, $2)
   313      }
   314  
   315  aggregate : '{' aggFields '}' {
   316  		a := &aggregateLiteralNode{elements: $2}
   317  		a.setRange($1, $3)
   318  		$$ = a
   319  	}
   320  
   321  aggFields : aggField
   322  	| aggFields aggField {
   323  		$$ = append($1, $2...)
   324  	}
   325  	| {
   326  		$$ = nil
   327  	}
   328  
   329  aggField : aggFieldEntry
   330  	| aggFieldEntry ',' {
   331  		$$ = $1
   332  	}
   333  	| aggFieldEntry ';' {
   334  		$$ = $1
   335  	}
   336  	| error ',' {
   337  	}
   338  	| error ';' {
   339  	}
   340  	| error {
   341  	}
   342  
   343  aggFieldEntry : aggName ':' scalarConstant {
   344  		a := &aggregateEntryNode{name: $1, val: $3}
   345  		a.setRange($1, $3)
   346  		$$ = []*aggregateEntryNode{a}
   347  	}
   348  	| aggName ':' '[' ']' {
   349  		s := &sliceLiteralNode{}
   350  		s.setRange($3, $4)
   351  		a := &aggregateEntryNode{name: $1, val: s}
   352  		a.setRange($1, $4)
   353  		$$ = []*aggregateEntryNode{a}
   354  	}
   355  	| aggName ':' '[' constantList ']' {
   356  		s := &sliceLiteralNode{elements: $4}
   357  		s.setRange($3, $5)
   358  		a := &aggregateEntryNode{name: $1, val: s}
   359  		a.setRange($1, $5)
   360  		$$ = []*aggregateEntryNode{a}
   361  	}
   362  	| aggName ':' '[' error ']' {
   363  	}
   364  	| aggName ':' aggregate {
   365  		a := &aggregateEntryNode{name: $1, val: $3}
   366  		a.setRange($1, $3)
   367  		$$ = []*aggregateEntryNode{a}
   368  	}
   369  	| aggName aggregate {
   370  		a := &aggregateEntryNode{name: $1, val: $2}
   371  		a.setRange($1, $2)
   372  		$$ = []*aggregateEntryNode{a}
   373  	}
   374  	| aggName ':' '<' aggFields '>' {
   375  		s := &aggregateLiteralNode{elements: $4}
   376  		s.setRange($3, $5)
   377  		a := &aggregateEntryNode{name: $1, val: s}
   378  		a.setRange($1, $5)
   379  		$$ = []*aggregateEntryNode{a}
   380  	}
   381  	| aggName '<' aggFields '>' {
   382  		s := &aggregateLiteralNode{elements: $3}
   383  		s.setRange($2, $4)
   384  		a := &aggregateEntryNode{name: $1, val: s}
   385  		a.setRange($1, $4)
   386  		$$ = []*aggregateEntryNode{a}
   387  	}
   388  	| aggName ':' '<' error '>' {
   389  	}
   390  	| aggName '<' error '>' {
   391  	}
   392  
   393  aggName : name {
   394  		$$ = &aggregateNameNode{name: $1}
   395  		$$.setRange($1, $1)
   396  	}
   397  	| '[' ident ']' {
   398  		$$ = &aggregateNameNode{name: $2, isExtension: true}
   399  		$$.setRange($1, $3)
   400  	}
   401  	| '[' error ']' {
   402  	}
   403  
   404  constantList : constant {
   405  		$$ = []valueNode{$1}
   406  	}
   407  	| constantList ',' constant {
   408  		$$ = append($1, $3)
   409  	}
   410  	| constantList ';' constant {
   411  		$$ = append($1, $3)
   412  	}
   413  	| '<' aggFields '>' {
   414  		s := &aggregateLiteralNode{elements: $2}
   415  		s.setRange($1, $3)
   416  		$$ = []valueNode{s}
   417  	}
   418  	| constantList ','  '<' aggFields '>' {
   419  		s := &aggregateLiteralNode{elements: $4}
   420  		s.setRange($3, $5)
   421  		$$ = append($1, s)
   422  	}
   423  	| constantList ';'  '<' aggFields '>' {
   424  		s := &aggregateLiteralNode{elements: $4}
   425  		s.setRange($3, $5)
   426  		$$ = append($1, s)
   427  	}
   428  	| '<' error '>' {
   429  	}
   430  	| constantList ','  '<' error '>' {
   431  	}
   432  	| constantList ';'  '<' error '>' {
   433  	}
   434  
   435  typeIdent : ident
   436  	| _TYPENAME
   437  	| typeIdent _TYPENAME {
   438          $$ = &identNode{val: $1.val + $2.val}
   439          $$.setRange($1, $2)
   440  	}
   441  
   442  field : _REQUIRED typeIdent name '=' _INT_LIT ';' {
   443  		checkTag(protolex, $5.start(), $5.val)
   444  		lbl := &labelNode{identNode: $1, required: true}
   445  		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5}
   446  		$$.setRange($1, $6)
   447  	}
   448  	| _OPTIONAL typeIdent name '=' _INT_LIT ';' {
   449  		checkTag(protolex, $5.start(), $5.val)
   450  		lbl := &labelNode{identNode: $1}
   451  		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5}
   452  		$$.setRange($1, $6)
   453  	}
   454  	| _REPEATED typeIdent name '=' _INT_LIT ';' {
   455  		checkTag(protolex, $5.start(), $5.val)
   456  		lbl := &labelNode{identNode: $1, repeated: true}
   457  		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5}
   458  		$$.setRange($1, $6)
   459  	}
   460  	| typeIdent name '=' _INT_LIT ';' {
   461  		checkTag(protolex, $4.start(), $4.val)
   462  		$$ = &fieldNode{fldType: $1, name: $2, tag: $4}
   463  		$$.setRange($1, $5)
   464  	}
   465  	| _REQUIRED typeIdent name '=' _INT_LIT compactOptions ';' {
   466  		checkTag(protolex, $5.start(), $5.val)
   467  		lbl := &labelNode{identNode: $1, required: true}
   468  		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5, options: $6}
   469  		$$.setRange($1, $7)
   470  	}
   471  	| _OPTIONAL typeIdent name '=' _INT_LIT compactOptions ';' {
   472  		checkTag(protolex, $5.start(), $5.val)
   473  		lbl := &labelNode{identNode: $1}
   474  		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5, options: $6}
   475  		$$.setRange($1, $7)
   476  	}
   477  	| _REPEATED typeIdent name '=' _INT_LIT compactOptions ';' {
   478  		checkTag(protolex, $5.start(), $5.val)
   479  		lbl := &labelNode{identNode: $1, repeated: true}
   480  		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5, options: $6}
   481  		$$.setRange($1, $7)
   482  	}
   483  	| typeIdent name '=' _INT_LIT compactOptions ';' {
   484  		checkTag(protolex, $4.start(), $4.val)
   485  		$$ = &fieldNode{fldType: $1, name: $2, tag: $4, options: $5}
   486  		$$.setRange($1, $6)
   487  	}
   488  
   489  compactOptions: '[' compactOptionDecls ']' {
   490          $$ = &compactOptionsNode{decls: $2}
   491          $$.setRange($1, $3)
   492      }
   493  
   494  compactOptionDecls : compactOptionDecls ',' compactOption {
   495  		$$ = append($1, $3...)
   496  	}
   497  	| compactOption
   498  
   499  compactOption: optionName '=' constant {
   500  		n := &optionNameNode{parts: $1}
   501  		n.setRange($1[0], $1[len($1)-1])
   502  		o := &optionNode{name: n, val: $3}
   503  		o.setRange($1[0], $3)
   504  		$$ = []*optionNode{o}
   505  	}
   506  
   507  group : _REQUIRED _GROUP name '=' _INT_LIT '{' messageBody '}' {
   508  		checkTag(protolex, $5.start(), $5.val)
   509  		if !unicode.IsUpper(rune($3.val[0])) {
   510  			lexError(protolex, $3.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", $3.val))
   511  		}
   512  		lbl := &labelNode{identNode: $1, required: true}
   513  		$$ = &groupNode{groupKeyword: $2, label: lbl, name: $3, tag: $5, decls: $7}
   514  		$$.setRange($1, $8)
   515  	}
   516  	| _OPTIONAL _GROUP name '=' _INT_LIT '{' messageBody '}' {
   517  		checkTag(protolex, $5.start(), $5.val)
   518  		if !unicode.IsUpper(rune($3.val[0])) {
   519  			lexError(protolex, $3.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", $3.val))
   520  		}
   521  		lbl := &labelNode{identNode: $1}
   522  		$$ = &groupNode{groupKeyword: $2, label: lbl, name: $3, tag: $5, decls: $7}
   523  		$$.setRange($1, $8)
   524  	}
   525  	| _REPEATED _GROUP name '=' _INT_LIT '{' messageBody '}' {
   526  		checkTag(protolex, $5.start(), $5.val)
   527  		if !unicode.IsUpper(rune($3.val[0])) {
   528  			lexError(protolex, $3.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", $3.val))
   529  		}
   530  		lbl := &labelNode{identNode: $1, repeated: true}
   531  		$$ = &groupNode{groupKeyword: $2, label: lbl, name: $3, tag: $5, decls: $7}
   532  		$$.setRange($1, $8)
   533  	}
   534  
   535  oneof : _ONEOF name '{' oneofBody '}' {
   536  		c := 0
   537  		for _, el := range $4 {
   538  			if el.field != nil {
   539  				c++
   540  			}
   541  		}
   542  		if c == 0 {
   543  			lexError(protolex, $1.start(), "oneof must contain at least one field")
   544  		}
   545  		$$ = &oneOfNode{name: $2, decls: $4}
   546  		$$.setRange($1, $5)
   547  	}
   548  
   549  oneofBody : oneofBody oneofItem {
   550  		$$ = append($1, $2...)
   551  	}
   552  	| oneofItem
   553  	| {
   554  		$$ = nil
   555  	}
   556  
   557  oneofItem : option {
   558  		$$ = []*oneOfElement{{option: $1[0]}}
   559  	}
   560  	| oneofField {
   561  		$$ = []*oneOfElement{{field: $1}}
   562  	}
   563  	| ';' {
   564  		$$ = []*oneOfElement{{empty: $1}}
   565  	}
   566  	| error ';' {
   567  	}
   568  	| error {
   569  	}
   570  
   571  oneofField : typeIdent name '=' _INT_LIT ';' {
   572  		checkTag(protolex, $4.start(), $4.val)
   573  		$$ = &fieldNode{fldType: $1, name: $2, tag: $4}
   574  		$$.setRange($1, $5)
   575  	}
   576  	| typeIdent name '=' _INT_LIT compactOptions ';' {
   577  		checkTag(protolex, $4.start(), $4.val)
   578  		$$ = &fieldNode{fldType: $1, name: $2, tag: $4, options: $5}
   579  		$$.setRange($1, $6)
   580  	}
   581  
   582  mapField : mapType name '=' _INT_LIT ';' {
   583  		checkTag(protolex, $4.start(), $4.val)
   584  		$$ = &mapFieldNode{mapType: $1, name: $2, tag: $4}
   585  		$$.setRange($1, $5)
   586  	}
   587  	| mapType name '=' _INT_LIT compactOptions ';' {
   588  		checkTag(protolex, $4.start(), $4.val)
   589  		$$ = &mapFieldNode{mapType: $1, name: $2, tag: $4, options: $5}
   590  		$$.setRange($1, $6)
   591  	}
   592  
   593  mapType : _MAP '<' keyType ',' typeIdent '>' {
   594          $$ = &mapTypeNode{mapKeyword: $1, keyType: $3, valueType: $5}
   595          $$.setRange($1, $6)
   596  }
   597  
   598  keyType : _INT32
   599  	| _INT64
   600  	| _UINT32
   601  	| _UINT64
   602  	| _SINT32
   603  	| _SINT64
   604  	| _FIXED32
   605  	| _FIXED64
   606  	| _SFIXED32
   607  	| _SFIXED64
   608  	| _BOOL
   609  	| _STRING
   610  
   611  extensions : _EXTENSIONS tagRanges ';' {
   612  		$$ = &extensionRangeNode{ranges: $2}
   613  		$$.setRange($1, $3)
   614  	}
   615  	| _EXTENSIONS tagRanges compactOptions ';' {
   616  		$$ = &extensionRangeNode{ranges: $2, options: $3}
   617  		$$.setRange($1, $4)
   618  	}
   619  
   620  tagRanges : tagRanges ',' tagRange {
   621  		$$ = append($1, $3...)
   622  	}
   623  	| tagRange
   624  
   625  tagRange : _INT_LIT {
   626  		if $1.val > internal.MaxTag {
   627  			lexError(protolex, $1.start(), fmt.Sprintf("range includes out-of-range tag: %d (should be between 0 and %d)", $1.val, internal.MaxTag))
   628  		}
   629  		r := &rangeNode{stNode: $1, enNode: $1, st: int32($1.val), en: int32($1.val)}
   630  		r.setRange($1, $1)
   631  		$$ = []*rangeNode{r}
   632  	}
   633  	| _INT_LIT _TO _INT_LIT {
   634  		if $1.val > internal.MaxTag {
   635  			lexError(protolex, $1.start(), fmt.Sprintf("range start is out-of-range tag: %d (should be between 0 and %d)", $1.val, internal.MaxTag))
   636  		}
   637  		if $3.val > internal.MaxTag {
   638  			lexError(protolex, $3.start(), fmt.Sprintf("range end is out-of-range tag: %d (should be between 0 and %d)", $3.val, internal.MaxTag))
   639  		}
   640  		if $1.val > $3.val {
   641  			lexError(protolex, $1.start(), fmt.Sprintf("range, %d to %d, is invalid: start must be <= end", $1.val, $3.val))
   642  		}
   643  		r := &rangeNode{stNode: $1, enNode: $3, st: int32($1.val), en: int32($3.val)}
   644  		r.setRange($1, $3)
   645  		$$ = []*rangeNode{r}
   646  	}
   647  	| _INT_LIT _TO _MAX {
   648  		if $1.val > internal.MaxTag {
   649  			lexError(protolex, $1.start(), fmt.Sprintf("range start is out-of-range tag: %d (should be between 0 and %d)", $1.val, internal.MaxTag))
   650  		}
   651  		r := &rangeNode{stNode: $1, enNode: $3, st: int32($1.val), en: internal.MaxTag}
   652  		r.setRange($1, $3)
   653  		$$ = []*rangeNode{r}
   654  	}
   655  
   656  enumRanges : enumRanges ',' enumRange {
   657  		$$ = append($1, $3...)
   658  	}
   659  	| enumRange
   660  
   661  enumRange : _INT_LIT {
   662  		checkUint64InInt32Range(protolex, $1.start(), $1.val)
   663  		r := &rangeNode{stNode: $1, enNode: $1, st: int32($1.val), en: int32($1.val)}
   664  		r.setRange($1, $1)
   665  		$$ = []*rangeNode{r}
   666  	}
   667  	| negIntLit {
   668  		checkInt64InInt32Range(protolex, $1.start(), $1.val)
   669  		r := &rangeNode{stNode: $1, enNode: $1, st: int32($1.val), en: int32($1.val)}
   670  		r.setRange($1, $1)
   671  		$$ = []*rangeNode{r}
   672  	}
   673  	| _INT_LIT _TO _INT_LIT {
   674  		checkUint64InInt32Range(protolex, $1.start(), $1.val)
   675  		checkUint64InInt32Range(protolex, $3.start(), $3.val)
   676  		if $1.val > $3.val {
   677  			lexError(protolex, $1.start(), fmt.Sprintf("range, %d to %d, is invalid: start must be <= end", $1.val, $3.val))
   678  		}
   679  		r := &rangeNode{stNode: $1, enNode: $3, st: int32($1.val), en: int32($3.val)}
   680  		r.setRange($1, $3)
   681  		$$ = []*rangeNode{r}
   682  	}
   683  	| negIntLit _TO negIntLit {
   684  		checkInt64InInt32Range(protolex, $1.start(), $1.val)
   685  		checkInt64InInt32Range(protolex, $3.start(), $3.val)
   686  		if $1.val > $3.val {
   687  			lexError(protolex, $1.start(), fmt.Sprintf("range, %d to %d, is invalid: start must be <= end", $1.val, $3.val))
   688  		}
   689  		r := &rangeNode{stNode: $1, enNode: $3, st: int32($1.val), en: int32($3.val)}
   690  		r.setRange($1, $3)
   691  		$$ = []*rangeNode{r}
   692  	}
   693  	| negIntLit _TO _INT_LIT {
   694  		checkInt64InInt32Range(protolex, $1.start(), $1.val)
   695  		checkUint64InInt32Range(protolex, $3.start(), $3.val)
   696  		r := &rangeNode{stNode: $1, enNode: $3, st: int32($1.val), en: int32($3.val)}
   697  		r.setRange($1, $3)
   698  		$$ = []*rangeNode{r}
   699  	}
   700  	| _INT_LIT _TO _MAX {
   701  		checkUint64InInt32Range(protolex, $1.start(), $1.val)
   702  		r := &rangeNode{stNode: $1, enNode: $3, st: int32($1.val), en: math.MaxInt32}
   703  		r.setRange($1, $3)
   704  		$$ = []*rangeNode{r}
   705  	}
   706  	| negIntLit _TO _MAX {
   707  		checkInt64InInt32Range(protolex, $1.start(), $1.val)
   708  		r := &rangeNode{stNode: $1, enNode: $3, st: int32($1.val), en: math.MaxInt32}
   709  		r.setRange($1, $3)
   710  		$$ = []*rangeNode{r}
   711  	}
   712  
   713  msgReserved : _RESERVED tagRanges ';' {
   714  		$$ = &reservedNode{ranges: $2}
   715  		$$.setRange($1, $3)
   716  	}
   717  	| reservedNames
   718  
   719  enumReserved : _RESERVED enumRanges ';' {
   720  		$$ = &reservedNode{ranges: $2}
   721  		$$.setRange($1, $3)
   722  	}
   723  	| reservedNames
   724  
   725  reservedNames : _RESERVED fieldNames ';' {
   726  		rsvd := map[string]struct{}{}
   727  		for _, n := range $2 {
   728  			if _, ok := rsvd[n.val]; ok {
   729  				lexError(protolex, n.start(), fmt.Sprintf("name %q is reserved multiple times", n.val))
   730  				break
   731  			}
   732  			rsvd[n.val] = struct{}{}
   733  		}
   734  		$$ = &reservedNode{names: $2}
   735  		$$.setRange($1, $3)
   736  	}
   737  
   738  fieldNames : fieldNames ',' stringLit {
   739  		$$ = append($1, $3)
   740  	}
   741  	| stringLit {
   742  		$$ = []*stringLiteralNode{$1}
   743  	}
   744  
   745  enum : _ENUM name '{' enumBody '}' {
   746  		c := 0
   747  		for _, el := range $4 {
   748  			if el.value != nil {
   749  				c++
   750  			}
   751  		}
   752  		if c == 0 {
   753  			lexError(protolex, $1.start(), "enums must define at least one value")
   754  		}
   755  		$$ = &enumNode{name: $2, decls: $4}
   756  		$$.setRange($1, $5)
   757  	}
   758  
   759  enumBody : enumBody enumItem {
   760  		$$ = append($1, $2...)
   761  	}
   762  	| enumItem
   763  	| {
   764  		$$ = nil
   765  	}
   766  
   767  enumItem : option {
   768  		$$ = []*enumElement{{option: $1[0]}}
   769  	}
   770  	| enumField {
   771  		$$ = []*enumElement{{value: $1}}
   772  	}
   773  	| enumReserved {
   774  		$$ = []*enumElement{{reserved: $1}}
   775  	}
   776  	| ';' {
   777  		$$ = []*enumElement{{empty: $1}}
   778  	}
   779  	| error ';' {
   780  	}
   781  	| error {
   782  	}
   783  
   784  enumField : name '=' _INT_LIT ';' {
   785  		checkUint64InInt32Range(protolex, $3.start(), $3.val)
   786  		$$ = &enumValueNode{name: $1, numberP: $3}
   787  		$$.setRange($1, $4)
   788  	}
   789  	|  name '=' _INT_LIT compactOptions ';' {
   790  		checkUint64InInt32Range(protolex, $3.start(), $3.val)
   791  		$$ = &enumValueNode{name: $1, numberP: $3, options: $4}
   792  		$$.setRange($1, $5)
   793  	}
   794  	| name '=' negIntLit ';' {
   795  		checkInt64InInt32Range(protolex, $3.start(), $3.val)
   796  		$$ = &enumValueNode{name: $1, numberN: $3}
   797  		$$.setRange($1, $4)
   798  	}
   799  	|  name '=' negIntLit compactOptions ';' {
   800  		checkInt64InInt32Range(protolex, $3.start(), $3.val)
   801  		$$ = &enumValueNode{name: $1, numberN: $3, options: $4}
   802  		$$.setRange($1, $5)
   803  	}
   804  
   805  message : _MESSAGE name '{' messageBody '}' {
   806  		$$ = &messageNode{name: $2, decls: $4}
   807  		$$.setRange($1, $5)
   808  	}
   809  
   810  messageBody : messageBody messageItem {
   811  		$$ = append($1, $2...)
   812  	}
   813  	| messageItem
   814  	| {
   815  		$$ = nil
   816  	}
   817  
   818  messageItem : field {
   819  		$$ = []*messageElement{{field: $1}}
   820  	}
   821  	| enum {
   822  		$$ = []*messageElement{{enum: $1}}
   823  	}
   824  	| message {
   825  		$$ = []*messageElement{{nested: $1}}
   826  	}
   827  	| extend {
   828  		$$ = []*messageElement{{extend: $1}}
   829  	}
   830  	| extensions {
   831  		$$ = []*messageElement{{extensionRange: $1}}
   832  	}
   833  	| group {
   834  		$$ = []*messageElement{{group: $1}}
   835  	}
   836  	| option {
   837  		$$ = []*messageElement{{option: $1[0]}}
   838  	}
   839  	| oneof {
   840  		$$ = []*messageElement{{oneOf: $1}}
   841  	}
   842  	| mapField {
   843  		$$ = []*messageElement{{mapField: $1}}
   844  	}
   845  	| msgReserved {
   846  		$$ = []*messageElement{{reserved: $1}}
   847  	}
   848  	| ';' {
   849  		$$ = []*messageElement{{empty: $1}}
   850  	}
   851  	| error ';' {
   852  	}
   853  	| error {
   854  	}
   855  
   856  extend : _EXTEND typeIdent '{' extendBody '}' {
   857  		c := 0
   858  		for _, el := range $4 {
   859  			if el.field != nil || el.group != nil {
   860  				c++
   861  			}
   862  		}
   863  		if c == 0 {
   864  			lexError(protolex, $1.start(), "extend sections must define at least one extension")
   865  		}
   866  		$$ = &extendNode{extendee: $2, decls: $4}
   867  		$$.setRange($1, $5)
   868  	}
   869  
   870  extendBody : extendBody extendItem {
   871  		$$ = append($1, $2...)
   872  	}
   873  	| extendItem
   874  	| {
   875  		$$ = nil
   876  	}
   877  
   878  extendItem : field {
   879  		$$ = []*extendElement{{field: $1}}
   880  	}
   881  	| group {
   882  		$$ = []*extendElement{{group: $1}}
   883  	}
   884  	| ';' {
   885  		$$ = []*extendElement{{empty: $1}}
   886  	}
   887  	| error ';' {
   888  	}
   889  	| error {
   890  	}
   891  
   892  service : _SERVICE name '{' serviceBody '}' {
   893  		$$ = &serviceNode{name: $2, decls: $4}
   894  		$$.setRange($1, $5)
   895  	}
   896  
   897  serviceBody : serviceBody serviceItem {
   898  		$$ = append($1, $2...)
   899  	}
   900  	| serviceItem
   901  	| {
   902  		$$ = nil
   903  	}
   904  
   905  // NB: doc suggests support for "stream" declaration, separate from "rpc", but
   906  // it does not appear to be supported in protoc (doc is likely from grammar for
   907  // Google-internal version of protoc, with support for streaming stubby)
   908  serviceItem : option {
   909  		$$ = []*serviceElement{{option: $1[0]}}
   910  	}
   911  	| rpc {
   912  		$$ = []*serviceElement{{rpc: $1}}
   913  	}
   914  	| ';' {
   915  		$$ = []*serviceElement{{empty: $1}}
   916  	}
   917  	| error ';' {
   918  	}
   919  	| error {
   920  	}
   921  
   922  rpc : _RPC name '(' rpcType ')' _RETURNS '(' rpcType ')' ';' {
   923  		$$ = &methodNode{name: $2, input: $4, output: $8}
   924  		$$.setRange($1, $10)
   925  	}
   926  	| _RPC name '(' rpcType ')' _RETURNS '(' rpcType ')' '{' rpcOptions '}' {
   927  		$$ = &methodNode{name: $2, input: $4, output: $8, options: $11}
   928  		$$.setRange($1, $12)
   929  	}
   930  
   931  rpcType : _STREAM typeIdent {
   932  		$$ = &rpcTypeNode{msgType: $2, streamKeyword: $1}
   933  		$$.setRange($1, $2)
   934  	}
   935  	| typeIdent {
   936  		$$ = &rpcTypeNode{msgType: $1}
   937  		$$.setRange($1, $1)
   938  	}
   939  
   940  rpcOptions : rpcOptions rpcOption {
   941  		$$ = append($1, $2...)
   942  	}
   943  	| rpcOption
   944  	| {
   945  		$$ = []*optionNode{}
   946  	}
   947  
   948  rpcOption : option {
   949  		$$ = $1
   950  	}
   951  	| ';' {
   952  		$$ = []*optionNode{}
   953  	}
   954  	| error ';' {
   955  	}
   956  	| error {
   957  	}
   958  
   959  name : _NAME
   960  	| _SYNTAX
   961  	| _IMPORT
   962  	| _WEAK
   963  	| _PUBLIC
   964  	| _PACKAGE
   965  	| _OPTION
   966  	| _TRUE
   967  	| _FALSE
   968  	| _INF
   969  	| _NAN
   970  	| _REPEATED
   971  	| _OPTIONAL
   972  	| _REQUIRED
   973  	| _DOUBLE
   974  	| _FLOAT
   975  	| _INT32
   976  	| _INT64
   977  	| _UINT32
   978  	| _UINT64
   979  	| _SINT32
   980  	| _SINT64
   981  	| _FIXED32
   982  	| _FIXED64
   983  	| _SFIXED32
   984  	| _SFIXED64
   985  	| _BOOL
   986  	| _STRING
   987  	| _BYTES
   988  	| _GROUP
   989  	| _ONEOF
   990  	| _MAP
   991  	| _EXTENSIONS
   992  	| _TO
   993  	| _MAX
   994  	| _RESERVED
   995  	| _ENUM
   996  	| _MESSAGE
   997  	| _EXTEND
   998  	| _SERVICE
   999  	| _RPC
  1000  	| _STREAM
  1001  	| _RETURNS
  1002  
  1003  %%