blob: 404c80b10603895490e991d80ed565c1964c28d8 [file] [log] [blame]
Mark Slee31985722006-05-24 21:45:31 +00001%{
2
3/**
4 * Thrift parser.
5 *
6 * This parser is used on a thrift definition file.
7 *
8 * @author Mark Slee <mcslee@facebook.com>
9 */
10
11#include <stdio.h>
12#include "main.h"
13#include "globals.h"
14#include "parse/t_program.h"
15
Mark Sleef5377b32006-10-10 01:42:59 +000016/**
17 * This global variable is used for automatic numbering of field indices etc.
18 * when parsing the members of a struct. Field values are automatically
19 * assigned starting from -1 and working their way down.
20 */
Mark Slee9cb7c612006-09-01 22:17:45 +000021int y_field_val = -1;
Mark Slee31985722006-05-24 21:45:31 +000022
23%}
24
Mark Sleef5377b32006-10-10 01:42:59 +000025/**
26 * This structure is used by the parser to hold the data types associated with
27 * various parse nodes.
28 */
Mark Slee31985722006-05-24 21:45:31 +000029%union {
30 char* id;
31 int iconst;
Mark Slee52f643d2006-08-09 00:03:43 +000032 bool tbool;
Mark Slee31985722006-05-24 21:45:31 +000033 t_type* ttype;
34 t_typedef* ttypedef;
35 t_enum* tenum;
36 t_struct* tstruct;
37 t_service* tservice;
38 t_function* tfunction;
39 t_field* tfield;
Mark Slee31985722006-05-24 21:45:31 +000040 t_constant* tconstant;
41}
42
Mark Sleef5377b32006-10-10 01:42:59 +000043/**
44 * Strings identifier
45 */
Mark Slee31985722006-05-24 21:45:31 +000046%token<id> tok_identifier
Mark Sleef5377b32006-10-10 01:42:59 +000047
48/**
49 * Integer constant value
50 */
Mark Slee31985722006-05-24 21:45:31 +000051%token<iconst> tok_int_constant
52
Mark Sleef5377b32006-10-10 01:42:59 +000053/**
54 * Namespace keyword
55 */
Mark Slee9cb7c612006-09-01 22:17:45 +000056%token tok_namespace
57
Mark Sleef5377b32006-10-10 01:42:59 +000058/**
59 * Base datatype keywords
60 */
61%token tok_void
Mark Slee78f58e22006-09-02 04:17:07 +000062%token tok_bool
Mark Slee31985722006-05-24 21:45:31 +000063%token tok_byte
64%token tok_string
Mark Slee9cb7c612006-09-01 22:17:45 +000065%token tok_i16
Mark Slee31985722006-05-24 21:45:31 +000066%token tok_i32
Mark Slee31985722006-05-24 21:45:31 +000067%token tok_i64
Mark Slee9cb7c612006-09-01 22:17:45 +000068%token tok_double
Mark Slee31985722006-05-24 21:45:31 +000069
Mark Sleef5377b32006-10-10 01:42:59 +000070/**
71 * Complex type keywords
72 */
Mark Slee31985722006-05-24 21:45:31 +000073%token tok_map
74%token tok_list
75%token tok_set
76
Mark Sleef5377b32006-10-10 01:42:59 +000077/**
78 * Function modifiers
79 */
Mark Slee31985722006-05-24 21:45:31 +000080%token tok_async
81
Mark Sleef5377b32006-10-10 01:42:59 +000082/**
83 * Thrift language keywords
84 */
Mark Slee31985722006-05-24 21:45:31 +000085%token tok_typedef
86%token tok_struct
Mark Slee9cb7c612006-09-01 22:17:45 +000087%token tok_xception
88%token tok_throws
Mark Slee31985722006-05-24 21:45:31 +000089%token tok_service
90%token tok_enum
91
Mark Sleef5377b32006-10-10 01:42:59 +000092/**
93 * Grammar nodes
94 */
95
96%type<id> Namespace
97
Mark Slee31985722006-05-24 21:45:31 +000098%type<ttype> BaseType
Mark Sleee8540632006-05-30 09:24:40 +000099%type<ttype> ContainerType
100%type<ttype> MapType
101%type<ttype> SetType
102%type<ttype> ListType
Mark Slee31985722006-05-24 21:45:31 +0000103
104%type<ttypedef> Typedef
105%type<ttype> DefinitionType
106
107%type<tfield> Field
108%type<ttype> FieldType
Mark Sleee8540632006-05-30 09:24:40 +0000109%type<tstruct> FieldList
Mark Slee31985722006-05-24 21:45:31 +0000110
111%type<tenum> Enum
112%type<tenum> EnumDefList
113%type<tconstant> EnumDef
114
115%type<tstruct> Struct
Mark Slee9cb7c612006-09-01 22:17:45 +0000116%type<tstruct> Xception
Mark Slee31985722006-05-24 21:45:31 +0000117%type<tservice> Service
118
119%type<tfunction> Function
Mark Slee31985722006-05-24 21:45:31 +0000120%type<ttype> FunctionType
121%type<tservice> FunctionList
122
Mark Sleef5377b32006-10-10 01:42:59 +0000123%type<tstruct> ThrowsOptional
Mark Slee52f643d2006-08-09 00:03:43 +0000124%type<tbool> AsyncOptional
125
Mark Slee31985722006-05-24 21:45:31 +0000126%%
127
Mark Sleef5377b32006-10-10 01:42:59 +0000128/**
129 * Thrift Grammar Implementation.
130 *
131 * For the most part this source file works its way top down from what you
132 * might expect to find in a typical .thrift file, i.e. type definitions and
133 * namespaces up top followed by service definitions using those types.
134 */
Mark Slee31985722006-05-24 21:45:31 +0000135
136Program:
137 DefinitionList
138 {
139 pdebug("Program -> DefinitionList");
140 }
141
142DefinitionList:
143 DefinitionList Definition
144 {
145 pdebug("DefinitionList -> DefinitionList Definition");
146 }
147|
148 {
149 pdebug("DefinitionList -> ");
150 }
151
152Definition:
Mark Slee9cb7c612006-09-01 22:17:45 +0000153 Namespace
154 {
155 pdebug("Definition -> Namespace");
156 g_program->set_namespace($1);
157 }
158| Typedef
Mark Slee31985722006-05-24 21:45:31 +0000159 {
160 pdebug("Definition -> Typedef");
161 g_program->add_typedef($1);
162 }
163| Enum
164 {
165 pdebug("Definition -> Enum");
166 g_program->add_enum($1);
167 }
168| Struct
169 {
170 pdebug("Definition -> Struct");
171 g_program->add_struct($1);
172 }
Mark Slee9cb7c612006-09-01 22:17:45 +0000173| Xception
174 {
175 pdebug("Definition -> Xception");
176 g_program->add_xception($1);
177 }
Mark Slee31985722006-05-24 21:45:31 +0000178| Service
179 {
180 pdebug("Definition -> Service");
181 g_program->add_service($1);
Mark Slee9cb7c612006-09-01 22:17:45 +0000182 }
183
184Namespace:
185 tok_namespace tok_identifier
186 {
187 pdebug("Namespace -> tok_namespace tok_identifier");
188 $$ = $2;
189 }
Mark Slee31985722006-05-24 21:45:31 +0000190
191Typedef:
192 tok_typedef DefinitionType tok_identifier
193 {
194 pdebug("TypeDef -> tok_typedef DefinitionType tok_identifier");
Mark Slee31985722006-05-24 21:45:31 +0000195 t_typedef *td = new t_typedef($2, $3);
196 $$ = td;
197 }
198
199Enum:
200 tok_enum tok_identifier '{' EnumDefList '}'
201 {
202 pdebug("Enum -> tok_enum tok_identifier { EnumDefList }");
203 $$ = $4;
204 $$->set_name($2);
205 }
206
207EnumDefList:
208 EnumDefList ',' EnumDef
209 {
210 pdebug("EnumDefList -> EnumDefList EnumDef");
211 $$ = $1;
212 $$->append($3);
213 }
214| EnumDef
215 {
216 pdebug("EnumDefList -> EnumDef");
217 $$ = new t_enum;
218 $$->append($1);
219 }
220|
221 {
222 pdebug("EnumDefList -> ");
223 $$ = new t_enum;
224 }
225
226EnumDef:
227 tok_identifier '=' tok_int_constant
228 {
Mark Sleee8540632006-05-30 09:24:40 +0000229 pdebug("EnumDef => tok_identifier = tok_int_constant");
Mark Slee31985722006-05-24 21:45:31 +0000230 if ($3 < 0) {
231 printf("WARNING (%d): Negative value supplied for enum %s.\n", yylineno, $1);
232 }
Mark Slee31985722006-05-24 21:45:31 +0000233 $$ = new t_constant($1, $3);
234 }
235|
236 tok_identifier
237 {
238 pdebug("EnumDef => tok_identifier");
239 $$ = new t_constant($1);
240 }
241
242Struct:
243 tok_struct tok_identifier '{' FieldList '}'
244 {
245 pdebug("Struct -> tok_struct tok_identifier { FieldList }");
Mark Sleee8540632006-05-30 09:24:40 +0000246 $4->set_name($2);
247 $$ = $4;
Mark Slee9cb7c612006-09-01 22:17:45 +0000248 y_field_val = -1;
249 }
250
251Xception:
252 tok_xception tok_identifier '{' FieldList '}'
253 {
254 pdebug("Xception -> tok_xception tok_identifier { FieldList }");
255 $4->set_name($2);
256 $4->set_xception(true);
257 $$ = $4;
258 y_field_val = -1;
Mark Slee31985722006-05-24 21:45:31 +0000259 }
260
261Service:
262 tok_service tok_identifier '{' FunctionList '}'
263 {
264 pdebug("Service -> tok_service tok_identifier { FunctionList }");
265 $$ = $4;
266 $$->set_name($2);
267 }
268
269FunctionList:
Mark Slee9cb7c612006-09-01 22:17:45 +0000270 FunctionList Function CommaOptional
Mark Slee31985722006-05-24 21:45:31 +0000271 {
272 pdebug("FunctionList -> FunctionList Function");
273 $$ = $1;
274 $1->add_function($2);
275 }
276|
277 {
278 pdebug("FunctionList -> ");
279 $$ = new t_service;
280 }
281
Mark Slee9cb7c612006-09-01 22:17:45 +0000282CommaOptional:
283 ','
284 {}
285|
286 {}
287
Mark Slee31985722006-05-24 21:45:31 +0000288Function:
Mark Slee4e755ca2006-09-12 00:46:08 +0000289 AsyncOptional FunctionType tok_identifier '(' FieldList ')' ThrowsOptional
Mark Slee31985722006-05-24 21:45:31 +0000290 {
Mark Sleeb15a68b2006-06-07 06:46:24 +0000291 $5->set_name(std::string($3) + "_args");
Mark Slee4e755ca2006-09-12 00:46:08 +0000292 $$ = new t_function($2, $3, $5, $7, $1);
Mark Slee9cb7c612006-09-01 22:17:45 +0000293 y_field_val = -1;
Mark Slee31985722006-05-24 21:45:31 +0000294 }
295
Mark Slee52f643d2006-08-09 00:03:43 +0000296AsyncOptional:
297 tok_async
Mark Slee31985722006-05-24 21:45:31 +0000298 {
Mark Slee52f643d2006-08-09 00:03:43 +0000299 $$ = true;
300 }
301|
302 {
303 $$ = false;
Mark Slee31985722006-05-24 21:45:31 +0000304 }
305
Mark Slee9cb7c612006-09-01 22:17:45 +0000306ThrowsOptional:
307 tok_throws '(' FieldList ')'
308 {
309 $$ = $3;
310 }
311|
312 {
313 $$ = new t_struct;
314 }
315
Mark Slee31985722006-05-24 21:45:31 +0000316FieldList:
317 FieldList ',' Field
318 {
319 pdebug("FieldList -> FieldList , Field");
320 $$ = $1;
321 $$->append($3);
322 }
323| Field
324 {
325 pdebug("FieldList -> Field");
Mark Sleee8540632006-05-30 09:24:40 +0000326 $$ = new t_struct;
Mark Slee31985722006-05-24 21:45:31 +0000327 $$->append($1);
328 }
329|
330 {
331 pdebug("FieldList -> ");
Mark Sleee8540632006-05-30 09:24:40 +0000332 $$ = new t_struct;
Mark Slee31985722006-05-24 21:45:31 +0000333 }
334
335Field:
336 FieldType tok_identifier '=' tok_int_constant
337 {
Mark Sleee8540632006-05-30 09:24:40 +0000338 pdebug("Field -> FieldType tok_identifier = tok_int_constant");
Mark Slee9cb7c612006-09-01 22:17:45 +0000339 if ($4 <= 0) {
340 printf("WARNING (%d): Nonpositive value (%d) not allowed as a field key for '%s'.\n", yylineno, $4, $2);
341 $4 = y_field_val--;
Mark Slee31985722006-05-24 21:45:31 +0000342 }
Mark Slee9cb7c612006-09-01 22:17:45 +0000343 $$ = new t_field($1, $2, $4);
Mark Slee31985722006-05-24 21:45:31 +0000344 }
345| FieldType tok_identifier
346 {
Mark Sleee8540632006-05-30 09:24:40 +0000347 pdebug("Field -> FieldType tok_identifier");
Mark Slee9cb7c612006-09-01 22:17:45 +0000348 printf("WARNING (%d): No field key specified for '%s', resulting protocol may have conflicts or not be backwards compatible!\n", yylineno, $2);
349 $$ = new t_field($1, $2, y_field_val--);
Mark Slee31985722006-05-24 21:45:31 +0000350 }
351
352DefinitionType:
353 BaseType
354 {
355 pdebug("DefinitionType -> BaseType");
356 $$ = $1;
357 }
Mark Sleee8540632006-05-30 09:24:40 +0000358| ContainerType
359 {
360 pdebug("DefinitionType -> ContainerType");
361 $$ = $1;
362 }
Mark Slee31985722006-05-24 21:45:31 +0000363
364FunctionType:
365 FieldType
366 {
Mark Sleee8540632006-05-30 09:24:40 +0000367 pdebug("FunctionType -> FieldType");
Mark Slee31985722006-05-24 21:45:31 +0000368 $$ = $1;
369 }
370| tok_void
371 {
Mark Sleee8540632006-05-30 09:24:40 +0000372 pdebug("FunctionType -> tok_void");
Mark Slee31985722006-05-24 21:45:31 +0000373 $$ = g_program->get_void_type();
374 }
375
376FieldType:
377 tok_identifier
378 {
Mark Sleee8540632006-05-30 09:24:40 +0000379 pdebug("FieldType -> tok_identifier");
380 $$ = g_program->get_custom_type($1);
381 if ($$ == NULL) {
382 yyerror("Type \"%s\" has not been defined.", $1);
383 exit(1);
384 }
Mark Slee31985722006-05-24 21:45:31 +0000385 }
386| BaseType
387 {
Mark Sleee8540632006-05-30 09:24:40 +0000388 pdebug("FieldType -> BaseType");
389 $$ = $1;
390 }
391| ContainerType
392 {
393 pdebug("FieldType -> ContainerType");
Mark Slee31985722006-05-24 21:45:31 +0000394 $$ = $1;
395 }
396
397BaseType:
398 tok_string
399 {
400 pdebug("BaseType -> tok_string");
401 $$ = g_program->get_string_type();
402 }
Mark Slee78f58e22006-09-02 04:17:07 +0000403| tok_bool
404 {
405 pdebug("BaseType -> tok_bool");
406 $$ = g_program->get_bool_type();
407 }
Mark Slee31985722006-05-24 21:45:31 +0000408| tok_byte
409 {
410 pdebug("BaseType -> tok_byte");
411 $$ = g_program->get_byte_type();
412 }
Mark Slee9cb7c612006-09-01 22:17:45 +0000413| tok_i16
414 {
415 pdebug("BaseType -> tok_i16");
416 $$ = g_program->get_i16_type();
417 }
Mark Slee31985722006-05-24 21:45:31 +0000418| tok_i32
419 {
420 pdebug("BaseType -> tok_i32");
421 $$ = g_program->get_i32_type();
422 }
Mark Slee31985722006-05-24 21:45:31 +0000423| tok_i64
424 {
425 pdebug("BaseType -> tok_i64");
426 $$ = g_program->get_i64_type();
427 }
Mark Sleec98d0502006-09-06 02:42:25 +0000428| tok_double
429 {
430 pdebug("BaseType -> tok_double");
431 $$ = g_program->get_double_type();
432 }
Mark Slee31985722006-05-24 21:45:31 +0000433
Mark Sleee8540632006-05-30 09:24:40 +0000434ContainerType:
435 MapType
436 {
437 pdebug("ContainerType -> MapType");
438 $$ = $1;
439 }
440| SetType
441 {
442 pdebug("ContainerType -> SetType");
443 $$ = $1;
444 }
445| ListType
446 {
447 pdebug("ContainerType -> ListType");
448 $$ = $1;
449 }
450
451MapType:
452 tok_map '<' FieldType ',' FieldType '>'
453 {
454 pdebug("MapType -> tok_map <FieldType, FieldType>");
455 $$ = new t_map($3, $5);
456 }
457
458SetType:
459 tok_set '<' FieldType '>'
460 {
461 pdebug("SetType -> tok_set<FieldType>");
462 $$ = new t_set($3);
463 }
464
465ListType:
466 tok_list '<' FieldType '>'
467 {
468 pdebug("ListType -> tok_list<FieldType>");
469 $$ = new t_list($3);
470 }
471
Mark Slee31985722006-05-24 21:45:31 +0000472%%