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 %%