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