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