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 1552 : pdebug("Program -> Headers DefinitionList");
277 1552 : if((g_program_doctext_candidate != NULL) && (g_program_doctext_status != ALREADY_PROCESSED))
278 : {
279 535 : g_program->set_doc(g_program_doctext_candidate);
280 535 : g_program_doctext_status = ALREADY_PROCESSED;
281 : }
282 1552 : clear_doctext();
283 : }
284 :
285 : CaptureDocText:
286 : {
287 125398 : if (g_parse_mode == PROGRAM) {
288 62699 : $$ = g_doctext;
289 62699 : g_doctext = NULL;
290 : } else {
291 62699 : $$ = NULL;
292 : }
293 : }
294 :
295 : /* TODO(dreiss): Try to DestroyDocText in all sorts or random places. */
296 : DestroyDocText:
297 : {
298 616 : if (g_parse_mode == PROGRAM) {
299 308 : 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 616 : pdebug("HeaderList -> HeaderList Header");
309 : }
310 : |
311 : {
312 1552 : pdebug("HeaderList -> ");
313 : }
314 :
315 : Header:
316 : Include
317 : {
318 428 : pdebug("Header -> Include");
319 : }
320 : | tok_namespace tok_identifier tok_identifier
321 : {
322 188 : pdebug("Header -> tok_namespace tok_identifier tok_identifier");
323 188 : if (g_parse_mode == PROGRAM) {
324 94 : 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 428 : pdebug("Include -> tok_include tok_literal");
454 428 : if (g_parse_mode == INCLUDES) {
455 428 : std::string path = include_file(std::string($2));
456 214 : if (!path.empty()) {
457 214 : g_program->add_include(path, std::string($2));
458 : }
459 214 : }
460 : }
461 :
462 : DefinitionList:
463 : DefinitionList CaptureDocText Definition
464 : {
465 28636 : pdebug("DefinitionList -> DefinitionList Definition");
466 28636 : if ($2 != NULL && $3 != NULL) {
467 5748 : $3->set_doc($2);
468 : }
469 : }
470 : |
471 : {
472 1552 : pdebug("DefinitionList -> ");
473 : }
474 :
475 : Definition:
476 : Const
477 : {
478 6962 : pdebug("Definition -> Const");
479 6962 : if (g_parse_mode == PROGRAM) {
480 3481 : g_program->add_const($1);
481 : }
482 6962 : $$ = $1;
483 : }
484 : | TypeDefinition
485 : {
486 10066 : pdebug("Definition -> TypeDefinition");
487 10066 : if (g_parse_mode == PROGRAM) {
488 5033 : g_scope->add_type($1->get_name(), $1);
489 5033 : if (g_parent_scope != NULL) {
490 2417 : g_parent_scope->add_type(g_parent_prefix + $1->get_name(), $1);
491 : }
492 : }
493 10066 : $$ = $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 11608 : pdebug("Definition -> Sandesh");
510 11608 : if (g_parse_mode == PROGRAM) {
511 5804 : 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 5804 : g_scope->add_sandesh($1->get_name(), $1);
516 5804 : if (g_parent_scope != NULL) {
517 2276 : g_parent_scope->add_sandesh(g_parent_prefix + $1->get_name(), $1);
518 : }
519 5804 : g_program->add_sandesh($1);
520 : }
521 11608 : $$ = $1;
522 : }
523 :
524 :
525 : TypeDefinition:
526 : Typedef
527 : {
528 8 : pdebug("TypeDefinition -> Typedef");
529 8 : if (g_parse_mode == PROGRAM) {
530 4 : g_program->add_typedef($1);
531 : }
532 : }
533 : | Enum
534 : {
535 1010 : pdebug("TypeDefinition -> Enum");
536 1010 : if (g_parse_mode == PROGRAM) {
537 505 : 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 9048 : pdebug("TypeDefinition -> Struct");
550 9048 : if (g_parse_mode == PROGRAM) {
551 4524 : 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 8 : pdebug("TypeDef -> tok_typedef FieldType tok_identifier");
566 8 : t_typedef *td = new t_typedef(g_program, $2, $3);
567 8 : $$ = td;
568 : }
569 :
570 : CommaOrSemicolonOptional:
571 : ','
572 : {}
573 : | ';'
574 : {}
575 : |
576 : {}
577 :
578 : Enum:
579 : tok_enum tok_identifier '{' EnumDefList '}'
580 : {
581 1010 : pdebug("Enum -> tok_enum tok_identifier { EnumDefList }");
582 1010 : $$ = $4;
583 1010 : $$->set_name($2);
584 1010 : $$->resolve_values();
585 : // make constants for all the enum values
586 1010 : if (g_parse_mode == PROGRAM) {
587 505 : const std::vector<t_enum_value*>& enum_values = $$->get_constants();
588 505 : std::vector<t_enum_value*>::const_iterator c_iter;
589 4526 : for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) {
590 4021 : std::string const_name = $$->get_name() + "." + (*c_iter)->get_name();
591 4021 : t_const_value* const_val = new t_const_value((*c_iter)->get_value());
592 4021 : const_val->set_enum($$);
593 4021 : g_scope->add_constant(const_name, new t_const(g_type_i32, (*c_iter)->get_name(), const_val));
594 4021 : if (g_parent_scope != NULL) {
595 948 : g_parent_scope->add_constant(g_parent_prefix + const_name, new t_const(g_type_i32, (*c_iter)->get_name(), const_val));
596 : }
597 4021 : }
598 : }
599 : }
600 :
601 : EnumDefList:
602 : EnumDefList EnumDef
603 : {
604 8042 : pdebug("EnumDefList -> EnumDefList EnumDef");
605 8042 : $$ = $1;
606 8042 : $$->append($2);
607 : }
608 : |
609 : {
610 1010 : pdebug("EnumDefList -> ");
611 1010 : $$ = new t_enum(g_program);
612 : }
613 :
614 : EnumDef:
615 : CaptureDocText tok_identifier '=' tok_int_constant CommaOrSemicolonOptional
616 : {
617 1524 : pdebug("EnumDef -> tok_identifier = tok_int_constant");
618 1524 : if ($4 < 0) {
619 26 : pwarning(1, "Negative value supplied for enum %s.\n", $2);
620 : }
621 1524 : if ($4 > INT_MAX) {
622 0 : pwarning(1, "64-bit value supplied for enum %s.\n", $2);
623 : }
624 1524 : $$ = new t_enum_value($2, $4);
625 1524 : if ($1 != NULL) {
626 0 : $$->set_doc($1);
627 : }
628 : }
629 : |
630 : CaptureDocText tok_identifier CommaOrSemicolonOptional
631 : {
632 6518 : pdebug("EnumDef -> tok_identifier");
633 6518 : $$ = new t_enum_value($2);
634 6518 : 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 6962 : pdebug("Const -> tok_const FieldType tok_identifier = ConstValue");
671 6962 : if (g_parse_mode == PROGRAM) {
672 3481 : g_scope->resolve_const_value($5, $2);
673 3481 : $$ = new t_const($2, $3, $5);
674 3481 : validate_const_type($$);
675 :
676 3481 : g_scope->add_constant($3, $$);
677 3481 : if (g_parent_scope != NULL) {
678 188 : g_parent_scope->add_constant(g_parent_prefix + $3, $$);
679 : }
680 : } else {
681 3481 : $$ = NULL;
682 : }
683 : }
684 :
685 : ConstValue:
686 : tok_int_constant
687 : {
688 11390 : pdebug("ConstValue => tok_int_constant");
689 11390 : $$ = new t_const_value();
690 11390 : $$->set_integer($1);
691 11390 : 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 64328 : pdebug("ConstValue => tok_literal");
704 64328 : $$ = new t_const_value($1);
705 : }
706 : | tok_identifier
707 : {
708 18184 : pdebug("ConstValue => tok_identifier");
709 18184 : $$ = new t_const_value();
710 18184 : $$->set_identifier($1);
711 : }
712 : | ConstList
713 : {
714 1928 : pdebug("ConstValue => ConstList");
715 1928 : $$ = $1;
716 : }
717 : | ConstMap
718 : {
719 10950 : pdebug("ConstValue => ConstMap");
720 10950 : $$ = $1;
721 : }
722 :
723 : ConstList:
724 : '[' ConstListContents ']'
725 : {
726 1928 : pdebug("ConstList => [ ConstListContents ]");
727 1928 : $$ = $2;
728 : }
729 :
730 : ConstListContents:
731 : ConstListContents ConstValue CommaOrSemicolonOptional
732 : {
733 13354 : pdebug("ConstListContents => ConstListContents ConstValue CommaOrSemicolonOptional");
734 13354 : $$ = $1;
735 13354 : $$->add_list($2);
736 : }
737 : |
738 : {
739 1928 : pdebug("ConstListContents =>");
740 1928 : $$ = new t_const_value();
741 1928 : $$->set_list();
742 : }
743 :
744 : ConstMap:
745 : '{' ConstMapContents '}'
746 : {
747 10950 : pdebug("ConstMap => { ConstMapContents }");
748 10950 : $$ = $2;
749 : }
750 :
751 : ConstMapContents:
752 : ConstMapContents ConstValue ':' ConstValue CommaOrSemicolonOptional
753 : {
754 43064 : pdebug("ConstMapContents => ConstMapContents ConstValue CommaOrSemicolonOptional");
755 43064 : $$ = $1;
756 43064 : $$->add_map($2, $4);
757 : }
758 : |
759 : {
760 10950 : pdebug("ConstMapContents =>");
761 10950 : $$ = new t_const_value();
762 10950 : $$->set_map();
763 : }
764 :
765 : StructHead:
766 : tok_struct
767 : {
768 9014 : $$ = struct_is_struct;
769 : }
770 : | tok_union
771 : {
772 34 : $$ = struct_is_union;
773 : }
774 :
775 : Struct:
776 : StructHead tok_identifier XsdAll '{' FieldList '}' TypeAnnotations
777 : {
778 9048 : pdebug("Struct -> tok_struct tok_identifier { FieldList }");
779 9048 : $5->set_xsd_all($3);
780 9048 : $5->set_union($1 == struct_is_union);
781 9048 : $$ = $5;
782 9048 : $$->set_name($2);
783 9048 : if ($7 != NULL) {
784 28 : $$->annotations_ = $7->annotations_;
785 28 : delete $7;
786 : }
787 : }
788 :
789 : XsdAll:
790 : tok_xsd_all
791 : {
792 0 : $$ = true;
793 : }
794 : |
795 : {
796 9048 : $$ = false;
797 : }
798 :
799 : XsdOptional:
800 : tok_xsd_optional
801 : {
802 0 : $$ = true;
803 : }
804 : |
805 : {
806 84394 : $$ = false;
807 : }
808 :
809 : XsdNillable:
810 : tok_xsd_nillable
811 : {
812 0 : $$ = true;
813 : }
814 : |
815 : {
816 84394 : $$ = false;
817 : }
818 :
819 : XsdAttributes:
820 : tok_xsd_attrs '{' FieldList '}'
821 : {
822 0 : $$ = $3;
823 : }
824 : |
825 : {
826 84394 : $$ = 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 11608 : pdebug("Sandesh -> tok_sandesh tok_identifier { SFieldList }");
842 11608 : $5->set_name($3);
843 11608 : $5->set_type($1);
844 :
845 11608 : if (($1 != g_type_sandesh_request) &&
846 8380 : ($1 != g_type_sandesh_response) &&
847 5728 : ($1 != g_type_sandesh_object)) {
848 5408 : if ($5->exist_opt_field()) {
849 0 : yyerror("optional field not supported in sandesh");
850 0 : exit(1);
851 : }
852 : }
853 :
854 11608 : if ($1 == g_type_sandesh_response) {
855 2652 : $5->append(new t_field(g_type_bool, "more", 0, true));
856 8956 : } else if ($1 == g_type_sandesh_request) {
857 5728 : } else if ($1 == g_type_sandesh_system || $1 == g_type_sandesh_object) {
858 2170 : $5->append(new t_field(g_type_string, "file", SHRT_MIN, true));
859 2170 : $5->append(new t_field(g_type_i32, "line", SHRT_MIN + 1, true));
860 3558 : } else if ($1 == g_type_sandesh_trace || $1 == g_type_sandesh_trace_object) {
861 2594 : $5->append(new t_field(g_type_string, "file", SHRT_MIN, true));
862 2594 : $5->append(new t_field(g_type_i32, "line", SHRT_MIN + 1, true));
863 : }
864 11608 : $$ = $5;
865 11608 : if ($7 != NULL) {
866 0 : $$->annotations_ = $7->annotations_;
867 0 : delete $7;
868 : }
869 : }
870 :
871 : SandeshType:
872 : tok_system
873 : {
874 1850 : $$ = g_type_sandesh_system;
875 : }
876 : |
877 : tok_request
878 : {
879 3228 : $$ = g_type_sandesh_request;
880 : }
881 : |
882 : tok_response
883 : {
884 2652 : $$ = g_type_sandesh_response;
885 : }
886 : |
887 : tok_trace
888 : {
889 2118 : $$ = g_type_sandesh_trace;
890 : }
891 : |
892 : tok_trace_object
893 : {
894 476 : $$ = g_type_sandesh_trace_object;
895 : }
896 : |
897 : tok_buffer
898 : {
899 248 : $$ = g_type_sandesh_buffer;
900 : }
901 : |
902 : tok_uve
903 : {
904 612 : $$ = g_type_sandesh_uve;
905 : }
906 : |
907 : tok_dynamic_uve
908 : {
909 44 : $$ = g_type_sandesh_dynamic_uve;
910 : }
911 : |
912 : tok_object
913 : {
914 320 : $$ = g_type_sandesh_object;
915 : }
916 : |
917 : tok_flow
918 : {
919 0 : $$ = g_type_sandesh_flow;
920 : }
921 : |
922 : tok_alarm
923 : {
924 34 : $$ = g_type_sandesh_alarm;
925 : }
926 : |
927 : tok_session
928 : {
929 26 : $$ = 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 55414 : pdebug("FieldList -> FieldList , Field");
1041 55414 : $$ = $1;
1042 55414 : 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 9048 : pdebug("FieldList -> ");
1050 9048 : y_field_val = -1;
1051 9048 : $$ = new t_struct(g_program);
1052 : }
1053 :
1054 : SFieldList:
1055 : SFieldList Field
1056 : {
1057 33306 : pdebug("SFieldList -> SFieldList , Field");
1058 33306 : $$ = $1;
1059 :
1060 33306 : 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 11608 : pdebug("SFieldList -> ");
1068 11608 : y_field_val = -1;
1069 11608 : $$ = new t_sandesh(g_program);
1070 : }
1071 :
1072 : Field:
1073 : CaptureDocText FieldIdentifier FieldRequiredness FieldType tok_identifier FieldValue XsdOptional XsdNillable XsdAttributes TypeAnnotations CommaOrSemicolonOptional
1074 : {
1075 84394 : pdebug("tok_int_constant : Field -> FieldType tok_identifier");
1076 84394 : 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 84394 : $$ = new t_field($4, $5, $2.value);
1084 84394 : $$->set_req($3);
1085 84394 : if ($6 != NULL) {
1086 168 : g_scope->resolve_const_value($6, $4);
1087 168 : validate_field_value($$, $6);
1088 168 : $$->set_value($6);
1089 : }
1090 84394 : $$->set_xsd_optional($7);
1091 84394 : $$->set_xsd_nillable($8);
1092 84394 : if ($1 != NULL) {
1093 11323 : $$->set_doc($1);
1094 : }
1095 84394 : if ($9 != NULL) {
1096 0 : $$->set_xsd_attrs($9);
1097 : }
1098 84394 : if ($10 != NULL) {
1099 6022 : $$->annotations_ = $10->annotations_;
1100 6022 : delete $10;
1101 : }
1102 : }
1103 : |
1104 : CaptureDocText FieldIdentifier tok_literal CommaOrSemicolonOptional
1105 : {
1106 4326 : pdebug("Field -> static string");
1107 4326 : 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 4326 : $$ = new t_field(g_type_static_const_string, t_field::auto_string_name($2.value), $2.value);
1116 :
1117 4326 : $$->set_req(t_field::T_REQUIRED);
1118 4326 : $$->set_value(new t_const_value($3));
1119 4326 : if ($1 != NULL) {
1120 3 : $$->set_doc($1);
1121 : }
1122 : }
1123 :
1124 : FieldIdentifier:
1125 : tok_int_constant ':'
1126 : {
1127 88720 : 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 88720 : $$.value = $1;
1157 88720 : $$.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 17788 : 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 17788 : $$ = t_field::T_OPTIONAL;
1180 : }
1181 : }
1182 : |
1183 : {
1184 66606 : $$ = t_field::T_OPT_IN_REQ_OUT;
1185 : }
1186 :
1187 : FieldValue:
1188 : '=' ConstValue
1189 : {
1190 336 : if (g_parse_mode == PROGRAM) {
1191 168 : $$ = $2;
1192 : } else {
1193 168 : $$ = NULL;
1194 : }
1195 : }
1196 : |
1197 : {
1198 84058 : $$ = 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 11238 : pdebug("FieldType -> tok_identifier");
1217 11238 : if (g_parse_mode == INCLUDES) {
1218 : // Ignore identifiers in include mode
1219 5619 : $$ = NULL;
1220 : } else {
1221 : // Lookup the identifier in the current scope
1222 5619 : $$ = g_scope->get_type($1);
1223 5619 : if ($$ == NULL) {
1224 0 : yyerror("Type \"%s\" has not been defined.", $1);
1225 0 : exit(1);
1226 : }
1227 : }
1228 : }
1229 : | BaseType
1230 : {
1231 82530 : pdebug("FieldType -> BaseType");
1232 82530 : $$ = $1;
1233 : }
1234 : | ContainerType
1235 : {
1236 11038 : pdebug("FieldType -> ContainerType");
1237 11038 : $$ = $1;
1238 : }
1239 :
1240 : BaseType: SimpleBaseType TypeAnnotations
1241 : {
1242 82530 : pdebug("BaseType -> SimpleBaseType TypeAnnotations");
1243 82530 : 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 82530 : $$ = $1;
1249 : }
1250 : }
1251 :
1252 : SimpleBaseType:
1253 : tok_string
1254 : {
1255 45624 : pdebug("BaseType -> tok_string");
1256 45624 : $$ = 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 4694 : pdebug("BaseType -> tok_bool");
1271 4694 : $$ = g_type_bool;
1272 : }
1273 : | tok_byte
1274 : {
1275 952 : pdebug("BaseType -> tok_byte");
1276 952 : $$ = g_type_byte;
1277 : }
1278 : | tok_i16
1279 : {
1280 1132 : pdebug("BaseType -> tok_i16");
1281 1132 : $$ = g_type_i16;
1282 : }
1283 : | tok_i32
1284 : {
1285 5076 : pdebug("BaseType -> tok_i32");
1286 5076 : $$ = g_type_i32;
1287 : }
1288 : | tok_i64
1289 : {
1290 2898 : pdebug("BaseType -> tok_i64");
1291 2898 : $$ = g_type_i64;
1292 : }
1293 : | tok_double
1294 : {
1295 1820 : pdebug("BaseType -> tok_double");
1296 1820 : $$ = g_type_double;
1297 : }
1298 : | tok_u16
1299 : {
1300 2638 : pdebug("BaseType -> tok_u16");
1301 2638 : $$ = g_type_u16;
1302 : }
1303 : | tok_u32
1304 : {
1305 6346 : pdebug("BaseType -> tok_u32");
1306 6346 : $$ = g_type_u32;
1307 : }
1308 : | tok_u64
1309 : {
1310 10730 : pdebug("BaseType -> tok_u64");
1311 10730 : $$ = g_type_u64;
1312 : }
1313 : | tok_ipv4
1314 : {
1315 52 : pdebug("BaseType -> tok_ipv4");
1316 52 : $$ = g_type_ipv4;
1317 : }
1318 : | tok_ipaddr
1319 : {
1320 196 : pdebug("BaseType -> tok_ipaddr");
1321 196 : $$ = g_type_ipaddr;
1322 : }
1323 : | tok_xml
1324 : {
1325 166 : pdebug("BaseType -> tok_xml");
1326 166 : $$ = g_type_xml;
1327 : }
1328 : | tok_uuid_t
1329 : {
1330 206 : pdebug("BaseType -> tok_uuid_t");
1331 206 : $$ = g_type_uuid_t;
1332 : }
1333 :
1334 : ContainerType: SimpleContainerType TypeAnnotations
1335 : {
1336 11038 : pdebug("ContainerType -> SimpleContainerType TypeAnnotations");
1337 11038 : $$ = $1;
1338 11038 : if ($2 != NULL) {
1339 0 : $$->annotations_ = $2->annotations_;
1340 0 : delete $2;
1341 : }
1342 : }
1343 :
1344 : SimpleContainerType:
1345 : MapType
1346 : {
1347 2404 : pdebug("SimpleContainerType -> MapType");
1348 2404 : $$ = $1;
1349 : }
1350 : | SetType
1351 : {
1352 110 : pdebug("SimpleContainerType -> SetType");
1353 110 : $$ = $1;
1354 : }
1355 : | ListType
1356 : {
1357 8524 : pdebug("SimpleContainerType -> ListType");
1358 8524 : $$ = $1;
1359 : }
1360 :
1361 : MapType:
1362 : tok_map CppType '<' FieldType ',' FieldType '>'
1363 : {
1364 2404 : pdebug("MapType -> tok_map <FieldType, FieldType>");
1365 2404 : $$ = new t_map($4, $6);
1366 2404 : 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 110 : pdebug("SetType -> tok_set<FieldType>");
1375 110 : $$ = new t_set($4);
1376 110 : 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 8524 : pdebug("ListType -> tok_list<FieldType>");
1385 8524 : $$ = new t_list($3);
1386 8524 : 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 11038 : $$ = NULL;
1399 : }
1400 :
1401 : TypeAnnotations:
1402 : '(' TypeAnnotationList ')'
1403 : {
1404 6050 : pdebug("TypeAnnotations -> ( TypeAnnotationList )");
1405 6050 : $$ = $2;
1406 : }
1407 : |
1408 : {
1409 192568 : $$ = NULL;
1410 : }
1411 :
1412 : TypeAnnotationList:
1413 : TypeAnnotationList TypeAnnotation
1414 : {
1415 7398 : pdebug("TypeAnnotationList -> TypeAnnotationList , TypeAnnotation");
1416 7398 : $$ = $1;
1417 7398 : $$->annotations_[$2->key] = $2->val;
1418 7398 : delete $2;
1419 : }
1420 : |
1421 : {
1422 : /* Just use a dummy structure to hold the annotations. */
1423 6050 : $$ = new t_struct(g_program);
1424 : }
1425 :
1426 : TypeAnnotation:
1427 : tok_identifier '=' tok_literal CommaOrSemicolonOptional
1428 : {
1429 7398 : pdebug("TypeAnnotation -> tok_identifier = tok_literal");
1430 7398 : $$ = new t_annotation;
1431 7398 : $$->key = $1;
1432 7398 : $$->val = $3;
1433 : }
1434 :
1435 : %%
|