Line data Source code
1 : %{
2 : /*
3 : * Licensed to the Apache Software Foundation (ASF) under one
4 : * or more contributor license agreements. See the NOTICE file
5 : * distributed with this work for additional information
6 : * regarding copyright ownership. The ASF licenses this file
7 : * to you under the Apache License, Version 2.0 (the
8 : * "License"); you may not use this file except in compliance
9 : * with the License. You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing,
14 : * software distributed under the License is distributed on an
15 : * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 : * KIND, either express or implied. See the License for the
17 : * specific language governing permissions and limitations
18 : * under the License.
19 : */
20 :
21 : /**
22 : * Thrift parser.
23 : *
24 : * This parser is used on a thrift definition file.
25 : */
26 :
27 : #ifdef SANDESH
28 : /**
29 : * Sandesh parser.
30 : *
31 : * This parser is used on a sandesh definition file.
32 : *
33 : * sandesh domain specific langauge is derived from apache thrift and
34 : * much of thrift code is reused.
35 : */
36 : #endif
37 :
38 : #define __STDC_LIMIT_MACROS
39 : #define __STDC_FORMAT_MACROS
40 : #include <stdio.h>
41 : #include <inttypes.h>
42 : #include <limits.h>
43 : #include "main.h"
44 : #include "globals.h"
45 : #include "parse/t_program.h"
46 : #include "parse/t_scope.h"
47 :
48 : /**
49 : * This global variable is used for automatic numbering of field indices etc.
50 : * when parsing the members of a struct. Field values are automatically
51 : * assigned starting from -1 and working their way down.
52 : */
53 : int y_field_val = -1;
54 : int g_arglist = 0;
55 : const int struct_is_struct = 0;
56 : const int struct_is_union = 1;
57 :
58 : %}
59 :
60 : /**
61 : * This structure is used by the parser to hold the data types associated with
62 : * various parse nodes.
63 : */
64 : %union {
65 : char* id;
66 : int64_t iconst;
67 : double dconst;
68 : bool tbool;
69 : t_doc* tdoc;
70 : t_type* ttype;
71 : t_base_type* tbase;
72 : t_typedef* ttypedef;
73 : t_enum* tenum;
74 : t_enum_value* tenumv;
75 : t_const* tconst;
76 : t_const_value* tconstv;
77 : t_struct* tstruct;
78 : t_service* tservice;
79 : t_function* tfunction;
80 : t_field* tfield;
81 : char* dtext;
82 : t_field::e_req ereq;
83 : t_annotation* tannot;
84 : t_field_id tfieldid;
85 : t_sandesh* tsandesh;
86 : }
87 :
88 : /**
89 : * Strings identifier
90 : */
91 : %token<id> tok_identifier
92 : %token<id> tok_literal
93 : %token<dtext> tok_doctext
94 : %token<id> tok_st_identifier
95 : %token<id> tok_format
96 :
97 : /**
98 : * Constant values
99 : */
100 : %token<iconst> tok_int_constant
101 : %token<dconst> tok_dub_constant
102 :
103 : /**
104 : * Header keywords
105 : */
106 : %token tok_include
107 : %token tok_namespace
108 : %token tok_cpp_namespace
109 : %token tok_cpp_include
110 : %token tok_cpp_type
111 : %token tok_php_namespace
112 : %token tok_py_module
113 : %token tok_perl_package
114 : %token tok_java_package
115 : %token tok_xsd_all
116 : %token tok_xsd_optional
117 : %token tok_xsd_nillable
118 : %token tok_xsd_namespace
119 : %token tok_xsd_attrs
120 : %token tok_ruby_namespace
121 : %token tok_smalltalk_category
122 : %token tok_smalltalk_prefix
123 : %token tok_cocoa_prefix
124 : %token tok_csharp_namespace
125 : %token tok_delphi_namespace
126 :
127 : /**
128 : * Base datatype keywords
129 : */
130 : %token tok_void
131 : %token tok_bool
132 : %token tok_byte
133 : %token tok_string
134 : %token tok_binary
135 : %token tok_slist
136 : %token tok_senum
137 : %token tok_i16
138 : %token tok_i32
139 : %token tok_i64
140 : %token tok_double
141 : %token tok_u16
142 : %token tok_u32
143 : %token tok_u64
144 : %token tok_ipv4
145 : %token tok_ipaddr
146 : %token tok_xml
147 : %token tok_uuid_t
148 :
149 : /**
150 : * Complex type keywords
151 : */
152 : %token tok_map
153 : %token tok_list
154 : %token tok_set
155 :
156 : /**
157 : * Function modifiers
158 : */
159 : %token tok_oneway
160 : %token tok_staticfunction
161 : %token tok_abcfunction
162 :
163 : /**
164 : * Sandesh modifiers
165 : */
166 : %token tok_system
167 : %token tok_request
168 : %token tok_response
169 : %token tok_trace
170 : %token tok_object
171 : %token tok_flow
172 : %token tok_buffer
173 : %token tok_uve
174 : %token tok_dynamic_uve
175 : %token tok_trace_object
176 : %token tok_alarm
177 : %token tok_session
178 :
179 : /**
180 : * Thrift language keywords
181 : */
182 : %token tok_typedef
183 : %token tok_struct
184 : %token tok_xception
185 : %token tok_throws
186 : %token tok_extends
187 : %token tok_service
188 : %token tok_sandesh
189 : %token tok_enum
190 : %token tok_const
191 : %token tok_required
192 : %token tok_optional
193 : %token tok_union
194 :
195 : /**
196 : * Grammar nodes
197 : */
198 :
199 : %type<ttype> BaseType
200 : %type<ttype> SimpleBaseType
201 : %type<ttype> ContainerType
202 : %type<ttype> SimpleContainerType
203 : %type<ttype> MapType
204 : %type<ttype> SetType
205 : %type<ttype> ListType
206 :
207 : %type<tdoc> Definition
208 : %type<ttype> TypeDefinition
209 :
210 : %type<ttypedef> Typedef
211 :
212 : %type<ttype> TypeAnnotations
213 : %type<ttype> TypeAnnotationList
214 : %type<tannot> TypeAnnotation
215 :
216 : %type<tfield> Field
217 : %type<tfieldid> FieldIdentifier
218 : %type<ereq> FieldRequiredness
219 : %type<ttype> FieldType
220 : %type<tconstv> FieldValue
221 : %type<tstruct> FieldList
222 : %type<tsandesh> SFieldList
223 :
224 : %type<tenum> Enum
225 : %type<tenum> EnumDefList
226 : %type<tenumv> EnumDef
227 :
228 : %type<ttypedef> Senum
229 : %type<tbase> SenumDefList
230 : %type<id> SenumDef
231 :
232 : %type<tconst> Const
233 : %type<tconstv> ConstValue
234 : %type<tconstv> ConstList
235 : %type<tconstv> ConstListContents
236 : %type<tconstv> ConstMap
237 : %type<tconstv> ConstMapContents
238 :
239 : %type<iconst> StructHead
240 : %type<tstruct> Struct
241 : %type<tstruct> Xception
242 : %type<tservice> Service
243 : %type<tsandesh> Sandesh
244 : %type<ttype> SandeshType
245 :
246 : %type<tfunction> Function
247 : %type<ttype> FunctionType
248 : %type<tservice> FunctionList
249 :
250 : %type<tstruct> Throws
251 : %type<tservice> Extends
252 : %type<tbool> Oneway
253 : %type<tbool> StaticFunction
254 : %type<tbool> AbcFunction
255 : %type<tbool> XsdAll
256 : %type<tbool> XsdOptional
257 : %type<tbool> XsdNillable
258 : %type<tstruct> XsdAttributes
259 : %type<id> CppType
260 :
261 : %type<dtext> CaptureDocText
262 :
263 : %%
264 :
265 : /**
266 : * Thrift Grammar Implementation.
267 : *
268 : * For the most part this source file works its way top down from what you
269 : * might expect to find in a typical .thrift file, i.e. type definitions and
270 : * namespaces up top followed by service definitions using those types.
271 : */
272 :
273 : Program:
274 : HeaderList DefinitionList
275 : {
276 584 : pdebug("Program -> Headers DefinitionList");
277 584 : if((g_program_doctext_candidate != NULL) && (g_program_doctext_status != ALREADY_PROCESSED))
278 : {
279 164 : g_program->set_doc(g_program_doctext_candidate);
280 164 : g_program_doctext_status = ALREADY_PROCESSED;
281 : }
282 584 : clear_doctext();
283 : }
284 :
285 : CaptureDocText:
286 : {
287 26044 : if (g_parse_mode == PROGRAM) {
288 13022 : $$ = g_doctext;
289 13022 : g_doctext = NULL;
290 : } else {
291 13022 : $$ = NULL;
292 : }
293 : }
294 :
295 : /* TODO(dreiss): Try to DestroyDocText in all sorts or random places. */
296 : DestroyDocText:
297 : {
298 132 : if (g_parse_mode == PROGRAM) {
299 66 : clear_doctext();
300 : }
301 : }
302 :
303 : /* We have to DestroyDocText here, otherwise it catches the doctext
304 : on the first real element. */
305 : HeaderList:
306 : HeaderList DestroyDocText Header
307 : {
308 132 : pdebug("HeaderList -> HeaderList Header");
309 : }
310 : |
311 : {
312 584 : pdebug("HeaderList -> ");
313 : }
314 :
315 : Header:
316 : Include
317 : {
318 72 : pdebug("Header -> Include");
319 : }
320 : | tok_namespace tok_identifier tok_identifier
321 : {
322 60 : pdebug("Header -> tok_namespace tok_identifier tok_identifier");
323 60 : if (g_parse_mode == PROGRAM) {
324 30 : g_program->set_namespace($2, $3);
325 : }
326 : }
327 : | tok_namespace '*' tok_identifier
328 : {
329 0 : pdebug("Header -> tok_namespace * tok_identifier");
330 0 : if (g_parse_mode == PROGRAM) {
331 0 : g_program->set_namespace("*", $3);
332 : }
333 : }
334 :
335 : /* TODO(dreiss): Get rid of this once everyone is using the new hotness. */
336 : | tok_cpp_namespace tok_identifier
337 : {
338 0 : pwarning(1, "'cpp_namespace' is deprecated. Use 'namespace cpp' instead");
339 0 : pdebug("Header -> tok_cpp_namespace tok_identifier");
340 0 : if (g_parse_mode == PROGRAM) {
341 0 : g_program->set_namespace("cpp", $2);
342 : }
343 : }
344 : | tok_cpp_include tok_literal
345 : {
346 0 : pdebug("Header -> tok_cpp_include tok_literal");
347 0 : if (g_parse_mode == PROGRAM) {
348 0 : g_program->add_cpp_include($2);
349 : }
350 : }
351 : | tok_php_namespace tok_identifier
352 : {
353 0 : pwarning(1, "'php_namespace' is deprecated. Use 'namespace php' instead");
354 0 : pdebug("Header -> tok_php_namespace tok_identifier");
355 0 : if (g_parse_mode == PROGRAM) {
356 0 : g_program->set_namespace("php", $2);
357 : }
358 : }
359 : /* TODO(dreiss): Get rid of this once everyone is using the new hotness. */
360 : | tok_py_module tok_identifier
361 : {
362 0 : pwarning(1, "'py_module' is deprecated. Use 'namespace py' instead");
363 0 : pdebug("Header -> tok_py_module tok_identifier");
364 0 : if (g_parse_mode == PROGRAM) {
365 0 : g_program->set_namespace("py", $2);
366 : }
367 : }
368 : /* TODO(dreiss): Get rid of this once everyone is using the new hotness. */
369 : | tok_perl_package tok_identifier
370 : {
371 0 : pwarning(1, "'perl_package' is deprecated. Use 'namespace perl' instead");
372 0 : pdebug("Header -> tok_perl_namespace tok_identifier");
373 0 : if (g_parse_mode == PROGRAM) {
374 0 : g_program->set_namespace("perl", $2);
375 : }
376 : }
377 : /* TODO(dreiss): Get rid of this once everyone is using the new hotness. */
378 : | tok_ruby_namespace tok_identifier
379 : {
380 0 : pwarning(1, "'ruby_namespace' is deprecated. Use 'namespace rb' instead");
381 0 : pdebug("Header -> tok_ruby_namespace tok_identifier");
382 0 : if (g_parse_mode == PROGRAM) {
383 0 : g_program->set_namespace("rb", $2);
384 : }
385 : }
386 : /* TODO(dreiss): Get rid of this once everyone is using the new hotness. */
387 : | tok_smalltalk_category tok_st_identifier
388 : {
389 0 : pwarning(1, "'smalltalk_category' is deprecated. Use 'namespace smalltalk.category' instead");
390 0 : pdebug("Header -> tok_smalltalk_category tok_st_identifier");
391 0 : if (g_parse_mode == PROGRAM) {
392 0 : g_program->set_namespace("smalltalk.category", $2);
393 : }
394 : }
395 : /* TODO(dreiss): Get rid of this once everyone is using the new hotness. */
396 : | tok_smalltalk_prefix tok_identifier
397 : {
398 0 : pwarning(1, "'smalltalk_prefix' is deprecated. Use 'namespace smalltalk.prefix' instead");
399 0 : pdebug("Header -> tok_smalltalk_prefix tok_identifier");
400 0 : if (g_parse_mode == PROGRAM) {
401 0 : g_program->set_namespace("smalltalk.prefix", $2);
402 : }
403 : }
404 : /* TODO(dreiss): Get rid of this once everyone is using the new hotness. */
405 : | tok_java_package tok_identifier
406 : {
407 0 : pwarning(1, "'java_package' is deprecated. Use 'namespace java' instead");
408 0 : pdebug("Header -> tok_java_package tok_identifier");
409 0 : if (g_parse_mode == PROGRAM) {
410 0 : g_program->set_namespace("java", $2);
411 : }
412 : }
413 : /* TODO(dreiss): Get rid of this once everyone is using the new hotness. */
414 : | tok_cocoa_prefix tok_identifier
415 : {
416 0 : pwarning(1, "'cocoa_prefix' is deprecated. Use 'namespace cocoa' instead");
417 0 : pdebug("Header -> tok_cocoa_prefix tok_identifier");
418 0 : if (g_parse_mode == PROGRAM) {
419 0 : g_program->set_namespace("cocoa", $2);
420 : }
421 : }
422 : /* TODO(dreiss): Get rid of this once everyone is using the new hotness. */
423 : | tok_xsd_namespace tok_literal
424 : {
425 0 : pwarning(1, "'xsd_namespace' is deprecated. Use 'namespace xsd' instead");
426 0 : pdebug("Header -> tok_xsd_namespace tok_literal");
427 0 : if (g_parse_mode == PROGRAM) {
428 0 : g_program->set_namespace("cocoa", $2);
429 : }
430 : }
431 : /* TODO(dreiss): Get rid of this once everyone is using the new hotness. */
432 : | tok_csharp_namespace tok_identifier
433 : {
434 0 : pwarning(1, "'csharp_namespace' is deprecated. Use 'namespace csharp' instead");
435 0 : pdebug("Header -> tok_csharp_namespace tok_identifier");
436 0 : if (g_parse_mode == PROGRAM) {
437 0 : g_program->set_namespace("csharp", $2);
438 : }
439 : }
440 : /* TODO(dreiss): Get rid of this once everyone is using the new hotness. */
441 : | tok_delphi_namespace tok_identifier
442 : {
443 0 : pwarning(1, "'delphi_namespace' is deprecated. Use 'namespace delphi' instead");
444 0 : pdebug("Header -> tok_delphi_namespace tok_identifier");
445 0 : if (g_parse_mode == PROGRAM) {
446 0 : g_program->set_namespace("delphi", $2);
447 : }
448 : }
449 :
450 : Include:
451 : tok_include tok_literal
452 : {
453 72 : pdebug("Include -> tok_include tok_literal");
454 72 : if (g_parse_mode == INCLUDES) {
455 72 : std::string path = include_file(std::string($2));
456 36 : if (!path.empty()) {
457 36 : g_program->add_include(path, std::string($2));
458 : }
459 36 : }
460 : }
461 :
462 : DefinitionList:
463 : DefinitionList CaptureDocText Definition
464 : {
465 7240 : pdebug("DefinitionList -> DefinitionList Definition");
466 7240 : if ($2 != NULL && $3 != NULL) {
467 800 : $3->set_doc($2);
468 : }
469 : }
470 : |
471 : {
472 584 : pdebug("DefinitionList -> ");
473 : }
474 :
475 : Definition:
476 : Const
477 : {
478 2544 : pdebug("Definition -> Const");
479 2544 : if (g_parse_mode == PROGRAM) {
480 1272 : g_program->add_const($1);
481 : }
482 2544 : $$ = $1;
483 : }
484 : | TypeDefinition
485 : {
486 2536 : pdebug("Definition -> TypeDefinition");
487 2536 : if (g_parse_mode == PROGRAM) {
488 1268 : g_scope->add_type($1->get_name(), $1);
489 1268 : if (g_parent_scope != NULL) {
490 246 : g_parent_scope->add_type(g_parent_prefix + $1->get_name(), $1);
491 : }
492 : }
493 2536 : $$ = $1;
494 : }
495 : | Service
496 : {
497 0 : pdebug("Definition -> Service");
498 0 : if (g_parse_mode == PROGRAM) {
499 0 : g_scope->add_service($1->get_name(), $1);
500 0 : if (g_parent_scope != NULL) {
501 0 : g_parent_scope->add_service(g_parent_prefix + $1->get_name(), $1);
502 : }
503 0 : g_program->add_service($1);
504 : }
505 0 : $$ = $1;
506 : }
507 : | Sandesh
508 : {
509 2160 : pdebug("Definition -> Sandesh");
510 2160 : if (g_parse_mode == PROGRAM) {
511 1080 : if (g_scope->get_sandesh($1->get_name())) {
512 0 : yyerror("Duplicate definition of sandesh: %s ", $1->get_name().c_str());
513 0 : exit(1);
514 : }
515 1080 : g_scope->add_sandesh($1->get_name(), $1);
516 1080 : if (g_parent_scope != NULL) {
517 108 : g_parent_scope->add_sandesh(g_parent_prefix + $1->get_name(), $1);
518 : }
519 1080 : g_program->add_sandesh($1);
520 : }
521 2160 : $$ = $1;
522 : }
523 :
524 :
525 : TypeDefinition:
526 : Typedef
527 : {
528 0 : pdebug("TypeDefinition -> Typedef");
529 0 : if (g_parse_mode == PROGRAM) {
530 0 : g_program->add_typedef($1);
531 : }
532 : }
533 : | Enum
534 : {
535 396 : pdebug("TypeDefinition -> Enum");
536 396 : if (g_parse_mode == PROGRAM) {
537 198 : g_program->add_enum($1);
538 : }
539 : }
540 : | Senum
541 : {
542 0 : pdebug("TypeDefinition -> Senum");
543 0 : if (g_parse_mode == PROGRAM) {
544 0 : g_program->add_typedef($1);
545 : }
546 : }
547 : | Struct
548 : {
549 2140 : pdebug("TypeDefinition -> Struct");
550 2140 : if (g_parse_mode == PROGRAM) {
551 1070 : g_program->add_struct($1);
552 : }
553 : }
554 : | Xception
555 : {
556 0 : pdebug("TypeDefinition -> Xception");
557 0 : if (g_parse_mode == PROGRAM) {
558 0 : g_program->add_xception($1);
559 : }
560 : }
561 :
562 : Typedef:
563 : tok_typedef FieldType tok_identifier
564 : {
565 0 : pdebug("TypeDef -> tok_typedef FieldType tok_identifier");
566 0 : t_typedef *td = new t_typedef(g_program, $2, $3);
567 0 : $$ = td;
568 : }
569 :
570 : CommaOrSemicolonOptional:
571 : ','
572 : {}
573 : | ';'
574 : {}
575 : |
576 : {}
577 :
578 : Enum:
579 : tok_enum tok_identifier '{' EnumDefList '}'
580 : {
581 396 : pdebug("Enum -> tok_enum tok_identifier { EnumDefList }");
582 396 : $$ = $4;
583 396 : $$->set_name($2);
584 396 : $$->resolve_values();
585 : // make constants for all the enum values
586 396 : if (g_parse_mode == PROGRAM) {
587 198 : const std::vector<t_enum_value*>& enum_values = $$->get_constants();
588 198 : std::vector<t_enum_value*>::const_iterator c_iter;
589 1800 : for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) {
590 1602 : std::string const_name = $$->get_name() + "." + (*c_iter)->get_name();
591 1602 : t_const_value* const_val = new t_const_value((*c_iter)->get_value());
592 1602 : const_val->set_enum($$);
593 1602 : g_scope->add_constant(const_name, new t_const(g_type_i32, (*c_iter)->get_name(), const_val));
594 1602 : if (g_parent_scope != NULL) {
595 288 : g_parent_scope->add_constant(g_parent_prefix + const_name, new t_const(g_type_i32, (*c_iter)->get_name(), const_val));
596 : }
597 1602 : }
598 : }
599 : }
600 :
601 : EnumDefList:
602 : EnumDefList EnumDef
603 : {
604 3204 : pdebug("EnumDefList -> EnumDefList EnumDef");
605 3204 : $$ = $1;
606 3204 : $$->append($2);
607 : }
608 : |
609 : {
610 396 : pdebug("EnumDefList -> ");
611 396 : $$ = new t_enum(g_program);
612 : }
613 :
614 : EnumDef:
615 : CaptureDocText tok_identifier '=' tok_int_constant CommaOrSemicolonOptional
616 : {
617 420 : pdebug("EnumDef -> tok_identifier = tok_int_constant");
618 420 : if ($4 < 0) {
619 12 : pwarning(1, "Negative value supplied for enum %s.\n", $2);
620 : }
621 420 : if ($4 > INT_MAX) {
622 0 : pwarning(1, "64-bit value supplied for enum %s.\n", $2);
623 : }
624 420 : $$ = new t_enum_value($2, $4);
625 420 : if ($1 != NULL) {
626 0 : $$->set_doc($1);
627 : }
628 : }
629 : |
630 : CaptureDocText tok_identifier CommaOrSemicolonOptional
631 : {
632 2784 : pdebug("EnumDef -> tok_identifier");
633 2784 : $$ = new t_enum_value($2);
634 2784 : if ($1 != NULL) {
635 0 : $$->set_doc($1);
636 : }
637 : }
638 :
639 : Senum:
640 : tok_senum tok_identifier '{' SenumDefList '}'
641 : {
642 0 : pdebug("Senum -> tok_senum tok_identifier { SenumDefList }");
643 0 : $$ = new t_typedef(g_program, $4, $2);
644 : }
645 :
646 : SenumDefList:
647 : SenumDefList SenumDef
648 : {
649 0 : pdebug("SenumDefList -> SenumDefList SenumDef");
650 0 : $$ = $1;
651 0 : $$->add_string_enum_val($2);
652 : }
653 : |
654 : {
655 0 : pdebug("SenumDefList -> ");
656 0 : $$ = new t_base_type("string", t_base_type::TYPE_STRING);
657 0 : $$->set_string_enum(true);
658 : }
659 :
660 : SenumDef:
661 : tok_literal CommaOrSemicolonOptional
662 : {
663 0 : pdebug("SenumDef -> tok_literal");
664 0 : $$ = $1;
665 : }
666 :
667 : Const:
668 : tok_const FieldType tok_identifier '=' ConstValue CommaOrSemicolonOptional
669 : {
670 2544 : pdebug("Const -> tok_const FieldType tok_identifier = ConstValue");
671 2544 : if (g_parse_mode == PROGRAM) {
672 1272 : g_scope->resolve_const_value($5, $2);
673 1272 : $$ = new t_const($2, $3, $5);
674 1272 : validate_const_type($$);
675 :
676 1272 : g_scope->add_constant($3, $$);
677 1272 : if (g_parent_scope != NULL) {
678 48 : g_parent_scope->add_constant(g_parent_prefix + $3, $$);
679 : }
680 : } else {
681 1272 : $$ = NULL;
682 : }
683 : }
684 :
685 : ConstValue:
686 : tok_int_constant
687 : {
688 1008 : pdebug("ConstValue => tok_int_constant");
689 1008 : $$ = new t_const_value();
690 1008 : $$->set_integer($1);
691 1008 : if (!g_allow_64bit_consts && ($1 < INT32_MIN || $1 > INT32_MAX)) {
692 0 : pwarning(1, "64-bit constant \"%" PRIi64 "\" may not work in all languages.\n", $1);
693 : }
694 : }
695 : | tok_dub_constant
696 : {
697 0 : pdebug("ConstValue => tok_dub_constant");
698 0 : $$ = new t_const_value();
699 0 : $$->set_double($1);
700 : }
701 : | tok_literal
702 : {
703 3828 : pdebug("ConstValue => tok_literal");
704 3828 : $$ = new t_const_value($1);
705 : }
706 : | tok_identifier
707 : {
708 7116 : pdebug("ConstValue => tok_identifier");
709 7116 : $$ = new t_const_value();
710 7116 : $$->set_identifier($1);
711 : }
712 : | ConstList
713 : {
714 528 : pdebug("ConstValue => ConstList");
715 528 : $$ = $1;
716 : }
717 : | ConstMap
718 : {
719 456 : pdebug("ConstValue => ConstMap");
720 456 : $$ = $1;
721 : }
722 :
723 : ConstList:
724 : '[' ConstListContents ']'
725 : {
726 528 : pdebug("ConstList => [ ConstListContents ]");
727 528 : $$ = $2;
728 : }
729 :
730 : ConstListContents:
731 : ConstListContents ConstValue CommaOrSemicolonOptional
732 : {
733 1428 : pdebug("ConstListContents => ConstListContents ConstValue CommaOrSemicolonOptional");
734 1428 : $$ = $1;
735 1428 : $$->add_list($2);
736 : }
737 : |
738 : {
739 528 : pdebug("ConstListContents =>");
740 528 : $$ = new t_const_value();
741 528 : $$->set_list();
742 : }
743 :
744 : ConstMap:
745 : '{' ConstMapContents '}'
746 : {
747 456 : pdebug("ConstMap => { ConstMapContents }");
748 456 : $$ = $2;
749 : }
750 :
751 : ConstMapContents:
752 : ConstMapContents ConstValue ':' ConstValue CommaOrSemicolonOptional
753 : {
754 4476 : pdebug("ConstMapContents => ConstMapContents ConstValue CommaOrSemicolonOptional");
755 4476 : $$ = $1;
756 4476 : $$->add_map($2, $4);
757 : }
758 : |
759 : {
760 456 : pdebug("ConstMapContents =>");
761 456 : $$ = new t_const_value();
762 456 : $$->set_map();
763 : }
764 :
765 : StructHead:
766 : tok_struct
767 : {
768 2128 : $$ = struct_is_struct;
769 : }
770 : | tok_union
771 : {
772 12 : $$ = struct_is_union;
773 : }
774 :
775 : Struct:
776 : StructHead tok_identifier XsdAll '{' FieldList '}' TypeAnnotations
777 : {
778 2140 : pdebug("Struct -> tok_struct tok_identifier { FieldList }");
779 2140 : $5->set_xsd_all($3);
780 2140 : $5->set_union($1 == struct_is_union);
781 2140 : $$ = $5;
782 2140 : $$->set_name($2);
783 2140 : if ($7 != NULL) {
784 0 : $$->annotations_ = $7->annotations_;
785 0 : delete $7;
786 : }
787 : }
788 :
789 : XsdAll:
790 : tok_xsd_all
791 : {
792 0 : $$ = true;
793 : }
794 : |
795 : {
796 2140 : $$ = false;
797 : }
798 :
799 : XsdOptional:
800 : tok_xsd_optional
801 : {
802 0 : $$ = true;
803 : }
804 : |
805 : {
806 15252 : $$ = false;
807 : }
808 :
809 : XsdNillable:
810 : tok_xsd_nillable
811 : {
812 0 : $$ = true;
813 : }
814 : |
815 : {
816 15252 : $$ = false;
817 : }
818 :
819 : XsdAttributes:
820 : tok_xsd_attrs '{' FieldList '}'
821 : {
822 0 : $$ = $3;
823 : }
824 : |
825 : {
826 15252 : $$ = NULL;
827 : }
828 :
829 : Xception:
830 : tok_xception tok_identifier '{' FieldList '}'
831 : {
832 0 : pdebug("Xception -> tok_xception tok_identifier { FieldList }");
833 0 : $4->set_name($2);
834 0 : $4->set_xception(true);
835 0 : $$ = $4;
836 : }
837 :
838 : Sandesh:
839 : SandeshType tok_sandesh tok_identifier '{' SFieldList '}' TypeAnnotations
840 : {
841 2160 : pdebug("Sandesh -> tok_sandesh tok_identifier { SFieldList }");
842 2160 : $5->set_name($3);
843 2160 : $5->set_type($1);
844 :
845 2160 : if (($1 != g_type_sandesh_request) &&
846 1608 : ($1 != g_type_sandesh_response) &&
847 1152 : ($1 != g_type_sandesh_object)) {
848 1028 : if ($5->exist_opt_field()) {
849 0 : yyerror("optional field not supported in sandesh");
850 0 : exit(1);
851 : }
852 : }
853 :
854 2160 : if ($1 == g_type_sandesh_response) {
855 456 : $5->append(new t_field(g_type_bool, "more", 0, true));
856 1704 : } else if ($1 == g_type_sandesh_request) {
857 1152 : } else if ($1 == g_type_sandesh_system || $1 == g_type_sandesh_object) {
858 500 : $5->append(new t_field(g_type_string, "file", SHRT_MIN, true));
859 500 : $5->append(new t_field(g_type_i32, "line", SHRT_MIN + 1, true));
860 652 : } else if ($1 == g_type_sandesh_trace || $1 == g_type_sandesh_trace_object) {
861 336 : $5->append(new t_field(g_type_string, "file", SHRT_MIN, true));
862 336 : $5->append(new t_field(g_type_i32, "line", SHRT_MIN + 1, true));
863 : }
864 2160 : $$ = $5;
865 2160 : if ($7 != NULL) {
866 0 : $$->annotations_ = $7->annotations_;
867 0 : delete $7;
868 : }
869 : }
870 :
871 : SandeshType:
872 : tok_system
873 : {
874 376 : $$ = g_type_sandesh_system;
875 : }
876 : |
877 : tok_request
878 : {
879 552 : $$ = g_type_sandesh_request;
880 : }
881 : |
882 : tok_response
883 : {
884 456 : $$ = g_type_sandesh_response;
885 : }
886 : |
887 : tok_trace
888 : {
889 324 : $$ = g_type_sandesh_trace;
890 : }
891 : |
892 : tok_trace_object
893 : {
894 12 : $$ = g_type_sandesh_trace_object;
895 : }
896 : |
897 : tok_buffer
898 : {
899 0 : $$ = g_type_sandesh_buffer;
900 : }
901 : |
902 : tok_uve
903 : {
904 256 : $$ = g_type_sandesh_uve;
905 : }
906 : |
907 : tok_dynamic_uve
908 : {
909 36 : $$ = g_type_sandesh_dynamic_uve;
910 : }
911 : |
912 : tok_object
913 : {
914 124 : $$ = g_type_sandesh_object;
915 : }
916 : |
917 : tok_flow
918 : {
919 0 : $$ = g_type_sandesh_flow;
920 : }
921 : |
922 : tok_alarm
923 : {
924 12 : $$ = g_type_sandesh_alarm;
925 : }
926 : |
927 : tok_session
928 : {
929 12 : $$ = g_type_sandesh_session;
930 : }
931 :
932 : Service:
933 : tok_service tok_identifier Extends '{' FlagArgs FunctionList UnflagArgs '}'
934 : {
935 0 : pdebug("Service -> tok_service tok_identifier { FunctionList }");
936 0 : $$ = $6;
937 0 : $$->set_name($2);
938 0 : $$->set_extends($3);
939 : }
940 :
941 : FlagArgs:
942 : {
943 0 : g_arglist = 1;
944 : }
945 :
946 : UnflagArgs:
947 : {
948 0 : g_arglist = 0;
949 : }
950 :
951 : Extends:
952 : tok_extends tok_identifier
953 : {
954 0 : pdebug("Extends -> tok_extends tok_identifier");
955 0 : $$ = NULL;
956 0 : if (g_parse_mode == PROGRAM) {
957 0 : $$ = g_scope->get_service($2);
958 0 : if ($$ == NULL) {
959 0 : yyerror("Service \"%s\" has not been defined.", $2);
960 0 : exit(1);
961 : }
962 : }
963 : }
964 : |
965 : {
966 0 : $$ = NULL;
967 : }
968 :
969 : FunctionList:
970 : FunctionList Function
971 : {
972 0 : pdebug("FunctionList -> FunctionList Function");
973 0 : $$ = $1;
974 0 : $1->add_function($2);
975 : }
976 : |
977 : {
978 0 : pdebug("FunctionList -> ");
979 0 : $$ = new t_service(g_program);
980 : }
981 :
982 : Function:
983 : CaptureDocText Oneway AbcFunction StaticFunction FunctionType tok_identifier '(' FieldList ')' Throws CommaOrSemicolonOptional
984 : {
985 0 : $8->set_name(std::string($6) + "_args");
986 0 : $$ = new t_function($5, $6, $8, $10, $2, $3, $4);
987 0 : if ($1 != NULL) {
988 0 : $$->set_doc($1);
989 : }
990 : }
991 :
992 : Oneway:
993 : tok_oneway
994 : {
995 0 : $$ = true;
996 : }
997 : |
998 : {
999 0 : $$ = false;
1000 : }
1001 :
1002 : StaticFunction:
1003 : tok_staticfunction
1004 : {
1005 0 : $$ = true;
1006 : }
1007 : |
1008 : {
1009 0 : $$ = false;
1010 : }
1011 :
1012 : AbcFunction:
1013 : tok_abcfunction
1014 : {
1015 0 : $$ = true;
1016 : }
1017 : |
1018 : {
1019 0 : $$ = false;
1020 : }
1021 :
1022 : Throws:
1023 : tok_throws '(' FieldList ')'
1024 : {
1025 0 : pdebug("Throws -> tok_throws ( FieldList )");
1026 0 : $$ = $3;
1027 0 : if (g_parse_mode == PROGRAM && !validate_throws($$)) {
1028 0 : yyerror("Throws clause may not contain non-exception types");
1029 0 : exit(1);
1030 : }
1031 : }
1032 : |
1033 : {
1034 0 : $$ = new t_struct(g_program);
1035 : }
1036 :
1037 : FieldList:
1038 : FieldList Field
1039 : {
1040 11372 : pdebug("FieldList -> FieldList , Field");
1041 11372 : $$ = $1;
1042 11372 : if (!($$->append($2))) {
1043 0 : yyerror("Field identifier %d for \"%s\" has already been used", $2->get_key(), $2->get_name().c_str());
1044 0 : exit(1);
1045 : }
1046 : }
1047 : |
1048 : {
1049 2140 : pdebug("FieldList -> ");
1050 2140 : y_field_val = -1;
1051 2140 : $$ = new t_struct(g_program);
1052 : }
1053 :
1054 : SFieldList:
1055 : SFieldList Field
1056 : {
1057 4228 : pdebug("SFieldList -> SFieldList , Field");
1058 4228 : $$ = $1;
1059 :
1060 4228 : if (!($$->append($2))) {
1061 0 : yyerror("Field identifier %d for \"%s\" has already been used", $2->get_key(), $2->get_name().c_str());
1062 0 : exit(1);
1063 : }
1064 : }
1065 : |
1066 : {
1067 2160 : pdebug("SFieldList -> ");
1068 2160 : y_field_val = -1;
1069 2160 : $$ = new t_sandesh(g_program);
1070 : }
1071 :
1072 : Field:
1073 : CaptureDocText FieldIdentifier FieldRequiredness FieldType tok_identifier FieldValue XsdOptional XsdNillable XsdAttributes TypeAnnotations CommaOrSemicolonOptional
1074 : {
1075 15252 : pdebug("tok_int_constant : Field -> FieldType tok_identifier");
1076 15252 : if ($2.auto_assigned) {
1077 0 : pwarning(1, "No field key specified for %s, resulting protocol may have conflicts or not be backwards compatible!\n", $5);
1078 0 : if (g_strict >= 192) {
1079 0 : yyerror("Implicit field keys are deprecated and not allowed with -strict");
1080 0 : exit(1);
1081 : }
1082 : }
1083 15252 : $$ = new t_field($4, $5, $2.value);
1084 15252 : $$->set_req($3);
1085 15252 : if ($6 != NULL) {
1086 6 : g_scope->resolve_const_value($6, $4);
1087 6 : validate_field_value($$, $6);
1088 6 : $$->set_value($6);
1089 : }
1090 15252 : $$->set_xsd_optional($7);
1091 15252 : $$->set_xsd_nillable($8);
1092 15252 : if ($1 != NULL) {
1093 754 : $$->set_doc($1);
1094 : }
1095 15252 : if ($9 != NULL) {
1096 0 : $$->set_xsd_attrs($9);
1097 : }
1098 15252 : if ($10 != NULL) {
1099 1032 : $$->annotations_ = $10->annotations_;
1100 1032 : delete $10;
1101 : }
1102 : }
1103 : |
1104 : CaptureDocText FieldIdentifier tok_literal CommaOrSemicolonOptional
1105 : {
1106 348 : pdebug("Field -> static string");
1107 348 : if ($2.auto_assigned) {
1108 0 : pwarning(1, "No field key specified for %s, resulting protocol may have conflicts or not be backwards compatible!\n", $3);
1109 0 : if (g_strict >= 192) {
1110 0 : yyerror("Implicit field keys are deprecated and not allowed with -strict");
1111 0 : exit(1);
1112 : }
1113 : }
1114 :
1115 348 : $$ = new t_field(g_type_static_const_string, t_field::auto_string_name($2.value), $2.value);
1116 :
1117 348 : $$->set_req(t_field::T_REQUIRED);
1118 348 : $$->set_value(new t_const_value($3));
1119 348 : if ($1 != NULL) {
1120 0 : $$->set_doc($1);
1121 : }
1122 : }
1123 :
1124 : FieldIdentifier:
1125 : tok_int_constant ':'
1126 : {
1127 15600 : if ($1 <= 0) {
1128 0 : if (g_allow_neg_field_keys) {
1129 : /*
1130 : * g_allow_neg_field_keys exists to allow users to add explicitly
1131 : * specified key values to old .thrift files without breaking
1132 : * protocol compatibility.
1133 : */
1134 0 : if ($1 != y_field_val) {
1135 : /*
1136 : * warn if the user-specified negative value isn't what
1137 : * thrift would have auto-assigned.
1138 : */
1139 0 : pwarning(1, "Negative field key (%d) differs from what would be "
1140 0 : "auto-assigned by thrift (%d).\n", $1, y_field_val);
1141 : }
1142 : /*
1143 : * Leave $1 as-is, and update y_field_val to be one less than $1.
1144 : * The FieldList parsing will catch any duplicate key values.
1145 : */
1146 0 : y_field_val = $1 - 1;
1147 0 : $$.value = $1;
1148 0 : $$.auto_assigned = false;
1149 : } else {
1150 0 : pwarning(1, "Nonpositive value (%d) not allowed as a field key.\n",
1151 0 : $1);
1152 0 : $$.value = y_field_val--;
1153 0 : $$.auto_assigned = true;
1154 : }
1155 : } else {
1156 15600 : $$.value = $1;
1157 15600 : $$.auto_assigned = false;
1158 : }
1159 : }
1160 : |
1161 : {
1162 0 : $$.value = y_field_val--;
1163 0 : $$.auto_assigned = true;
1164 : }
1165 :
1166 : FieldRequiredness:
1167 : tok_required
1168 : {
1169 0 : $$ = t_field::T_REQUIRED;
1170 : }
1171 : | tok_optional
1172 : {
1173 4028 : if (g_arglist) {
1174 0 : if (g_parse_mode == PROGRAM) {
1175 0 : pwarning(1, "optional keyword is ignored in argument lists.\n");
1176 : }
1177 0 : $$ = t_field::T_OPT_IN_REQ_OUT;
1178 : } else {
1179 4028 : $$ = t_field::T_OPTIONAL;
1180 : }
1181 : }
1182 : |
1183 : {
1184 11224 : $$ = t_field::T_OPT_IN_REQ_OUT;
1185 : }
1186 :
1187 : FieldValue:
1188 : '=' ConstValue
1189 : {
1190 12 : if (g_parse_mode == PROGRAM) {
1191 6 : $$ = $2;
1192 : } else {
1193 6 : $$ = NULL;
1194 : }
1195 : }
1196 : |
1197 : {
1198 15240 : $$ = NULL;
1199 : }
1200 :
1201 : FunctionType:
1202 : FieldType
1203 : {
1204 0 : pdebug("FunctionType -> FieldType");
1205 0 : $$ = $1;
1206 : }
1207 : | tok_void
1208 : {
1209 0 : pdebug("FunctionType -> tok_void");
1210 0 : $$ = g_type_void;
1211 : }
1212 :
1213 : FieldType:
1214 : tok_identifier
1215 : {
1216 2360 : pdebug("FieldType -> tok_identifier");
1217 2360 : if (g_parse_mode == INCLUDES) {
1218 : // Ignore identifiers in include mode
1219 1180 : $$ = NULL;
1220 : } else {
1221 : // Lookup the identifier in the current scope
1222 1180 : $$ = g_scope->get_type($1);
1223 1180 : if ($$ == NULL) {
1224 0 : yyerror("Type \"%s\" has not been defined.", $1);
1225 0 : exit(1);
1226 : }
1227 : }
1228 : }
1229 : | BaseType
1230 : {
1231 16412 : pdebug("FieldType -> BaseType");
1232 16412 : $$ = $1;
1233 : }
1234 : | ContainerType
1235 : {
1236 2672 : pdebug("FieldType -> ContainerType");
1237 2672 : $$ = $1;
1238 : }
1239 :
1240 : BaseType: SimpleBaseType TypeAnnotations
1241 : {
1242 16412 : pdebug("BaseType -> SimpleBaseType TypeAnnotations");
1243 16412 : if ($2 != NULL) {
1244 0 : $$ = new t_base_type(*static_cast<t_base_type*>($1));
1245 0 : $$->annotations_ = $2->annotations_;
1246 0 : delete $2;
1247 : } else {
1248 16412 : $$ = $1;
1249 : }
1250 : }
1251 :
1252 : SimpleBaseType:
1253 : tok_string
1254 : {
1255 9936 : pdebug("BaseType -> tok_string");
1256 9936 : $$ = g_type_string;
1257 : }
1258 : | tok_binary
1259 : {
1260 0 : pdebug("BaseType -> tok_binary");
1261 0 : $$ = g_type_binary;
1262 : }
1263 : | tok_slist
1264 : {
1265 0 : pdebug("BaseType -> tok_slist");
1266 0 : $$ = g_type_slist;
1267 : }
1268 : | tok_bool
1269 : {
1270 880 : pdebug("BaseType -> tok_bool");
1271 880 : $$ = g_type_bool;
1272 : }
1273 : | tok_byte
1274 : {
1275 108 : pdebug("BaseType -> tok_byte");
1276 108 : $$ = g_type_byte;
1277 : }
1278 : | tok_i16
1279 : {
1280 48 : pdebug("BaseType -> tok_i16");
1281 48 : $$ = g_type_i16;
1282 : }
1283 : | tok_i32
1284 : {
1285 380 : pdebug("BaseType -> tok_i32");
1286 380 : $$ = g_type_i32;
1287 : }
1288 : | tok_i64
1289 : {
1290 276 : pdebug("BaseType -> tok_i64");
1291 276 : $$ = g_type_i64;
1292 : }
1293 : | tok_double
1294 : {
1295 716 : pdebug("BaseType -> tok_double");
1296 716 : $$ = g_type_double;
1297 : }
1298 : | tok_u16
1299 : {
1300 948 : pdebug("BaseType -> tok_u16");
1301 948 : $$ = g_type_u16;
1302 : }
1303 : | tok_u32
1304 : {
1305 1152 : pdebug("BaseType -> tok_u32");
1306 1152 : $$ = g_type_u32;
1307 : }
1308 : | tok_u64
1309 : {
1310 1632 : pdebug("BaseType -> tok_u64");
1311 1632 : $$ = g_type_u64;
1312 : }
1313 : | tok_ipv4
1314 : {
1315 24 : pdebug("BaseType -> tok_ipv4");
1316 24 : $$ = g_type_ipv4;
1317 : }
1318 : | tok_ipaddr
1319 : {
1320 96 : pdebug("BaseType -> tok_ipaddr");
1321 96 : $$ = g_type_ipaddr;
1322 : }
1323 : | tok_xml
1324 : {
1325 108 : pdebug("BaseType -> tok_xml");
1326 108 : $$ = g_type_xml;
1327 : }
1328 : | tok_uuid_t
1329 : {
1330 108 : pdebug("BaseType -> tok_uuid_t");
1331 108 : $$ = g_type_uuid_t;
1332 : }
1333 :
1334 : ContainerType: SimpleContainerType TypeAnnotations
1335 : {
1336 2672 : pdebug("ContainerType -> SimpleContainerType TypeAnnotations");
1337 2672 : $$ = $1;
1338 2672 : if ($2 != NULL) {
1339 0 : $$->annotations_ = $2->annotations_;
1340 0 : delete $2;
1341 : }
1342 : }
1343 :
1344 : SimpleContainerType:
1345 : MapType
1346 : {
1347 976 : pdebug("SimpleContainerType -> MapType");
1348 976 : $$ = $1;
1349 : }
1350 : | SetType
1351 : {
1352 48 : pdebug("SimpleContainerType -> SetType");
1353 48 : $$ = $1;
1354 : }
1355 : | ListType
1356 : {
1357 1648 : pdebug("SimpleContainerType -> ListType");
1358 1648 : $$ = $1;
1359 : }
1360 :
1361 : MapType:
1362 : tok_map CppType '<' FieldType ',' FieldType '>'
1363 : {
1364 976 : pdebug("MapType -> tok_map <FieldType, FieldType>");
1365 976 : $$ = new t_map($4, $6);
1366 976 : if ($2 != NULL) {
1367 0 : ((t_container*)$$)->set_cpp_name(std::string($2));
1368 : }
1369 : }
1370 :
1371 : SetType:
1372 : tok_set CppType '<' FieldType '>'
1373 : {
1374 48 : pdebug("SetType -> tok_set<FieldType>");
1375 48 : $$ = new t_set($4);
1376 48 : if ($2 != NULL) {
1377 0 : ((t_container*)$$)->set_cpp_name(std::string($2));
1378 : }
1379 : }
1380 :
1381 : ListType:
1382 : tok_list '<' FieldType '>' CppType
1383 : {
1384 1648 : pdebug("ListType -> tok_list<FieldType>");
1385 1648 : $$ = new t_list($3);
1386 1648 : if ($5 != NULL) {
1387 0 : ((t_container*)$$)->set_cpp_name(std::string($5));
1388 : }
1389 : }
1390 :
1391 : CppType:
1392 : tok_cpp_type tok_literal
1393 : {
1394 0 : $$ = $2;
1395 : }
1396 : |
1397 : {
1398 2672 : $$ = NULL;
1399 : }
1400 :
1401 : TypeAnnotations:
1402 : '(' TypeAnnotationList ')'
1403 : {
1404 1032 : pdebug("TypeAnnotations -> ( TypeAnnotationList )");
1405 1032 : $$ = $2;
1406 : }
1407 : |
1408 : {
1409 37604 : $$ = NULL;
1410 : }
1411 :
1412 : TypeAnnotationList:
1413 : TypeAnnotationList TypeAnnotation
1414 : {
1415 1068 : pdebug("TypeAnnotationList -> TypeAnnotationList , TypeAnnotation");
1416 1068 : $$ = $1;
1417 1068 : $$->annotations_[$2->key] = $2->val;
1418 1068 : delete $2;
1419 : }
1420 : |
1421 : {
1422 : /* Just use a dummy structure to hold the annotations. */
1423 1032 : $$ = new t_struct(g_program);
1424 : }
1425 :
1426 : TypeAnnotation:
1427 : tok_identifier '=' tok_literal CommaOrSemicolonOptional
1428 : {
1429 1068 : pdebug("TypeAnnotation -> tok_identifier = tok_literal");
1430 1068 : $$ = new t_annotation;
1431 1068 : $$->key = $1;
1432 1068 : $$->val = $3;
1433 : }
1434 :
1435 : %%
|