]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/thrift/compiler/cpp/src/thrift/thrifty.yy
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / jaegertracing / thrift / compiler / cpp / src / thrift / thrifty.yy
1 %code requires {
2 #include "thrift/parse/t_program.h"
3 }
4 %{
5 /*
6 * Licensed to the Apache Software Foundation (ASF) under one
7 * or more contributor license agreements. See the NOTICE file
8 * distributed with this work for additional information
9 * regarding copyright ownership. The ASF licenses this file
10 * to you under the Apache License, Version 2.0 (the
11 * "License"); you may not use this file except in compliance
12 * with the License. You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing,
17 * software distributed under the License is distributed on an
18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 * KIND, either express or implied. See the License for the
20 * specific language governing permissions and limitations
21 * under the License.
22 */
23
24 /**
25 * Thrift parser.
26 *
27 * This parser is used on a thrift definition file.
28 *
29 */
30
31 #ifndef __STDC_LIMIT_MACROS
32 #define __STDC_LIMIT_MACROS
33 #endif
34 #ifndef __STDC_FORMAT_MACROS
35 #define __STDC_FORMAT_MACROS
36 #endif
37 #include <stdio.h>
38 #include <string.h>
39 #ifndef _MSC_VER
40 #include <inttypes.h>
41 #else
42 #include <stdint.h>
43 #endif
44 #include <limits.h>
45 #ifdef _MSC_VER
46 #include "thrift/windows/config.h"
47 #endif
48 #include "thrift/main.h"
49 #include "thrift/common.h"
50 #include "thrift/globals.h"
51 #include "thrift/parse/t_program.h"
52 #include "thrift/parse/t_scope.h"
53
54 #ifdef _MSC_VER
55 //warning C4065: switch statement contains 'default' but no 'case' labels
56 #pragma warning(disable:4065)
57 #endif
58
59 /**
60 * This global variable is used for automatic numbering of field indices etc.
61 * when parsing the members of a struct. Field values are automatically
62 * assigned starting from -1 and working their way down.
63 */
64 int y_field_val = -1;
65 /**
66 * This global variable is used for automatic numbering of enum values.
67 * y_enum_val is the last value assigned; the next auto-assigned value will be
68 * y_enum_val+1, and then it continues working upwards. Explicitly specified
69 * enum values reset y_enum_val to that value.
70 */
71 int32_t y_enum_val = -1;
72 int g_arglist = 0;
73 const int struct_is_struct = 0;
74 const int struct_is_union = 1;
75
76 %}
77
78 /**
79 * This structure is used by the parser to hold the data types associated with
80 * various parse nodes.
81 */
82 %union {
83 char* id;
84 int64_t iconst;
85 double dconst;
86 bool tbool;
87 t_doc* tdoc;
88 t_type* ttype;
89 t_base_type* tbase;
90 t_typedef* ttypedef;
91 t_enum* tenum;
92 t_enum_value* tenumv;
93 t_const* tconst;
94 t_const_value* tconstv;
95 t_struct* tstruct;
96 t_service* tservice;
97 t_function* tfunction;
98 t_field* tfield;
99 char* dtext;
100 t_field::e_req ereq;
101 t_annotation* tannot;
102 t_field_id tfieldid;
103 }
104
105 /**
106 * Strings identifier
107 */
108 %token<id> tok_identifier
109 %token<id> tok_literal
110 %token<dtext> tok_doctext
111
112 /**
113 * Constant values
114 */
115 %token<iconst> tok_int_constant
116 %token<dconst> tok_dub_constant
117
118 /**
119 * Header keywords
120 */
121 %token tok_include
122 %token tok_namespace
123 %token tok_cpp_include
124 %token tok_cpp_type
125 %token tok_xsd_all
126 %token tok_xsd_optional
127 %token tok_xsd_nillable
128 %token tok_xsd_attrs
129
130 /**
131 * Base datatype keywords
132 */
133 %token tok_void
134 %token tok_bool
135 %token tok_string
136 %token tok_binary
137 %token tok_slist
138 %token tok_senum
139 %token tok_i8
140 %token tok_i16
141 %token tok_i32
142 %token tok_i64
143 %token tok_double
144
145 /**
146 * Complex type keywords
147 */
148 %token tok_map
149 %token tok_list
150 %token tok_set
151
152 /**
153 * Function modifiers
154 */
155 %token tok_oneway
156
157 /**
158 * Thrift language keywords
159 */
160 %token tok_typedef
161 %token tok_struct
162 %token tok_xception
163 %token tok_throws
164 %token tok_extends
165 %token tok_service
166 %token tok_enum
167 %token tok_const
168 %token tok_required
169 %token tok_optional
170 %token tok_union
171 %token tok_reference
172
173 /**
174 * Grammar nodes
175 */
176
177 %type<ttype> BaseType
178 %type<ttype> SimpleBaseType
179 %type<ttype> ContainerType
180 %type<ttype> SimpleContainerType
181 %type<ttype> MapType
182 %type<ttype> SetType
183 %type<ttype> ListType
184
185 %type<tdoc> Definition
186 %type<ttype> TypeDefinition
187
188 %type<ttypedef> Typedef
189
190 %type<ttype> TypeAnnotations
191 %type<ttype> TypeAnnotationList
192 %type<tannot> TypeAnnotation
193 %type<id> TypeAnnotationValue
194
195 %type<tfield> Field
196 %type<tfieldid> FieldIdentifier
197 %type<ereq> FieldRequiredness
198 %type<ttype> FieldType
199 %type<tconstv> FieldValue
200 %type<tstruct> FieldList
201 %type<tbool> FieldReference
202
203 %type<tenum> Enum
204 %type<tenum> EnumDefList
205 %type<tenumv> EnumDef
206 %type<tenumv> EnumValue
207
208 %type<ttypedef> Senum
209 %type<tbase> SenumDefList
210 %type<id> SenumDef
211
212 %type<tconst> Const
213 %type<tconstv> ConstValue
214 %type<tconstv> ConstList
215 %type<tconstv> ConstListContents
216 %type<tconstv> ConstMap
217 %type<tconstv> ConstMapContents
218
219 %type<iconst> StructHead
220 %type<tstruct> Struct
221 %type<tstruct> Xception
222 %type<tservice> Service
223
224 %type<tfunction> Function
225 %type<ttype> FunctionType
226 %type<tservice> FunctionList
227
228 %type<tstruct> Throws
229 %type<tservice> Extends
230 %type<tbool> Oneway
231 %type<tbool> XsdAll
232 %type<tbool> XsdOptional
233 %type<tbool> XsdNillable
234 %type<tstruct> XsdAttributes
235 %type<id> CppType
236
237 %type<dtext> CaptureDocText
238
239 %%
240
241 /**
242 * Thrift Grammar Implementation.
243 *
244 * For the most part this source file works its way top down from what you
245 * might expect to find in a typical .thrift file, i.e. type definitions and
246 * namespaces up top followed by service definitions using those types.
247 */
248
249 Program:
250 HeaderList DefinitionList
251 {
252 pdebug("Program -> Headers DefinitionList");
253 if((g_program_doctext_candidate != NULL) && (g_program_doctext_status != ALREADY_PROCESSED))
254 {
255 g_program->set_doc(g_program_doctext_candidate);
256 g_program_doctext_status = ALREADY_PROCESSED;
257 }
258 clear_doctext();
259 }
260
261 CaptureDocText:
262 {
263 if (g_parse_mode == PROGRAM) {
264 $$ = g_doctext;
265 g_doctext = NULL;
266 } else {
267 $$ = NULL;
268 }
269 }
270
271 /* TODO(dreiss): Try to DestroyDocText in all sorts or random places. */
272 DestroyDocText:
273 {
274 if (g_parse_mode == PROGRAM) {
275 clear_doctext();
276 }
277 }
278
279 /* We have to DestroyDocText here, otherwise it catches the doctext
280 on the first real element. */
281 HeaderList:
282 HeaderList DestroyDocText Header
283 {
284 pdebug("HeaderList -> HeaderList Header");
285 }
286 |
287 {
288 pdebug("HeaderList -> ");
289 }
290
291 Header:
292 Include
293 {
294 pdebug("Header -> Include");
295 }
296 | tok_namespace tok_identifier tok_identifier TypeAnnotations
297 {
298 pdebug("Header -> tok_namespace tok_identifier tok_identifier");
299 declare_valid_program_doctext();
300 if (g_parse_mode == PROGRAM) {
301 g_program->set_namespace($2, $3);
302 }
303 if ($4 != NULL) {
304 g_program->set_namespace_annotations($2, $4->annotations_);
305 delete $4;
306 }
307 }
308 | tok_namespace '*' tok_identifier
309 {
310 pdebug("Header -> tok_namespace * tok_identifier");
311 declare_valid_program_doctext();
312 if (g_parse_mode == PROGRAM) {
313 g_program->set_namespace("*", $3);
314 }
315 }
316 | tok_cpp_include tok_literal
317 {
318 pdebug("Header -> tok_cpp_include tok_literal");
319 declare_valid_program_doctext();
320 if (g_parse_mode == PROGRAM) {
321 g_program->add_cpp_include($2);
322 }
323 }
324
325 Include:
326 tok_include tok_literal
327 {
328 pdebug("Include -> tok_include tok_literal");
329 declare_valid_program_doctext();
330 if (g_parse_mode == INCLUDES) {
331 std::string path = include_file(std::string($2));
332 if (!path.empty()) {
333 g_program->add_include(path, std::string($2));
334 }
335 }
336 }
337
338 DefinitionList:
339 DefinitionList CaptureDocText Definition
340 {
341 pdebug("DefinitionList -> DefinitionList Definition");
342 if ($2 != NULL && $3 != NULL) {
343 $3->set_doc($2);
344 }
345 }
346 |
347 {
348 pdebug("DefinitionList -> ");
349 }
350
351 Definition:
352 Const
353 {
354 pdebug("Definition -> Const");
355 if (g_parse_mode == PROGRAM) {
356 g_program->add_const($1);
357 }
358 $$ = $1;
359 }
360 | TypeDefinition
361 {
362 pdebug("Definition -> TypeDefinition");
363 if (g_parse_mode == PROGRAM) {
364 g_scope->add_type($1->get_name(), $1);
365 if (g_parent_scope != NULL) {
366 g_parent_scope->add_type(g_parent_prefix + $1->get_name(), $1);
367 }
368 if (! g_program->is_unique_typename($1)) {
369 yyerror("Type \"%s\" is already defined.", $1->get_name().c_str());
370 exit(1);
371 }
372 }
373 $$ = $1;
374 }
375 | Service
376 {
377 pdebug("Definition -> Service");
378 if (g_parse_mode == PROGRAM) {
379 g_scope->add_service($1->get_name(), $1);
380 if (g_parent_scope != NULL) {
381 g_parent_scope->add_service(g_parent_prefix + $1->get_name(), $1);
382 }
383 g_program->add_service($1);
384 if (! g_program->is_unique_typename($1)) {
385 yyerror("Type \"%s\" is already defined.", $1->get_name().c_str());
386 exit(1);
387 }
388 }
389 $$ = $1;
390 }
391
392 TypeDefinition:
393 Typedef
394 {
395 pdebug("TypeDefinition -> Typedef");
396 if (g_parse_mode == PROGRAM) {
397 g_program->add_typedef($1);
398 }
399 }
400 | Enum
401 {
402 pdebug("TypeDefinition -> Enum");
403 if (g_parse_mode == PROGRAM) {
404 g_program->add_enum($1);
405 }
406 }
407 | Senum
408 {
409 pdebug("TypeDefinition -> Senum");
410 if (g_parse_mode == PROGRAM) {
411 g_program->add_typedef($1);
412 }
413 }
414 | Struct
415 {
416 pdebug("TypeDefinition -> Struct");
417 if (g_parse_mode == PROGRAM) {
418 g_program->add_struct($1);
419 }
420 }
421 | Xception
422 {
423 pdebug("TypeDefinition -> Xception");
424 if (g_parse_mode == PROGRAM) {
425 g_program->add_xception($1);
426 }
427 }
428
429 CommaOrSemicolonOptional:
430 ','
431 {}
432 | ';'
433 {}
434 |
435 {}
436
437 Typedef:
438 tok_typedef FieldType tok_identifier TypeAnnotations CommaOrSemicolonOptional
439 {
440 pdebug("TypeDef -> tok_typedef FieldType tok_identifier");
441 validate_simple_identifier( $3);
442 t_typedef *td = new t_typedef(g_program, $2, $3);
443 $$ = td;
444 if ($4 != NULL) {
445 $$->annotations_ = $4->annotations_;
446 delete $4;
447 }
448 }
449
450 Enum:
451 tok_enum tok_identifier '{' EnumDefList '}' TypeAnnotations
452 {
453 pdebug("Enum -> tok_enum tok_identifier { EnumDefList }");
454 $$ = $4;
455 validate_simple_identifier( $2);
456 $$->set_name($2);
457 if ($6 != NULL) {
458 $$->annotations_ = $6->annotations_;
459 delete $6;
460 }
461
462 // make constants for all the enum values
463 if (g_parse_mode == PROGRAM) {
464 const std::vector<t_enum_value*>& enum_values = $$->get_constants();
465 std::vector<t_enum_value*>::const_iterator c_iter;
466 for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) {
467 std::string const_name = $$->get_name() + "." + (*c_iter)->get_name();
468 t_const_value* const_val = new t_const_value((*c_iter)->get_value());
469 const_val->set_enum($$);
470 g_scope->add_constant(const_name, new t_const(g_type_i32, (*c_iter)->get_name(), const_val));
471 if (g_parent_scope != NULL) {
472 g_parent_scope->add_constant(g_parent_prefix + const_name, new t_const(g_type_i32, (*c_iter)->get_name(), const_val));
473 }
474 }
475 }
476 }
477
478 EnumDefList:
479 EnumDefList EnumDef
480 {
481 pdebug("EnumDefList -> EnumDefList EnumDef");
482 $$ = $1;
483 $$->append($2);
484 }
485 |
486 {
487 pdebug("EnumDefList -> ");
488 $$ = new t_enum(g_program);
489 y_enum_val = -1;
490 }
491
492 EnumDef:
493 CaptureDocText EnumValue TypeAnnotations CommaOrSemicolonOptional
494 {
495 pdebug("EnumDef -> EnumValue");
496 $$ = $2;
497 if ($1 != NULL) {
498 $$->set_doc($1);
499 }
500 if ($3 != NULL) {
501 $$->annotations_ = $3->annotations_;
502 delete $3;
503 }
504 }
505
506 EnumValue:
507 tok_identifier '=' tok_int_constant
508 {
509 pdebug("EnumValue -> tok_identifier = tok_int_constant");
510 if ($3 < INT32_MIN || $3 > INT32_MAX) {
511 // Note: this used to be just a warning. However, since thrift always
512 // treats enums as i32 values, I'm changing it to a fatal error.
513 // I doubt this will affect many people, but users who run into this
514 // will have to update their thrift files to manually specify the
515 // truncated i32 value that thrift has always been using anyway.
516 failure("64-bit value supplied for enum %s will be truncated.", $1);
517 }
518 y_enum_val = static_cast<int32_t>($3);
519 $$ = new t_enum_value($1, y_enum_val);
520 }
521 |
522 tok_identifier
523 {
524 pdebug("EnumValue -> tok_identifier");
525 validate_simple_identifier( $1);
526 if (y_enum_val == INT32_MAX) {
527 failure("enum value overflow at enum %s", $1);
528 }
529 ++y_enum_val;
530 $$ = new t_enum_value($1, y_enum_val);
531 }
532
533 Senum:
534 tok_senum tok_identifier '{' SenumDefList '}' TypeAnnotations
535 {
536 pdebug("Senum -> tok_senum tok_identifier { SenumDefList }");
537 validate_simple_identifier( $2);
538 $$ = new t_typedef(g_program, $4, $2);
539 if ($6 != NULL) {
540 $$->annotations_ = $6->annotations_;
541 delete $6;
542 }
543 }
544
545 SenumDefList:
546 SenumDefList SenumDef
547 {
548 pdebug("SenumDefList -> SenumDefList SenumDef");
549 $$ = $1;
550 $$->add_string_enum_val($2);
551 }
552 |
553 {
554 pdebug("SenumDefList -> ");
555 $$ = new t_base_type("string", t_base_type::TYPE_STRING);
556 $$->set_string_enum(true);
557 }
558
559 SenumDef:
560 tok_literal CommaOrSemicolonOptional
561 {
562 pdebug("SenumDef -> tok_literal");
563 $$ = $1;
564 }
565
566 Const:
567 tok_const FieldType tok_identifier '=' ConstValue CommaOrSemicolonOptional
568 {
569 pdebug("Const -> tok_const FieldType tok_identifier = ConstValue");
570 if (g_parse_mode == PROGRAM) {
571 validate_simple_identifier( $3);
572 g_scope->resolve_const_value($5, $2);
573 $$ = new t_const($2, $3, $5);
574 validate_const_type($$);
575
576 g_scope->add_constant($3, $$);
577 if (g_parent_scope != NULL) {
578 g_parent_scope->add_constant(g_parent_prefix + $3, $$);
579 }
580 } else {
581 $$ = NULL;
582 }
583 }
584
585 ConstValue:
586 tok_int_constant
587 {
588 pdebug("ConstValue => tok_int_constant");
589 $$ = new t_const_value();
590 $$->set_integer($1);
591 if (!g_allow_64bit_consts && ($1 < INT32_MIN || $1 > INT32_MAX)) {
592 pwarning(1, "64-bit constant \"%" PRIi64"\" may not work in all languages.\n", $1);
593 }
594 }
595 | tok_dub_constant
596 {
597 pdebug("ConstValue => tok_dub_constant");
598 $$ = new t_const_value();
599 $$->set_double($1);
600 }
601 | tok_literal
602 {
603 pdebug("ConstValue => tok_literal");
604 $$ = new t_const_value($1);
605 }
606 | tok_identifier
607 {
608 pdebug("ConstValue => tok_identifier");
609 $$ = new t_const_value();
610 $$->set_identifier($1);
611 }
612 | ConstList
613 {
614 pdebug("ConstValue => ConstList");
615 $$ = $1;
616 }
617 | ConstMap
618 {
619 pdebug("ConstValue => ConstMap");
620 $$ = $1;
621 }
622
623 ConstList:
624 '[' ConstListContents ']'
625 {
626 pdebug("ConstList => [ ConstListContents ]");
627 $$ = $2;
628 }
629
630 ConstListContents:
631 ConstListContents ConstValue CommaOrSemicolonOptional
632 {
633 pdebug("ConstListContents => ConstListContents ConstValue CommaOrSemicolonOptional");
634 $$ = $1;
635 $$->add_list($2);
636 }
637 |
638 {
639 pdebug("ConstListContents =>");
640 $$ = new t_const_value();
641 $$->set_list();
642 }
643
644 ConstMap:
645 '{' ConstMapContents '}'
646 {
647 pdebug("ConstMap => { ConstMapContents }");
648 $$ = $2;
649 }
650
651 ConstMapContents:
652 ConstMapContents ConstValue ':' ConstValue CommaOrSemicolonOptional
653 {
654 pdebug("ConstMapContents => ConstMapContents ConstValue CommaOrSemicolonOptional");
655 $$ = $1;
656 $$->add_map($2, $4);
657 }
658 |
659 {
660 pdebug("ConstMapContents =>");
661 $$ = new t_const_value();
662 $$->set_map();
663 }
664
665 StructHead:
666 tok_struct
667 {
668 $$ = struct_is_struct;
669 }
670 | tok_union
671 {
672 $$ = struct_is_union;
673 }
674
675 Struct:
676 StructHead tok_identifier XsdAll '{' FieldList '}' TypeAnnotations
677 {
678 pdebug("Struct -> tok_struct tok_identifier { FieldList }");
679 validate_simple_identifier( $2);
680 $5->set_xsd_all($3);
681 $5->set_union($1 == struct_is_union);
682 $$ = $5;
683 $$->set_name($2);
684 if ($7 != NULL) {
685 $$->annotations_ = $7->annotations_;
686 delete $7;
687 }
688 }
689
690 XsdAll:
691 tok_xsd_all
692 {
693 $$ = true;
694 }
695 |
696 {
697 $$ = false;
698 }
699
700 XsdOptional:
701 tok_xsd_optional
702 {
703 $$ = true;
704 }
705 |
706 {
707 $$ = false;
708 }
709
710 XsdNillable:
711 tok_xsd_nillable
712 {
713 $$ = true;
714 }
715 |
716 {
717 $$ = false;
718 }
719
720 XsdAttributes:
721 tok_xsd_attrs '{' FieldList '}'
722 {
723 $$ = $3;
724 }
725 |
726 {
727 $$ = NULL;
728 }
729
730 Xception:
731 tok_xception tok_identifier '{' FieldList '}' TypeAnnotations
732 {
733 pdebug("Xception -> tok_xception tok_identifier { FieldList }");
734 validate_simple_identifier( $2);
735 $4->set_name($2);
736 $4->set_xception(true);
737 $$ = $4;
738 if ($6 != NULL) {
739 $$->annotations_ = $6->annotations_;
740 delete $6;
741 }
742 }
743
744 Service:
745 tok_service tok_identifier Extends '{' FlagArgs FunctionList UnflagArgs '}' TypeAnnotations
746 {
747 pdebug("Service -> tok_service tok_identifier { FunctionList }");
748 validate_simple_identifier( $2);
749 $$ = $6;
750 $$->set_name($2);
751 $$->set_extends($3);
752 if ($9 != NULL) {
753 $$->annotations_ = $9->annotations_;
754 delete $9;
755 }
756 }
757
758 FlagArgs:
759 {
760 g_arglist = 1;
761 }
762
763 UnflagArgs:
764 {
765 g_arglist = 0;
766 }
767
768 Extends:
769 tok_extends tok_identifier
770 {
771 pdebug("Extends -> tok_extends tok_identifier");
772 $$ = NULL;
773 if (g_parse_mode == PROGRAM) {
774 $$ = g_scope->get_service($2);
775 if ($$ == NULL) {
776 yyerror("Service \"%s\" has not been defined.", $2);
777 exit(1);
778 }
779 }
780 }
781 |
782 {
783 $$ = NULL;
784 }
785
786 FunctionList:
787 FunctionList Function
788 {
789 pdebug("FunctionList -> FunctionList Function");
790 $$ = $1;
791 $1->add_function($2);
792 }
793 |
794 {
795 pdebug("FunctionList -> ");
796 $$ = new t_service(g_program);
797 }
798
799 Function:
800 CaptureDocText Oneway FunctionType tok_identifier '(' FieldList ')' Throws TypeAnnotations CommaOrSemicolonOptional
801 {
802 validate_simple_identifier( $4);
803 $6->set_name(std::string($4) + "_args");
804 $$ = new t_function($3, $4, $6, $8, $2);
805 if ($1 != NULL) {
806 $$->set_doc($1);
807 }
808 if ($9 != NULL) {
809 $$->annotations_ = $9->annotations_;
810 delete $9;
811 }
812 }
813
814 Oneway:
815 tok_oneway
816 {
817 $$ = true;
818 }
819 |
820 {
821 $$ = false;
822 }
823
824 Throws:
825 tok_throws '(' FieldList ')'
826 {
827 pdebug("Throws -> tok_throws ( FieldList )");
828 $$ = $3;
829 if (g_parse_mode == PROGRAM && !validate_throws($$)) {
830 yyerror("Throws clause may not contain non-exception types");
831 exit(1);
832 }
833 }
834 |
835 {
836 $$ = new t_struct(g_program);
837 }
838
839 FieldList:
840 FieldList Field
841 {
842 pdebug("FieldList -> FieldList , Field");
843 $$ = $1;
844 if (!($$->append($2))) {
845 yyerror("\"%d: %s\" - field identifier/name has already been used", $2->get_key(), $2->get_name().c_str());
846 exit(1);
847 }
848 }
849 |
850 {
851 pdebug("FieldList -> ");
852 y_field_val = -1;
853 $$ = new t_struct(g_program);
854 }
855
856 Field:
857 CaptureDocText FieldIdentifier FieldRequiredness FieldType FieldReference tok_identifier FieldValue XsdOptional XsdNillable XsdAttributes TypeAnnotations CommaOrSemicolonOptional
858 {
859 pdebug("tok_int_constant : Field -> FieldType tok_identifier");
860 if ($2.auto_assigned) {
861 pwarning(1, "No field key specified for %s, resulting protocol may have conflicts or not be backwards compatible!\n", $6);
862 if (g_strict >= 192) {
863 yyerror("Implicit field keys are deprecated and not allowed with -strict");
864 exit(1);
865 }
866 }
867 validate_simple_identifier($6);
868 $$ = new t_field($4, $6, $2.value);
869 $$->set_reference($5);
870 $$->set_req($3);
871 if ($7 != NULL) {
872 g_scope->resolve_const_value($7, $4);
873 validate_field_value($$, $7);
874 $$->set_value($7);
875 }
876 $$->set_xsd_optional($8);
877 $$->set_xsd_nillable($9);
878 if ($1 != NULL) {
879 $$->set_doc($1);
880 }
881 if ($10 != NULL) {
882 $$->set_xsd_attrs($10);
883 }
884 if ($11 != NULL) {
885 $$->annotations_ = $11->annotations_;
886 delete $11;
887 }
888 }
889
890 FieldIdentifier:
891 tok_int_constant ':'
892 {
893 if ($1 <= 0) {
894 if (g_allow_neg_field_keys) {
895 /*
896 * g_allow_neg_field_keys exists to allow users to add explicitly
897 * specified key values to old .thrift files without breaking
898 * protocol compatibility.
899 */
900 if ($1 != y_field_val) {
901 /*
902 * warn if the user-specified negative value isn't what
903 * thrift would have auto-assigned.
904 */
905 pwarning(1, "Nonpositive field key (%" PRIi64") differs from what would be "
906 "auto-assigned by thrift (%d).\n", $1, y_field_val);
907 }
908 /*
909 * Leave $1 as-is, and update y_field_val to be one less than $1.
910 * The FieldList parsing will catch any duplicate key values.
911 */
912 y_field_val = static_cast<int32_t>($1 - 1);
913 $$.value = static_cast<int32_t>($1);
914 $$.auto_assigned = false;
915 } else {
916 pwarning(1, "Nonpositive value (%d) not allowed as a field key.\n",
917 $1);
918 $$.value = y_field_val--;
919 $$.auto_assigned = true;
920 }
921 } else {
922 $$.value = static_cast<int32_t>($1);
923 $$.auto_assigned = false;
924 }
925 if( (SHRT_MIN > $$.value) || ($$.value > SHRT_MAX)) {
926 pwarning(1, "Field key (%d) exceeds allowed range (%d..%d).\n",
927 $$.value, SHRT_MIN, SHRT_MAX);
928 }
929 }
930 |
931 {
932 $$.value = y_field_val--;
933 $$.auto_assigned = true;
934 if( (SHRT_MIN > $$.value) || ($$.value > SHRT_MAX)) {
935 pwarning(1, "Field key (%d) exceeds allowed range (%d..%d).\n",
936 $$.value, SHRT_MIN, SHRT_MAX);
937 }
938 }
939
940 FieldReference:
941 tok_reference
942 {
943 $$ = true;
944 }
945 |
946 {
947 $$ = false;
948 }
949
950 FieldRequiredness:
951 tok_required
952 {
953 $$ = t_field::T_REQUIRED;
954 }
955 | tok_optional
956 {
957 if (g_arglist) {
958 if (g_parse_mode == PROGRAM) {
959 pwarning(1, "optional keyword is ignored in argument lists.\n");
960 }
961 $$ = t_field::T_OPT_IN_REQ_OUT;
962 } else {
963 $$ = t_field::T_OPTIONAL;
964 }
965 }
966 |
967 {
968 $$ = t_field::T_OPT_IN_REQ_OUT;
969 }
970
971 FieldValue:
972 '=' ConstValue
973 {
974 if (g_parse_mode == PROGRAM) {
975 $$ = $2;
976 } else {
977 $$ = NULL;
978 }
979 }
980 |
981 {
982 $$ = NULL;
983 }
984
985 FunctionType:
986 FieldType
987 {
988 pdebug("FunctionType -> FieldType");
989 $$ = $1;
990 }
991 | tok_void
992 {
993 pdebug("FunctionType -> tok_void");
994 $$ = g_type_void;
995 }
996
997 FieldType:
998 tok_identifier
999 {
1000 pdebug("FieldType -> tok_identifier");
1001 if (g_parse_mode == INCLUDES) {
1002 // Ignore identifiers in include mode
1003 $$ = NULL;
1004 } else {
1005 // Lookup the identifier in the current scope
1006 $$ = g_scope->get_type($1);
1007 if ($$ == NULL) {
1008 /*
1009 * Either this type isn't yet declared, or it's never
1010 declared. Either way allow it and we'll figure it out
1011 during generation.
1012 */
1013 $$ = new t_typedef(g_program, $1, true);
1014 }
1015 }
1016 }
1017 | BaseType
1018 {
1019 pdebug("FieldType -> BaseType");
1020 $$ = $1;
1021 }
1022 | ContainerType
1023 {
1024 pdebug("FieldType -> ContainerType");
1025 $$ = $1;
1026 }
1027
1028 BaseType: SimpleBaseType TypeAnnotations
1029 {
1030 pdebug("BaseType -> SimpleBaseType TypeAnnotations");
1031 if ($2 != NULL) {
1032 $$ = new t_base_type(*static_cast<t_base_type*>($1));
1033 $$->annotations_ = $2->annotations_;
1034 delete $2;
1035 } else {
1036 $$ = $1;
1037 }
1038 }
1039
1040 SimpleBaseType:
1041 tok_string
1042 {
1043 pdebug("BaseType -> tok_string");
1044 $$ = g_type_string;
1045 }
1046 | tok_binary
1047 {
1048 pdebug("BaseType -> tok_binary");
1049 $$ = g_type_binary;
1050 }
1051 | tok_slist
1052 {
1053 pdebug("BaseType -> tok_slist");
1054 $$ = g_type_slist;
1055 }
1056 | tok_bool
1057 {
1058 pdebug("BaseType -> tok_bool");
1059 $$ = g_type_bool;
1060 }
1061 | tok_i8
1062 {
1063 pdebug("BaseType -> tok_i8");
1064 $$ = g_type_i8;
1065 }
1066 | tok_i16
1067 {
1068 pdebug("BaseType -> tok_i16");
1069 $$ = g_type_i16;
1070 }
1071 | tok_i32
1072 {
1073 pdebug("BaseType -> tok_i32");
1074 $$ = g_type_i32;
1075 }
1076 | tok_i64
1077 {
1078 pdebug("BaseType -> tok_i64");
1079 $$ = g_type_i64;
1080 }
1081 | tok_double
1082 {
1083 pdebug("BaseType -> tok_double");
1084 $$ = g_type_double;
1085 }
1086
1087 ContainerType: SimpleContainerType TypeAnnotations
1088 {
1089 pdebug("ContainerType -> SimpleContainerType TypeAnnotations");
1090 $$ = $1;
1091 if ($2 != NULL) {
1092 $$->annotations_ = $2->annotations_;
1093 delete $2;
1094 }
1095 }
1096
1097 SimpleContainerType:
1098 MapType
1099 {
1100 pdebug("SimpleContainerType -> MapType");
1101 $$ = $1;
1102 }
1103 | SetType
1104 {
1105 pdebug("SimpleContainerType -> SetType");
1106 $$ = $1;
1107 }
1108 | ListType
1109 {
1110 pdebug("SimpleContainerType -> ListType");
1111 $$ = $1;
1112 }
1113
1114 MapType:
1115 tok_map CppType '<' FieldType ',' FieldType '>'
1116 {
1117 pdebug("MapType -> tok_map <FieldType, FieldType>");
1118 $$ = new t_map($4, $6);
1119 if ($2 != NULL) {
1120 ((t_container*)$$)->set_cpp_name(std::string($2));
1121 }
1122 }
1123
1124 SetType:
1125 tok_set CppType '<' FieldType '>'
1126 {
1127 pdebug("SetType -> tok_set<FieldType>");
1128 $$ = new t_set($4);
1129 if ($2 != NULL) {
1130 ((t_container*)$$)->set_cpp_name(std::string($2));
1131 }
1132 }
1133
1134 ListType:
1135 tok_list '<' FieldType '>' CppType
1136 {
1137 pdebug("ListType -> tok_list<FieldType>");
1138 check_for_list_of_bytes($3);
1139 $$ = new t_list($3);
1140 if ($5 != NULL) {
1141 ((t_container*)$$)->set_cpp_name(std::string($5));
1142 }
1143 }
1144
1145 CppType:
1146 tok_cpp_type tok_literal
1147 {
1148 $$ = $2;
1149 }
1150 |
1151 {
1152 $$ = NULL;
1153 }
1154
1155 TypeAnnotations:
1156 '(' TypeAnnotationList ')'
1157 {
1158 pdebug("TypeAnnotations -> ( TypeAnnotationList )");
1159 $$ = $2;
1160 }
1161 |
1162 {
1163 $$ = NULL;
1164 }
1165
1166 TypeAnnotationList:
1167 TypeAnnotationList TypeAnnotation
1168 {
1169 pdebug("TypeAnnotationList -> TypeAnnotationList , TypeAnnotation");
1170 $$ = $1;
1171 $$->annotations_[$2->key] = $2->val;
1172 delete $2;
1173 }
1174 |
1175 {
1176 /* Just use a dummy structure to hold the annotations. */
1177 $$ = new t_struct(g_program);
1178 }
1179
1180 TypeAnnotation:
1181 tok_identifier TypeAnnotationValue CommaOrSemicolonOptional
1182 {
1183 pdebug("TypeAnnotation -> TypeAnnotationValue");
1184 $$ = new t_annotation;
1185 $$->key = $1;
1186 $$->val = $2;
1187 }
1188
1189 TypeAnnotationValue:
1190 '=' tok_literal
1191 {
1192 pdebug("TypeAnnotationValue -> = tok_literal");
1193 $$ = $2;
1194 }
1195 |
1196 {
1197 pdebug("TypeAnnotationValue ->");
1198 $$ = strdup("1");
1199 }
1200
1201 %%