github.com/jhump/protocompile@v0.0.0-20221021153901-4f6f732835e8/parser/proto.y (about)

     1  %{
     2  package parser
     3  
     4  //lint:file-ignore SA4006 generated parser has unused values
     5  
     6  import (
     7  	"math"
     8  
     9  	"github.com/jhump/protocompile/ast"
    10  )
    11  
    12  %}
    13  
    14  // fields inside this union end up as the fields in a structure known
    15  // as ${PREFIX}SymType, of which a reference is passed to the lexer.
    16  %union{
    17  	file      *ast.FileNode
    18  	syn       *ast.SyntaxNode
    19  	fileDecl  ast.FileElement
    20  	fileDecls []ast.FileElement
    21  	pkg       *ast.PackageNode
    22  	imprt     *ast.ImportNode
    23  	msg       *ast.MessageNode
    24  	msgDecl   ast.MessageElement
    25  	msgDecls  []ast.MessageElement
    26  	fld       *ast.FieldNode
    27  	mapFld    *ast.MapFieldNode
    28  	mapType   *ast.MapTypeNode
    29  	grp       *ast.GroupNode
    30  	oo        *ast.OneOfNode
    31  	ooDecl    ast.OneOfElement
    32  	ooDecls   []ast.OneOfElement
    33  	ext       *ast.ExtensionRangeNode
    34  	resvd     *ast.ReservedNode
    35  	en        *ast.EnumNode
    36  	enDecl    ast.EnumElement
    37  	enDecls   []ast.EnumElement
    38  	env       *ast.EnumValueNode
    39  	extend    *ast.ExtendNode
    40  	extDecl   ast.ExtendElement
    41  	extDecls  []ast.ExtendElement
    42  	svc       *ast.ServiceNode
    43  	svcDecl   ast.ServiceElement
    44  	svcDecls  []ast.ServiceElement
    45  	mtd       *ast.RPCNode
    46  	rpcType   *ast.RPCTypeNode
    47  	rpcDecl   ast.RPCElement
    48  	rpcDecls  []ast.RPCElement
    49  	opt       *ast.OptionNode
    50  	opts      *compactOptionList
    51  	ref       *ast.FieldReferenceNode
    52  	optNms    *fieldRefList
    53  	cmpctOpts *ast.CompactOptionsNode
    54  	rng       *ast.RangeNode
    55  	rngs      *rangeList
    56  	names     *nameList
    57  	cid       *identList
    58  	tid       ast.IdentValueNode
    59  	sl        *valueList
    60  	msgField  *ast.MessageFieldNode
    61  	msgEntry  *messageFieldEntry
    62  	msgLit    *messageFieldList
    63  	v         ast.ValueNode
    64  	il        ast.IntValueNode
    65  	str       *stringList
    66  	s         *ast.StringLiteralNode
    67  	i         *ast.UintLiteralNode
    68  	f         *ast.FloatLiteralNode
    69  	id        *ast.IdentNode
    70  	b         *ast.RuneNode
    71  	err       error
    72  }
    73  
    74  // any non-terminal which returns a value needs a type, which is
    75  // really a field name in the above union struct
    76  %type <file>      file
    77  %type <syn>       syntax
    78  %type <fileDecl>  fileDecl
    79  %type <fileDecls> fileDecls
    80  %type <imprt>     import
    81  %type <pkg>       package
    82  %type <opt>       option compactOption
    83  %type <opts>      compactOptionDecls
    84  %type <rpcDecl>   rpcDecl
    85  %type <rpcDecls>  rpcDecls
    86  %type <ref>       optionNameComponent aggName
    87  %type <optNms>    optionName
    88  %type <cmpctOpts> compactOptions
    89  %type <v>         constant scalarConstant aggregate numLit
    90  %type <il>        intLit
    91  %type <id>        name keyType msgElementName extElementName oneofElementName enumElementName
    92  %type <cid>       ident msgElementIdent extElementIdent oneofElementIdent
    93  %type <tid>       typeIdent msgElementTypeIdent extElementTypeIdent oneofElementTypeIdent
    94  %type <sl>        constantList
    95  %type <msgField>  aggFieldEntry
    96  %type <msgEntry>  aggField
    97  %type <msgLit>    aggFields
    98  %type <fld>       msgField oneofField extField
    99  %type <oo>        oneof
   100  %type <grp>       group oneofGroup
   101  %type <mapFld>    mapField
   102  %type <mapType>   mapType
   103  %type <msg>       message
   104  %type <msgDecl>   messageDecl
   105  %type <msgDecls>  messageDecls
   106  %type <ooDecl>    ooDecl
   107  %type <ooDecls>   ooDecls
   108  %type <names>     fieldNames
   109  %type <resvd>     msgReserved enumReserved reservedNames
   110  %type <rng>       tagRange enumRange
   111  %type <rngs>      tagRanges enumRanges
   112  %type <ext>       extensions
   113  %type <en>        enum
   114  %type <enDecl>    enumDecl
   115  %type <enDecls>   enumDecls
   116  %type <env>       enumValue
   117  %type <extend>    extend
   118  %type <extDecl>   extendDecl
   119  %type <extDecls>  extendDecls
   120  %type <str>       stringLit
   121  %type <svc>       service
   122  %type <svcDecl>   serviceDecl
   123  %type <svcDecls>  serviceDecls
   124  %type <mtd>       rpc
   125  %type <rpcType>   rpcType
   126  
   127  // same for terminals
   128  %token <s>   _STRING_LIT
   129  %token <i>   _INT_LIT
   130  %token <f>   _FLOAT_LIT
   131  %token <id>  _NAME
   132  %token <id>  _SYNTAX _IMPORT _WEAK _PUBLIC _PACKAGE _OPTION _TRUE _FALSE _INF _NAN _REPEATED _OPTIONAL _REQUIRED
   133  %token <id>  _DOUBLE _FLOAT _INT32 _INT64 _UINT32 _UINT64 _SINT32 _SINT64 _FIXED32 _FIXED64 _SFIXED32 _SFIXED64
   134  %token <id>  _BOOL _STRING _BYTES _GROUP _ONEOF _MAP _EXTENSIONS _TO _MAX _RESERVED _ENUM _MESSAGE _EXTEND
   135  %token <id>  _SERVICE _RPC _STREAM _RETURNS
   136  %token <err> _ERROR
   137  // we define all of these, even ones that aren't used, to improve error messages
   138  // so it shows the unexpected symbol instead of showing "$unk"
   139  %token <b>   '=' ';' ':' '{' '}' '\\' '/' '?' '.' ',' '>' '<' '+' '-' '(' ')' '[' ']' '*' '&' '^' '%' '$' '#' '@' '!' '~' '`'
   140  
   141  %%
   142  
   143  file : syntax {
   144  		lex := protolex.(*protoLex)
   145  		$$ = ast.NewFileNode(lex.info, $1, nil, lex.eof)
   146  		lex.res = $$
   147  	}
   148  	| fileDecls  {
   149  		lex := protolex.(*protoLex)
   150  		$$ = ast.NewFileNode(lex.info, nil, $1, lex.eof)
   151  		lex.res = $$
   152  	}
   153  	| syntax fileDecls {
   154  		lex := protolex.(*protoLex)
   155  		$$ = ast.NewFileNode(lex.info, $1, $2, lex.eof)
   156  		lex.res = $$
   157  	}
   158  	| {
   159  	}
   160  
   161  fileDecls : fileDecls fileDecl {
   162  		if $2 != nil {
   163  			$$ = append($1, $2)
   164  		} else {
   165  			$$ = $1
   166  		}
   167  	}
   168  	| fileDecl {
   169  		if $1 != nil {
   170  			$$ = []ast.FileElement{$1}
   171  		} else {
   172  			$$ = nil
   173  		}
   174  	}
   175  
   176  fileDecl : import {
   177  		$$ = $1
   178  	}
   179  	| package {
   180  		$$ = $1
   181  	}
   182  	| option {
   183  		$$ = $1
   184  	}
   185  	| message {
   186  		$$ = $1
   187  	}
   188  	| enum {
   189  		$$ = $1
   190  	}
   191  	| extend {
   192  		$$ = $1
   193  	}
   194  	| service {
   195  		$$ = $1
   196  	}
   197  	| ';' {
   198  		$$ = ast.NewEmptyDeclNode($1)
   199  	}
   200  	| error ';' {
   201  		$$ = nil
   202  	}
   203  	| error {
   204  		$$ = nil
   205  	}
   206  
   207  syntax : _SYNTAX '=' stringLit ';' {
   208  		$$ = ast.NewSyntaxNode($1.ToKeyword(), $2, $3.toStringValueNode(), $4)
   209  	}
   210  
   211  import : _IMPORT stringLit ';' {
   212  		$$ = ast.NewImportNode($1.ToKeyword(), nil, nil, $2.toStringValueNode(), $3)
   213  	}
   214  	| _IMPORT _WEAK stringLit ';' {
   215  		$$ = ast.NewImportNode($1.ToKeyword(), nil, $2.ToKeyword(), $3.toStringValueNode(), $4)
   216  	}
   217  	| _IMPORT _PUBLIC stringLit ';' {
   218  		$$ = ast.NewImportNode($1.ToKeyword(), $2.ToKeyword(), nil, $3.toStringValueNode(), $4)
   219  	}
   220  
   221  package : _PACKAGE ident ';' {
   222  		$$ = ast.NewPackageNode($1.ToKeyword(), $2.toIdentValueNode(nil), $3)
   223  	}
   224  
   225  ident : name {
   226  		$$ = &identList{$1, nil, nil}
   227  	}
   228  	| name '.' ident {
   229  		$$ = &identList{$1, $2, $3}
   230  	}
   231  
   232  // to mimic limitations of protoc recursive-descent parser,
   233  // we don't allowed message statement keywords as identifiers
   234  // (or oneof statement keywords [e.g. "option"] below)
   235  
   236  msgElementIdent : msgElementName {
   237  		$$ = &identList{$1, nil, nil}
   238  	}
   239  	| msgElementName '.' ident {
   240  		$$ = &identList{$1, $2, $3}
   241  	}
   242  
   243  extElementIdent : extElementName {
   244  		$$ = &identList{$1, nil, nil}
   245  	}
   246  	| extElementName '.' ident {
   247  		$$ = &identList{$1, $2, $3}
   248  	}
   249  
   250  oneofElementIdent : oneofElementName {
   251  		$$ = &identList{$1, nil, nil}
   252  	}
   253  	| oneofElementName '.' ident {
   254  		$$ = &identList{$1, $2, $3}
   255  	}
   256  
   257  option : _OPTION optionName '=' constant ';' {
   258  		refs, dots := $2.toNodes()
   259  		optName := ast.NewOptionNameNode(refs, dots)
   260  		$$ = ast.NewOptionNode($1.ToKeyword(), optName, $3, $4, $5)
   261  	}
   262  
   263  optionName : optionNameComponent {
   264  		$$ = &fieldRefList{$1, nil, nil}
   265  	}
   266  	| optionNameComponent '.' optionName {
   267  		$$ = &fieldRefList{$1, $2, $3}
   268  	}
   269  
   270  optionNameComponent : name {
   271  		$$ = ast.NewFieldReferenceNode($1)
   272  	}
   273  	| '(' typeIdent ')' {
   274  		$$ = ast.NewExtensionFieldReferenceNode($1, $2, $3)
   275  	}
   276  
   277  constant : scalarConstant
   278  	| aggregate
   279  
   280  scalarConstant : stringLit {
   281  		$$ = $1.toStringValueNode()
   282  	}
   283  	| numLit
   284  	| name {
   285  		if $1.Val == "true" || $1.Val == "false" {
   286  			$$ = ast.NewBoolLiteralNode($1.ToKeyword())
   287  		} else if $1.Val == "inf" || $1.Val == "nan" {
   288  			$$ = ast.NewSpecialFloatLiteralNode($1.ToKeyword())
   289  		} else {
   290  			$$ = $1
   291  		}
   292  	}
   293  
   294  numLit : _FLOAT_LIT {
   295  		$$ = $1
   296  	}
   297  	| '-' _FLOAT_LIT {
   298  		$$ = ast.NewSignedFloatLiteralNode($1, $2)
   299  	}
   300  	| '+' _FLOAT_LIT {
   301  		$$ = ast.NewSignedFloatLiteralNode($1, $2)
   302  	}
   303  	| '+' _INF {
   304  		f := ast.NewSpecialFloatLiteralNode($2.ToKeyword())
   305  		$$ = ast.NewSignedFloatLiteralNode($1, f)
   306  	}
   307  	| '-' _INF {
   308  		f := ast.NewSpecialFloatLiteralNode($2.ToKeyword())
   309  		$$ = ast.NewSignedFloatLiteralNode($1, f)
   310  	}
   311  	| _INT_LIT {
   312  		$$ = $1
   313  	}
   314  	| '+' _INT_LIT {
   315  		$$ = ast.NewPositiveUintLiteralNode($1, $2)
   316  	}
   317  	| '-' _INT_LIT {
   318  		if $2.Val > math.MaxInt64 + 1 {
   319  			// can't represent as int so treat as float literal
   320  			$$ = ast.NewSignedFloatLiteralNode($1, $2)
   321  		} else {
   322  			$$ = ast.NewNegativeIntLiteralNode($1, $2)
   323  		}
   324  	}
   325  
   326  stringLit : _STRING_LIT {
   327  		$$ = &stringList{$1, nil}
   328  	}
   329  	| _STRING_LIT stringLit  {
   330  		$$ = &stringList{$1, $2}
   331  	}
   332  
   333  aggregate : '{' aggFields '}' {
   334  		fields, delims := $2.toNodes()
   335  		$$ = ast.NewMessageLiteralNode($1, fields, delims, $3)
   336  	}
   337  
   338  aggFields : aggField {
   339  		if $1 != nil {
   340  			$$ = &messageFieldList{$1, nil}
   341  		} else {
   342  			$$ = nil
   343  		}
   344  	}
   345  	| aggField aggFields {
   346  		if $1 != nil {
   347  			$$ = &messageFieldList{$1, $2}
   348  		} else {
   349  			$$ = $2
   350  		}
   351  	}
   352  	| {
   353  		$$ = nil
   354  	}
   355  
   356  aggField : aggFieldEntry {
   357  		if $1 != nil {
   358  			$$ = &messageFieldEntry{$1, nil}
   359  		} else {
   360  			$$ = nil
   361  		}
   362  	}
   363  	| aggFieldEntry ',' {
   364  		if $1 != nil {
   365  			$$ = &messageFieldEntry{$1, $2}
   366  		} else {
   367  			$$ = nil
   368  		}
   369  	}
   370  	| aggFieldEntry ';' {
   371  		if $1 != nil {
   372  			$$ = &messageFieldEntry{$1, $2}
   373  		} else {
   374  			$$ = nil
   375  		}
   376  	}
   377  	| error ',' {
   378  		$$ = nil
   379  	}
   380  	| error ';' {
   381  		$$ = nil
   382  	}
   383  	| error {
   384  		$$ = nil
   385  	}
   386  
   387  aggFieldEntry : aggName ':' scalarConstant {
   388  		if $1 != nil {
   389  			$$ = ast.NewMessageFieldNode($1, $2, $3)
   390  		} else {
   391  			$$ = nil
   392  		}
   393  	}
   394  	| aggName '[' ']' {
   395  		if $1 != nil {
   396  			val := ast.NewArrayLiteralNode($2, nil, nil, $3)
   397  			$$ = ast.NewMessageFieldNode($1, nil, val)
   398  		} else {
   399  			$$ = nil
   400  		}
   401  	}
   402  	| aggName ':' '[' ']' {
   403  		if $1 != nil {
   404  			val := ast.NewArrayLiteralNode($3, nil, nil, $4)
   405  			$$ = ast.NewMessageFieldNode($1, $2, val)
   406  		} else {
   407  			$$ = nil
   408  		}
   409  	}
   410  	| aggName '[' constantList ']' {
   411  		if $1 != nil {
   412  			vals, commas := $3.toNodes()
   413  			val := ast.NewArrayLiteralNode($2, vals, commas, $4)
   414  			$$ = ast.NewMessageFieldNode($1, nil, val)
   415  		} else {
   416  			$$ = nil
   417  		}
   418  	}
   419  	| aggName ':' '[' constantList ']' {
   420  		if $1 != nil {
   421  			vals, commas := $4.toNodes()
   422  			val := ast.NewArrayLiteralNode($3, vals, commas, $5)
   423  			$$ = ast.NewMessageFieldNode($1, $2, val)
   424  		} else {
   425  			$$ = nil
   426  		}
   427  	}
   428  	| aggName ':' '[' error ']' {
   429  		$$ = nil
   430  	}
   431  	| aggName ':' aggregate {
   432  		if $1 != nil {
   433  			$$ = ast.NewMessageFieldNode($1, $2, $3)
   434  		} else {
   435  			$$ = nil
   436  		}
   437  	}
   438  	| aggName aggregate {
   439  		if $1 != nil {
   440  			$$ = ast.NewMessageFieldNode($1, nil, $2)
   441  		} else {
   442  			$$ = nil
   443  		}
   444  	}
   445  	| aggName ':' '<' aggFields '>' {
   446  		if $1 != nil {
   447  			fields, delims := $4.toNodes()
   448  			msg := ast.NewMessageLiteralNode($3, fields, delims, $5)
   449  			$$ = ast.NewMessageFieldNode($1, $2, msg)
   450  		} else {
   451  			$$ = nil
   452  		}
   453  	}
   454  	| aggName '<' aggFields '>' {
   455  		if $1 != nil {
   456  			fields, delims := $3.toNodes()
   457  			msg := ast.NewMessageLiteralNode($2, fields, delims, $4)
   458  			$$ = ast.NewMessageFieldNode($1, nil, msg)
   459  		} else {
   460  			$$ = nil
   461  		}
   462  	}
   463  	| aggName ':' '<' error '>' {
   464  		$$ = nil
   465  	}
   466  	| aggName '<' error '>' {
   467  		$$ = nil
   468  	}
   469  
   470  aggName : name {
   471  		$$ = ast.NewFieldReferenceNode($1)
   472  	}
   473  	| '[' typeIdent ']' {
   474  		$$ = ast.NewExtensionFieldReferenceNode($1, $2, $3)
   475  	}
   476  	| '[' error ']' {
   477  		$$ = nil
   478  	}
   479  
   480  constantList : constant {
   481  		$$ = &valueList{$1, nil, nil}
   482  	}
   483  	| constant ',' constantList {
   484  		$$ = &valueList{$1, $2, $3}
   485  	}
   486  	| '<' aggFields '>' {
   487  		fields, delims := $2.toNodes()
   488  		msg := ast.NewMessageLiteralNode($1, fields, delims, $3)
   489  		$$ = &valueList{msg, nil, nil}
   490  	}
   491  	| '<' aggFields '>' ',' constantList {
   492  		fields, delims := $2.toNodes()
   493  		msg := ast.NewMessageLiteralNode($1, fields, delims, $3)
   494  		$$ = &valueList{msg, $4, $5}
   495  	}
   496  	| '<' error '>' {
   497  		$$ = nil
   498  	}
   499  	| '<' error '>' ',' constantList {
   500  		$$ = $5
   501  	}
   502  
   503  typeIdent : ident {
   504  		$$ = $1.toIdentValueNode(nil)
   505  	}
   506  	| '.' ident {
   507  		$$ = $2.toIdentValueNode($1)
   508  	}
   509  
   510  msgElementTypeIdent : msgElementIdent {
   511  		$$ = $1.toIdentValueNode(nil)
   512  	}
   513  	| '.' ident {
   514  		$$ = $2.toIdentValueNode($1)
   515  	}
   516  
   517  extElementTypeIdent : extElementIdent {
   518  		$$ = $1.toIdentValueNode(nil)
   519  	}
   520  	| '.' ident {
   521  		$$ = $2.toIdentValueNode($1)
   522  	}
   523  
   524  oneofElementTypeIdent : oneofElementIdent {
   525  		$$ = $1.toIdentValueNode(nil)
   526  	}
   527  	| '.' ident {
   528  		$$ = $2.toIdentValueNode($1)
   529  	}
   530  
   531  msgField : _REQUIRED typeIdent name '=' _INT_LIT ';' {
   532  		$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, nil, $6)
   533  	}
   534  	| _OPTIONAL typeIdent name '=' _INT_LIT ';' {
   535  		$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, nil, $6)
   536  	}
   537  	| _REPEATED typeIdent name '=' _INT_LIT ';' {
   538  		$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, nil, $6)
   539  	}
   540  	| _REQUIRED typeIdent name '=' _INT_LIT compactOptions ';' {
   541  		$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, $6, $7)
   542  	}
   543  	| _OPTIONAL typeIdent name '=' _INT_LIT compactOptions ';' {
   544  		$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, $6, $7)
   545  	}
   546  	| _REPEATED typeIdent name '=' _INT_LIT compactOptions ';' {
   547  		$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, $6, $7)
   548  	}
   549  	| msgElementTypeIdent name '=' _INT_LIT ';' {
   550  		$$ = ast.NewFieldNode(nil, $1, $2, $3, $4, nil, $5)
   551  	}
   552  	| msgElementTypeIdent name '=' _INT_LIT compactOptions ';' {
   553  		$$ = ast.NewFieldNode(nil, $1, $2, $3, $4, $5, $6)
   554  	}
   555  
   556  extField : _REQUIRED typeIdent name '=' _INT_LIT ';' {
   557  		$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, nil, $6)
   558  	}
   559  	| _OPTIONAL typeIdent name '=' _INT_LIT ';' {
   560  		$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, nil, $6)
   561  	}
   562  	| _REPEATED typeIdent name '=' _INT_LIT ';' {
   563  		$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, nil, $6)
   564  	}
   565  	| _REQUIRED typeIdent name '=' _INT_LIT compactOptions ';' {
   566  		$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, $6, $7)
   567  	}
   568  	| _OPTIONAL typeIdent name '=' _INT_LIT compactOptions ';' {
   569  		$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, $6, $7)
   570  	}
   571  	| _REPEATED typeIdent name '=' _INT_LIT compactOptions ';' {
   572  		$$ = ast.NewFieldNode($1.ToKeyword(), $2, $3, $4, $5, $6, $7)
   573  	}
   574  	| extElementTypeIdent name '=' _INT_LIT ';' {
   575  		$$ = ast.NewFieldNode(nil, $1, $2, $3, $4, nil, $5)
   576  	}
   577  	| extElementTypeIdent name '=' _INT_LIT compactOptions ';' {
   578  		$$ = ast.NewFieldNode(nil, $1, $2, $3, $4, $5, $6)
   579  	}
   580  
   581  compactOptions: '[' compactOptionDecls ']' {
   582  		opts, commas := $2.toNodes()
   583  		$$ = ast.NewCompactOptionsNode($1, opts, commas, $3)
   584  	}
   585  
   586  compactOptionDecls : compactOption {
   587  		$$ = &compactOptionList{$1, nil, nil}
   588  	}
   589  	| compactOption ',' compactOptionDecls {
   590  		$$ = &compactOptionList{$1, $2, $3}
   591  	}
   592  
   593  compactOption: optionName '=' constant {
   594  		refs, dots := $1.toNodes()
   595  		optName := ast.NewOptionNameNode(refs, dots)
   596  		$$ = ast.NewCompactOptionNode(optName, $2, $3)
   597  	}
   598  
   599  group : _REQUIRED _GROUP name '=' _INT_LIT '{' messageDecls '}' {
   600  		$$ = ast.NewGroupNode($1.ToKeyword(), $2.ToKeyword(), $3, $4, $5, nil, $6, $7, $8)
   601  	}
   602  	| _OPTIONAL _GROUP name '=' _INT_LIT '{' messageDecls '}' {
   603  		$$ = ast.NewGroupNode($1.ToKeyword(), $2.ToKeyword(), $3, $4, $5, nil, $6, $7, $8)
   604  	}
   605  	| _REPEATED _GROUP name '=' _INT_LIT '{' messageDecls '}' {
   606  		$$ = ast.NewGroupNode($1.ToKeyword(), $2.ToKeyword(), $3, $4, $5, nil, $6, $7, $8)
   607  	}
   608  	| _REQUIRED _GROUP name '=' _INT_LIT compactOptions '{' messageDecls '}' {
   609  		$$ = ast.NewGroupNode($1.ToKeyword(), $2.ToKeyword(), $3, $4, $5, $6, $7, $8, $9)
   610  	}
   611  	| _OPTIONAL _GROUP name '=' _INT_LIT compactOptions '{' messageDecls '}' {
   612  		$$ = ast.NewGroupNode($1.ToKeyword(), $2.ToKeyword(), $3, $4, $5, $6, $7, $8, $9)
   613  	}
   614  	| _REPEATED _GROUP name '=' _INT_LIT compactOptions '{' messageDecls '}' {
   615  		$$ = ast.NewGroupNode($1.ToKeyword(), $2.ToKeyword(), $3, $4, $5, $6, $7, $8, $9)
   616  	}
   617  
   618  oneof : _ONEOF name '{' ooDecls '}' {
   619  		$$ = ast.NewOneOfNode($1.ToKeyword(), $2, $3, $4, $5)
   620  	}
   621  
   622  ooDecls : ooDecls ooDecl {
   623  		if $2 != nil {
   624  			$$ = append($1, $2)
   625  		} else {
   626  			$$ = $1
   627  		}
   628  	}
   629  	| ooDecl {
   630  		if $1 != nil {
   631  			$$ = []ast.OneOfElement{$1}
   632  		} else {
   633  			$$ = nil
   634  		}
   635  	}
   636  	| {
   637  		$$ = nil
   638  	}
   639  
   640  ooDecl : option {
   641  		$$ = $1
   642  	}
   643  	| oneofField {
   644  		$$ = $1
   645  	}
   646  	| oneofGroup {
   647  		$$ = $1
   648  	}
   649  	| ';' {
   650  		$$ = ast.NewEmptyDeclNode($1)
   651  	}
   652  	| error ';' {
   653  		$$ = nil
   654  	}
   655  	| error {
   656  		$$ = nil
   657  	}
   658  
   659  oneofField : oneofElementTypeIdent name '=' _INT_LIT ';' {
   660  		$$ = ast.NewFieldNode(nil, $1, $2, $3, $4, nil, $5)
   661  	}
   662  	| oneofElementTypeIdent name '=' _INT_LIT compactOptions ';' {
   663  		$$ = ast.NewFieldNode(nil, $1, $2, $3, $4, $5, $6)
   664  	}
   665  
   666  oneofGroup : _GROUP name '=' _INT_LIT '{' messageDecls '}' {
   667  		$$ = ast.NewGroupNode(nil, $1.ToKeyword(), $2, $3, $4, nil, $5, $6, $7)
   668  	}
   669  	| _GROUP name '=' _INT_LIT compactOptions '{' messageDecls '}' {
   670  		$$ = ast.NewGroupNode(nil, $1.ToKeyword(), $2, $3, $4, $5, $6, $7, $8)
   671  	}
   672  
   673  mapField : mapType name '=' _INT_LIT ';' {
   674  		$$ = ast.NewMapFieldNode($1, $2, $3, $4, nil, $5)
   675  	}
   676  	| mapType name '=' _INT_LIT compactOptions ';' {
   677  		$$ = ast.NewMapFieldNode($1, $2, $3, $4, $5, $6)
   678  	}
   679  
   680  mapType : _MAP '<' keyType ',' typeIdent '>' {
   681  		$$ = ast.NewMapTypeNode($1.ToKeyword(), $2, $3, $4, $5, $6)
   682  	}
   683  
   684  keyType : _INT32
   685  	| _INT64
   686  	| _UINT32
   687  	| _UINT64
   688  	| _SINT32
   689  	| _SINT64
   690  	| _FIXED32
   691  	| _FIXED64
   692  	| _SFIXED32
   693  	| _SFIXED64
   694  	| _BOOL
   695  	| _STRING
   696  
   697  extensions : _EXTENSIONS tagRanges ';' {
   698  		ranges, commas := $2.toNodes()
   699  		$$ = ast.NewExtensionRangeNode($1.ToKeyword(), ranges, commas, nil, $3)
   700  	}
   701  	| _EXTENSIONS tagRanges compactOptions ';' {
   702  		ranges, commas := $2.toNodes()
   703  		$$ = ast.NewExtensionRangeNode($1.ToKeyword(), ranges, commas, $3, $4)
   704  	}
   705  
   706  tagRanges : tagRange {
   707  		$$ = &rangeList{$1, nil, nil}
   708  	}
   709  	| tagRange ',' tagRanges {
   710  		$$ = &rangeList{$1, $2, $3}
   711  	}
   712  
   713  tagRange : _INT_LIT {
   714  		$$ = ast.NewRangeNode($1, nil, nil, nil)
   715  	}
   716  	| _INT_LIT _TO _INT_LIT {
   717  		$$ = ast.NewRangeNode($1, $2.ToKeyword(), $3, nil)
   718  	}
   719  	| _INT_LIT _TO _MAX {
   720  		$$ = ast.NewRangeNode($1, $2.ToKeyword(), nil, $3.ToKeyword())
   721  	}
   722  
   723  enumRanges : enumRange {
   724  		$$ = &rangeList{$1, nil, nil}
   725  	}
   726  	| enumRange ',' enumRanges {
   727  		$$ = &rangeList{$1, $2, $3}
   728  	}
   729  
   730  enumRange : intLit {
   731  		$$ = ast.NewRangeNode($1, nil, nil, nil)
   732  	}
   733  	| intLit _TO intLit {
   734  		$$ = ast.NewRangeNode($1, $2.ToKeyword(), $3, nil)
   735  	}
   736  	| intLit _TO _MAX {
   737  		$$ = ast.NewRangeNode($1, $2.ToKeyword(), nil, $3.ToKeyword())
   738  	}
   739  
   740  intLit : _INT_LIT {
   741  		$$ = $1
   742  	}
   743  	| '-' _INT_LIT {
   744  		$$ = ast.NewNegativeIntLiteralNode($1, $2)
   745  	}
   746  
   747  msgReserved : _RESERVED tagRanges ';' {
   748  		ranges, commas := $2.toNodes()
   749  		$$ = ast.NewReservedRangesNode($1.ToKeyword(), ranges, commas, $3)
   750  	}
   751  	| reservedNames
   752  
   753  enumReserved : _RESERVED enumRanges ';' {
   754  		ranges, commas := $2.toNodes()
   755  		$$ = ast.NewReservedRangesNode($1.ToKeyword(), ranges, commas, $3)
   756  	}
   757  	| reservedNames
   758  
   759  reservedNames : _RESERVED fieldNames ';' {
   760  		names, commas := $2.toNodes()
   761  		$$ = ast.NewReservedNamesNode($1.ToKeyword(), names, commas, $3)
   762  	}
   763  
   764  fieldNames : stringLit {
   765  		$$ = &nameList{$1.toStringValueNode(), nil, nil}
   766  	}
   767  	| stringLit ',' fieldNames {
   768  		$$ = &nameList{$1.toStringValueNode(), $2, $3}
   769  	}
   770  
   771  enum : _ENUM name '{' enumDecls '}' {
   772  		$$ = ast.NewEnumNode($1.ToKeyword(), $2, $3, $4, $5)
   773  	}
   774  
   775  enumDecls : enumDecls enumDecl {
   776  		if $2 != nil {
   777  			$$ = append($1, $2)
   778  		} else {
   779  			$$ = $1
   780  		}
   781  	}
   782  	| enumDecl {
   783  		if $1 != nil {
   784  			$$ = []ast.EnumElement{$1}
   785  		} else {
   786  			$$ = nil
   787  		}
   788  	}
   789  	| {
   790  		$$ = nil
   791  	}
   792  
   793  enumDecl : option {
   794  		$$ = $1
   795  	}
   796  	| enumValue {
   797  		$$ = $1
   798  	}
   799  	| enumReserved {
   800  		$$ = $1
   801  	}
   802  	| ';' {
   803  		$$ = ast.NewEmptyDeclNode($1)
   804  	}
   805  	| error ';' {
   806  		$$ = nil
   807  	}
   808  	| error {
   809  		$$ = nil
   810  	}
   811  
   812  enumValue : enumElementName '=' intLit ';' {
   813  		$$ = ast.NewEnumValueNode($1, $2, $3, nil, $4)
   814  	}
   815  	|  enumElementName '=' intLit compactOptions ';' {
   816  		$$ = ast.NewEnumValueNode($1, $2, $3, $4, $5)
   817  	}
   818  
   819  message : _MESSAGE name '{' messageDecls '}' {
   820  		$$ = ast.NewMessageNode($1.ToKeyword(), $2, $3, $4, $5)
   821  	}
   822  
   823  messageDecls : messageDecls messageDecl {
   824  		if $2 != nil {
   825  			$$ = append($1, $2)
   826  		} else {
   827  			$$ = $1
   828  		}
   829  	}
   830  	| messageDecl {
   831  		if $1 != nil {
   832  			$$ = []ast.MessageElement{$1}
   833  		} else {
   834  			$$ = nil
   835  		}
   836  	}
   837  	| {
   838  		$$ = nil
   839  	}
   840  
   841  messageDecl : msgField {
   842  		$$ = $1
   843  	}
   844  	| enum {
   845  		$$ = $1
   846  	}
   847  	| message {
   848  		$$ = $1
   849  	}
   850  	| extend {
   851  		$$ = $1
   852  	}
   853  	| extensions {
   854  		$$ = $1
   855  	}
   856  	| group {
   857  		$$ = $1
   858  	}
   859  	| option {
   860  		$$ = $1
   861  	}
   862  	| oneof {
   863  		$$ = $1
   864  	}
   865  	| mapField {
   866  		$$ = $1
   867  	}
   868  	| msgReserved {
   869  		$$ = $1
   870  	}
   871  	| ';' {
   872  		$$ = ast.NewEmptyDeclNode($1)
   873  	}
   874  	| error ';' {
   875  		$$ = nil
   876  	}
   877  	| error {
   878  		$$ = nil
   879  	}
   880  
   881  extend : _EXTEND typeIdent '{' extendDecls '}' {
   882  		$$ = ast.NewExtendNode($1.ToKeyword(), $2, $3, $4, $5)
   883  	}
   884  
   885  extendDecls : extendDecls extendDecl {
   886  		if $2 != nil {
   887  			$$ = append($1, $2)
   888  		} else {
   889  			$$ = $1
   890  		}
   891  	}
   892  	| extendDecl {
   893  		if $1 != nil {
   894  			$$ = []ast.ExtendElement{$1}
   895  		} else {
   896  			$$ = nil
   897  		}
   898  	}
   899  	| {
   900  		$$ = nil
   901  	}
   902  
   903  extendDecl : extField {
   904  		$$ = $1
   905  	}
   906  	| group {
   907  		$$ = $1
   908  	}
   909  	| ';' {
   910  		$$ = ast.NewEmptyDeclNode($1)
   911  	}
   912  	| error ';' {
   913  		$$ = nil
   914  	}
   915  	| error {
   916  		$$ = nil
   917  	}
   918  
   919  service : _SERVICE name '{' serviceDecls '}' {
   920  		$$ = ast.NewServiceNode($1.ToKeyword(), $2, $3, $4, $5)
   921  	}
   922  
   923  serviceDecls : serviceDecls serviceDecl {
   924  		if $2 != nil {
   925  			$$ = append($1, $2)
   926  		} else {
   927  			$$ = $1
   928  		}
   929  	}
   930  	| serviceDecl {
   931  		if $1 != nil {
   932  			$$ = []ast.ServiceElement{$1}
   933  		} else {
   934  			$$ = nil
   935  		}
   936  	}
   937  	| {
   938  		$$ = nil
   939  	}
   940  
   941  // NB: doc suggests support for "stream" declaration, separate from "rpc", but
   942  // it does not appear to be supported in protoc (doc is likely from grammar for
   943  // Google-internal version of protoc, with support for streaming stubby)
   944  serviceDecl : option {
   945  		$$ = $1
   946  	}
   947  	| rpc {
   948  		$$ = $1
   949  	}
   950  	| ';' {
   951  		$$ = ast.NewEmptyDeclNode($1)
   952  	}
   953  	| error ';' {
   954  		$$ = nil
   955  	}
   956  	| error {
   957  		$$ = nil
   958  	}
   959  
   960  rpc : _RPC name rpcType _RETURNS rpcType ';' {
   961  		$$ = ast.NewRPCNode($1.ToKeyword(), $2, $3, $4.ToKeyword(), $5, $6)
   962  	}
   963  	| _RPC name rpcType _RETURNS rpcType '{' rpcDecls '}' {
   964  		$$ = ast.NewRPCNodeWithBody($1.ToKeyword(), $2, $3, $4.ToKeyword(), $5, $6, $7, $8)
   965  	}
   966  
   967  rpcType : '(' _STREAM typeIdent ')' {
   968  		$$ = ast.NewRPCTypeNode($1, $2.ToKeyword(), $3, $4)
   969  	}
   970  	| '(' typeIdent ')' {
   971  		$$ = ast.NewRPCTypeNode($1, nil, $2, $3)
   972  	}
   973  
   974  rpcDecls : rpcDecls rpcDecl {
   975  		if $2 != nil {
   976  			$$ = append($1, $2)
   977  		} else {
   978  			$$ = $1
   979  		}
   980  	}
   981  	| rpcDecl {
   982  		if $1 != nil {
   983  			$$ = []ast.RPCElement{$1}
   984  		} else {
   985  			$$ = nil
   986  		}
   987  	}
   988  	| {
   989  		$$ = nil
   990  	}
   991  
   992  rpcDecl : option {
   993  		$$ = $1
   994  	}
   995  	| ';' {
   996  		$$ = ast.NewEmptyDeclNode($1)
   997  	}
   998  	| error ';' {
   999  		$$ = nil
  1000  	}
  1001  	| error {
  1002  		$$ = nil
  1003  	}
  1004  
  1005  // excludes message, enum, oneof, extensions, reserved, extend,
  1006  //   option, optional, required, and repeated
  1007  msgElementName : _NAME
  1008  	| _SYNTAX
  1009  	| _IMPORT
  1010  	| _WEAK
  1011  	| _PUBLIC
  1012  	| _PACKAGE
  1013  	| _TRUE
  1014  	| _FALSE
  1015  	| _INF
  1016  	| _NAN
  1017  	| _DOUBLE
  1018  	| _FLOAT
  1019  	| _INT32
  1020  	| _INT64
  1021  	| _UINT32
  1022  	| _UINT64
  1023  	| _SINT32
  1024  	| _SINT64
  1025  	| _FIXED32
  1026  	| _FIXED64
  1027  	| _SFIXED32
  1028  	| _SFIXED64
  1029  	| _BOOL
  1030  	| _STRING
  1031  	| _BYTES
  1032  	| _GROUP
  1033  	| _MAP
  1034  	| _TO
  1035  	| _MAX
  1036  	| _SERVICE
  1037  	| _RPC
  1038  	| _STREAM
  1039  	| _RETURNS
  1040  
  1041  // excludes optional, required, and repeated
  1042  extElementName : _NAME
  1043  	| _SYNTAX
  1044  	| _IMPORT
  1045  	| _WEAK
  1046  	| _PUBLIC
  1047  	| _PACKAGE
  1048  	| _OPTION
  1049  	| _TRUE
  1050  	| _FALSE
  1051  	| _INF
  1052  	| _NAN
  1053  	| _DOUBLE
  1054  	| _FLOAT
  1055  	| _INT32
  1056  	| _INT64
  1057  	| _UINT32
  1058  	| _UINT64
  1059  	| _SINT32
  1060  	| _SINT64
  1061  	| _FIXED32
  1062  	| _FIXED64
  1063  	| _SFIXED32
  1064  	| _SFIXED64
  1065  	| _BOOL
  1066  	| _STRING
  1067  	| _BYTES
  1068  	| _GROUP
  1069  	| _ONEOF
  1070  	| _MAP
  1071  	| _EXTENSIONS
  1072  	| _TO
  1073  	| _MAX
  1074  	| _RESERVED
  1075  	| _ENUM
  1076  	| _MESSAGE
  1077  	| _EXTEND
  1078  	| _SERVICE
  1079  	| _RPC
  1080  	| _STREAM
  1081  	| _RETURNS
  1082  
  1083  // excludes reserved, option
  1084  enumElementName : _NAME
  1085  	| _SYNTAX
  1086  	| _IMPORT
  1087  	| _WEAK
  1088  	| _PUBLIC
  1089  	| _PACKAGE
  1090  	| _TRUE
  1091  	| _FALSE
  1092  	| _INF
  1093  	| _NAN
  1094  	| _REPEATED
  1095  	| _OPTIONAL
  1096  	| _REQUIRED
  1097  	| _DOUBLE
  1098  	| _FLOAT
  1099  	| _INT32
  1100  	| _INT64
  1101  	| _UINT32
  1102  	| _UINT64
  1103  	| _SINT32
  1104  	| _SINT64
  1105  	| _FIXED32
  1106  	| _FIXED64
  1107  	| _SFIXED32
  1108  	| _SFIXED64
  1109  	| _BOOL
  1110  	| _STRING
  1111  	| _BYTES
  1112  	| _GROUP
  1113  	| _ONEOF
  1114  	| _MAP
  1115  	| _EXTENSIONS
  1116  	| _TO
  1117  	| _MAX
  1118  	| _ENUM
  1119  	| _MESSAGE
  1120  	| _EXTEND
  1121  	| _SERVICE
  1122  	| _RPC
  1123  	| _STREAM
  1124  	| _RETURNS
  1125  
  1126  // excludes option, optional, required, and repeated
  1127  oneofElementName : _NAME
  1128  	| _SYNTAX
  1129  	| _IMPORT
  1130  	| _WEAK
  1131  	| _PUBLIC
  1132  	| _PACKAGE
  1133  	| _TRUE
  1134  	| _FALSE
  1135  	| _INF
  1136  	| _NAN
  1137  	| _DOUBLE
  1138  	| _FLOAT
  1139  	| _INT32
  1140  	| _INT64
  1141  	| _UINT32
  1142  	| _UINT64
  1143  	| _SINT32
  1144  	| _SINT64
  1145  	| _FIXED32
  1146  	| _FIXED64
  1147  	| _SFIXED32
  1148  	| _SFIXED64
  1149  	| _BOOL
  1150  	| _STRING
  1151  	| _BYTES
  1152  	| _GROUP
  1153  	| _ONEOF
  1154  	| _MAP
  1155  	| _EXTENSIONS
  1156  	| _TO
  1157  	| _MAX
  1158  	| _RESERVED
  1159  	| _ENUM
  1160  	| _MESSAGE
  1161  	| _EXTEND
  1162  	| _SERVICE
  1163  	| _RPC
  1164  	| _STREAM
  1165  	| _RETURNS
  1166  
  1167  name : _NAME
  1168  	| _SYNTAX
  1169  	| _IMPORT
  1170  	| _WEAK
  1171  	| _PUBLIC
  1172  	| _PACKAGE
  1173  	| _OPTION
  1174  	| _TRUE
  1175  	| _FALSE
  1176  	| _INF
  1177  	| _NAN
  1178  	| _REPEATED
  1179  	| _OPTIONAL
  1180  	| _REQUIRED
  1181  	| _DOUBLE
  1182  	| _FLOAT
  1183  	| _INT32
  1184  	| _INT64
  1185  	| _UINT32
  1186  	| _UINT64
  1187  	| _SINT32
  1188  	| _SINT64
  1189  	| _FIXED32
  1190  	| _FIXED64
  1191  	| _SFIXED32
  1192  	| _SFIXED64
  1193  	| _BOOL
  1194  	| _STRING
  1195  	| _BYTES
  1196  	| _GROUP
  1197  	| _ONEOF
  1198  	| _MAP
  1199  	| _EXTENSIONS
  1200  	| _TO
  1201  	| _MAX
  1202  	| _RESERVED
  1203  	| _ENUM
  1204  	| _MESSAGE
  1205  	| _EXTEND
  1206  	| _SERVICE
  1207  	| _RPC
  1208  	| _STREAM
  1209  	| _RETURNS
  1210  
  1211  %%