Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

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