1/**
2 * Copyright (c) 2015-present, Facebook, Inc.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8/* %require "3" */
9
10%skeleton "lalr1.cc"
11
12%defines
13%define parser_class_name {GraphQLParserImpl}
14
15%define api.token.prefix {TOK_}
16
17%define parse.error verbose
18
19%code requires
20{
21#include <cstdlib>
22#include <cstring>
23#include <iostream>
24#include <sstream>
25#include <string>
26
27#include "Ast.h"
28
29using facebook::graphql::ast::Node;
30using facebook::graphql::ast::Name;
31using facebook::graphql::ast::Definition;
32using facebook::graphql::ast::Document;
33using facebook::graphql::ast::OperationDefinition;
34using facebook::graphql::ast::VariableDefinition;
35using facebook::graphql::ast::Variable;
36using facebook::graphql::ast::SelectionSet;
37using facebook::graphql::ast::Selection;
38using facebook::graphql::ast::Field;
39using facebook::graphql::ast::Argument;
40using facebook::graphql::ast::FragmentSpread;
41using facebook::graphql::ast::InlineFragment;
42using facebook::graphql::ast::FragmentDefinition;
43using facebook::graphql::ast::Value;
44using facebook::graphql::ast::IntValue;
45using facebook::graphql::ast::FloatValue;
46using facebook::graphql::ast::StringValue;
47using facebook::graphql::ast::BooleanValue;
48using facebook::graphql::ast::NullValue;
49using facebook::graphql::ast::EnumValue;
50using facebook::graphql::ast::ListValue;
51using facebook::graphql::ast::ObjectValue;
52using facebook::graphql::ast::ObjectField;
53using facebook::graphql::ast::Directive;
54using facebook::graphql::ast::Type;
55using facebook::graphql::ast::NamedType;
56using facebook::graphql::ast::ListType;
57using facebook::graphql::ast::NonNullType;
58
59// Experimental schema support.
60using facebook::graphql::ast::SchemaDefinition;
61using facebook::graphql::ast::ScalarTypeDefinition;
62using facebook::graphql::ast::ObjectTypeDefinition;
63using facebook::graphql::ast::InterfaceTypeDefinition;
64using facebook::graphql::ast::UnionTypeDefinition;
65using facebook::graphql::ast::EnumTypeDefinition;
66using facebook::graphql::ast::InputObjectTypeDefinition;
67using facebook::graphql::ast::TypeExtensionDefinition;
68using facebook::graphql::ast::DirectiveDefinition;
69using facebook::graphql::ast::SchemaDefinition;
70using facebook::graphql::ast::OperationTypeDefinition;
71using facebook::graphql::ast::ScalarTypeDefinition;
72using facebook::graphql::ast::ObjectTypeDefinition;
73using facebook::graphql::ast::FieldDefinition;
74using facebook::graphql::ast::InputValueDefinition;
75using facebook::graphql::ast::InterfaceTypeDefinition;
76using facebook::graphql::ast::UnionTypeDefinition;
77using facebook::graphql::ast::EnumTypeDefinition;
78using facebook::graphql::ast::EnumValueDefinition;
79using facebook::graphql::ast::InputObjectTypeDefinition;
80using facebook::graphql::ast::TypeExtensionDefinition;
81using facebook::graphql::ast::DirectiveDefinition;
82
83union yystype {                                         \
84    const char *str;                                    \
85    const char *heapStr;                                \
86    Name *name;                                         \
87    Definition *definition;                             \
88    Document *document;                                 \
89    OperationDefinition *operationDefinition;           \
90    VariableDefinition *variableDefinition;             \
91    Variable *variable;                                 \
92    SelectionSet *selectionSet;                     \
93    Selection *selection;                           \
94    Field *field;                                   \
95    Argument *argument;                             \
96    FragmentSpread *fragmentSpread;                 \
97    InlineFragment *inlineFragment;                 \
98    FragmentDefinition *fragmentDefinition;         \
99    Value *value;                                   \
100    IntValue *intValue;                             \
101    FloatValue *floatValue;                         \
102    StringValue *stringValue;                       \
103    BooleanValue *booleanValue;                     \
104    NullValue *nullValue;                           \
105    EnumValue *enumValue;                           \
106    ListValue *arrayValue;                          \
107    ObjectValue *objectValue;                       \
108    ObjectField *objectField;                       \
109    Directive *directive;                           \
110    Type *type;                                     \
111    NamedType *namedType;                           \
112    ListType *listType;                             \
113    NonNullType *nonNullType;                       \
114    \
115    std::vector<std::unique_ptr<Definition>> *definitionList;       \
116    std::vector<std::unique_ptr<VariableDefinition>> *variableDefinitionList; \
117    std::vector<std::unique_ptr<Selection>> *selectionList;         \
118    std::vector<std::unique_ptr<Field>> *fieldList;                 \
119    std::vector<std::unique_ptr<Argument>> *argumentList;           \
120    std::vector<std::unique_ptr<Value>> *valueList;                 \
121    std::vector<std::unique_ptr<ObjectField>> *objectFieldList;     \
122    std::vector<std::unique_ptr<Directive>> *directiveList;         \
123                                                                    \
124    SchemaDefinition *schemaDefinition;                             \
125    ScalarTypeDefinition *scalarTypeDefinition;                     \
126    ObjectTypeDefinition *objectTypeDefinition;                     \
127    InterfaceTypeDefinition *interfaceTypeDefinition;               \
128    UnionTypeDefinition *unionTypeDefinition;                       \
129    EnumTypeDefinition *enumTypeDefinition;                         \
130    InputObjectTypeDefinition *inputObjectTypeDefinition;           \
131    TypeExtensionDefinition *typeExtensionDefinition;               \
132    DirectiveDefinition *directiveDefinition;                       \
133    OperationTypeDefinition *operationTypeDefinition;               \
134    InputValueDefinition *inputValueDefinition;                     \
135    FieldDefinition *fieldDefinition;                               \
136    EnumValueDefinition *enumValueDefinition;                       \
137    \
138    std::vector<std::unique_ptr<OperationTypeDefinition>> *operationTypeDefinitionList; \
139    std::vector<std::unique_ptr<NamedType>> *typeNameList;          \
140    std::vector<std::unique_ptr<InputValueDefinition>> *inputValueDefinitionList; \
141    std::vector<std::unique_ptr<FieldDefinition>> *fieldDefinitionList; \
142    std::vector<std::unique_ptr<Name>> *nameList;          \
143    std::vector<std::unique_ptr<EnumValueDefinition>> *enumValueDefinitionList; \
144};
145
146#define YYSTYPE union yystype
147#define YYLTYPE yy::location
148
149}
150
151%lex-param { void *scanner }
152%parse-param { bool enableSchema } { Node **outAST } { const char **outError } { void *scanner }
153
154%locations
155
156%code
157{
158#include "lexer.h"
159#include "syntaxdefs.h"
160}
161
162%token EOF 0
163%token <str> DIRECTIVE "directive"
164%token <str> ENUM "enum"
165%token <str> EXTEND "extend"
166%token <str> FALSE "false"
167%token <str> FRAGMENT "fragment"
168%token <str> IMPLEMENTS "implements"
169%token <str> INPUT "input"
170%token <str> INTERFACE "interface"
171%token <str> MUTATION "mutation"
172%token <str> NULL "null"
173%token <str> QUERY "query"
174%token <str> ON "on"
175%token <str> SCALAR "scalar"
176%token <str> SCHEMA "schema"
177%token <str> SUBSCRIPTION "subscription"
178%token <str> TRUE "true"
179%token <str> TYPE "type"
180%token <str> UNION "union"
181%token BANG "!"
182%token LPAREN "("
183%token RPAREN ")"
184%token ELLIPSIS "..."
185%token COLON ":"
186%token EQUAL "="
187%token AT "@"
188%token LBRACKET "["
189%token RBRACKET "]"
190%token LBRACE "{"
191%token PIPE "|"
192%token RBRACE "}"
193
194%token <str> VARIABLE
195%token <str> INTEGER
196%token <str> FLOAT
197%token <str> STRING
198%token <str> IDENTIFIER
199
200%type <variable> variable
201%type <intValue> int_value
202%type <floatValue> float_value
203%type <stringValue> string_value
204
205%type <document> start
206%type <document> document
207%type <name> fragment_name
208%type <name> name
209%type <name> name_opt
210
211%type <definitionList> definition_list
212%type <definition> definition
213%type <definition> schema_gate
214
215%type <operationDefinition> operation_definition
216%type <variableDefinitionList> variable_definitions
217%type <variableDefinitionList> variable_definition_list
218%type <variableDefinition> variable_definition
219%type <value> default_value_opt
220%type <value> default_value
221%type <selectionSet> selection_set
222%type <selectionSet> selection_set_opt
223%type <selectionList> selection_list
224%type <selection> selection
225%type <field> field
226%type <argumentList> arguments_opt
227%type <argumentList> arguments
228%type <argumentList> argument_list
229%type <argument> argument
230
231%type <fragmentSpread> fragment_spread
232%type <inlineFragment> inline_fragment
233%type <fragmentDefinition> fragment_definition
234%type <namedType> type_condition
235
236%type <value> value
237%type <value> value_const
238%type <booleanValue> boolean_value
239%type <nullValue> null_value
240%type <enumValue> enum_value
241%type <arrayValue> list_value
242%type <arrayValue> list_value_const
243%type <valueList> value_list
244%type <valueList> value_const_list
245%type <objectValue> object_value
246%type <objectValue> object_value_const
247%type <objectFieldList> object_field_list
248%type <objectFieldList> object_field_const_list
249%type <objectField> object_field
250%type <objectField> object_field_const
251
252
253%type <directiveList> directives
254%type <directiveList> directives_opt
255%type <directiveList> directive_list
256%type <directive> directive
257
258%type <type> type
259%type <namedType> type_name
260%type <listType> list_type
261%type <nonNullType> non_null_type
262
263%type <heapStr> operation_type
264
265%type <schemaDefinition> schema_definition;
266%type <scalarTypeDefinition> scalar_type_definition;
267%type <objectTypeDefinition> object_type_definition;
268%type <interfaceTypeDefinition> interface_type_definition;
269%type <unionTypeDefinition> union_type_definition;
270%type <enumTypeDefinition> enum_type_definition;
271%type <inputObjectTypeDefinition> input_object_type_definition;
272%type <typeExtensionDefinition> type_extension_definition;
273%type <directiveDefinition> directive_definition;
274%type <operationTypeDefinition> operation_type_definition;
275%type <operationTypeDefinitionList> operation_type_definition_list;
276%type <typeNameList> type_name_list;
277%type <typeNameList> implements_interfaces_opt;
278%type <typeNameList> union_members;
279%type <fieldDefinition> field_definition;
280%type <fieldDefinitionList> field_definition_list;
281%type <inputValueDefinitionList> arguments_definition_opt;
282%type <inputValueDefinitionList> arguments_definition;
283%type <inputValueDefinitionList> input_value_definition_list;
284%type <inputValueDefinition> input_value_definition;
285%type <enumValueDefinition> enum_value_definition;
286%type <nameList> directive_locations;
287%type <enumValueDefinitionList> enum_value_definition_list;
288
289%destructor { } <str>
290%destructor { free((void *)$$); } <heapStr>
291%destructor { } <document>  /* we steal it and put it in outAST, don't free! */
292%destructor { delete $$; } <*>
293
294%printer { yyoutput << $$; } <str>
295
296%%
297
298start:          document  { *outAST = $1; }
299        ;
300
301/* All of the non-identifier tokens are to accommodate various flavors
302   of name that don't include those tokens. */
303fragment_name:  DIRECTIVE { $$ = new Name(@1, strdup($1)); }
304        |       ENUM { $$ = new Name(@1, strdup($1)); }
305        |       EXTEND { $$ = new Name(@1, strdup($1)); }
306        |       FALSE { $$ = new Name(@1, strdup($1)); }
307        |       FRAGMENT { $$ = new Name(@1, strdup($1)); }
308        |       IDENTIFIER { $$ = new Name(@1, strdup($1)); }
309        |       IMPLEMENTS { $$ = new Name(@1, strdup($1)); }
310        |       INPUT { $$ = new Name(@1, strdup($1)); }
311        |       INTERFACE { $$ = new Name(@1, strdup($1)); }
312        |       MUTATION { $$ = new Name(@1, strdup($1)); }
313        |       NULL { $$ = new Name(@1, strdup($1)); }
314        |       QUERY { $$ = new Name(@1, strdup($1)); }
315        |       SCALAR { $$ = new Name(@1, strdup($1)); }
316        |       SCHEMA { $$ = new Name(@1, strdup($1)); }
317        |       SUBSCRIPTION { $$ = new Name(@1, strdup($1)); }
318        |       TRUE { $$ = new Name(@1, strdup($1)); }
319        |       TYPE { $$ = new Name(@1, strdup($1)); }
320        |       UNION { $$ = new Name(@1, strdup($1)); }
321        ;
322
323name: fragment_name
324        |       ON { $$ = new Name(@1, strdup($1)); }
325        ;
326
327name_opt:
328                %empty {$$ = nullptr;}
329        |       name
330        ;
331
332/* 2.2 Document */
333
334document:       definition_list { $$ = new Document(@$, $1); }
335        ;
336
337definition_list:definition { $$ = new std::vector<std::unique_ptr<Definition>>(); $$->emplace_back($1); }
338        |       definition_list definition { $1->emplace_back($2); $$ = $1; }
339        ;
340
341definition:     operation_definition { $$ = static_cast<Definition *>($1); }
342        |       fragment_definition { $$ = static_cast<Definition *>($1); }
343        |       schema_gate {
344            if (!enableSchema) {
345              error(@$, "schema support disabled");
346              // %destructor doesn't work with YYERROR. See
347              // https://www.gnu.org/software/bison/manual/html_node/Destructor-Decl.html
348              delete $$;
349              YYERROR;
350            }
351            $$ = static_cast<Definition *>($1);
352          }
353        ;
354
355schema_gate:    schema_definition { $$ = static_cast<Definition *>($1); }
356        |       scalar_type_definition { $$ = static_cast<Definition *>($1); }
357        |       object_type_definition { $$ = static_cast<Definition *>($1); }
358        |       interface_type_definition { $$ = static_cast<Definition *>($1); }
359        |       union_type_definition { $$ = static_cast<Definition *>($1); }
360        |       enum_type_definition { $$ = static_cast<Definition *>($1); }
361        |       input_object_type_definition { $$ = static_cast<Definition *>($1); }
362        |       type_extension_definition { $$ = static_cast<Definition *>($1); }
363        |       directive_definition { $$ = static_cast<Definition *>($1); }
364        ;
365
366
367/* 2.2.1 Operations */
368operation_definition:
369                selection_set { $$ = new OperationDefinition(@$, strdup("query"), nullptr, nullptr, nullptr, $1); }
370        |       operation_type name_opt selection_set { $$ = new OperationDefinition(@$, $1, $2, nullptr, nullptr, $3); }
371        |       operation_type name_opt variable_definitions selection_set { $$ = new OperationDefinition(@$, $1, $2, $3, nullptr, $4); }
372        |       operation_type name_opt directives selection_set { $$ = new OperationDefinition(@$, $1, $2, nullptr, $3, $4); }
373        |       operation_type name_opt variable_definitions directives selection_set { $$ = new OperationDefinition(@$, $1, $2, $3, $4, $5); }
374        ;
375
376operation_type: QUERY { $$ = strdup($1); }
377        |       MUTATION { $$ = strdup($1); }
378        |       SUBSCRIPTION { $$ = strdup($1); }
379        ;
380
381variable_definitions:
382                "(" variable_definition_list ")" { $$ = $2; }
383        ;
384
385variable_definition_list:
386                variable_definition { $$ = new std::vector<std::unique_ptr<VariableDefinition>>(); $$->emplace_back($1); }
387        |       variable_definition_list variable_definition { $1->emplace_back($2); $$ = $1; }
388        ;
389
390variable:       VARIABLE { $$ = new Variable(@$, new Name(@1, strdup($1))); }
391        ;
392
393variable_definition:
394                variable ":" type default_value_opt { $$ = new VariableDefinition(@$, $1, $3, $4); }
395        ;
396
397default_value_opt:
398                %empty { $$ = nullptr; }
399        |       default_value
400        ;
401
402default_value:  "=" value_const { $$ = $2; }
403        ;
404
405selection_set:
406                  "{" selection_list "}" { $$ = new SelectionSet(@$, $2); }
407        ;
408
409selection_set_opt:
410                %empty { $$ = nullptr; }
411        |       selection_set
412        ;
413selection_list: selection { $$ = new std::vector<std::unique_ptr<Selection>>(); $$->emplace_back($1); }
414        |       selection_list selection { $1->emplace_back($2); $$ = $1; }
415        ;
416
417selection:      field { $$ = static_cast<Selection *>($1); }
418        |       fragment_spread { $$ = static_cast<Selection *>($1); }
419        |       inline_fragment { $$ = static_cast<Selection *>($1); }
420        ;
421
422field:          name arguments_opt directives_opt selection_set_opt { $$ = new Field(@$, nullptr, $1, $2, $3, $4); }
423        |       name ":" name arguments_opt directives_opt selection_set_opt { $$ = new Field(@$, $1, $3, $4, $5, $6); }
424        ;
425
426arguments:      "(" argument_list ")" { $$ = $2; }
427        ;
428
429arguments_opt:  %empty { $$ = nullptr; }
430        |       arguments { $$ = $1; }
431        ;
432
433argument_list:  argument { $$ = new std::vector<std::unique_ptr<Argument>>(); $$->emplace_back($1); }
434        |       argument_list argument { $1->emplace_back($2); $$ = $1; }
435        ;
436
437argument:       name ":" value { $$ = new Argument(@$, $1, $3); }
438        ;
439
440/* 2.2.6 Fragments */
441fragment_spread:
442                "..." fragment_name directives_opt { $$ = new FragmentSpread(@$, $2, $3); }
443        ;
444
445inline_fragment:
446                "..." "on" type_condition directives_opt selection_set { $$ = new InlineFragment(@$, $3, $4, $5); }
447        |       "..." directives_opt selection_set { $$ = new InlineFragment(@$, nullptr, $2, $3); }
448        ;
449
450fragment_definition:
451                "fragment" fragment_name "on" type_condition directives_opt selection_set { $$ = new FragmentDefinition(@$, $2, $4, $5, $6); }
452        ;
453
454type_condition: type_name
455        ;
456
457/* 2.2.7 Input Values */
458value:          variable { $$ = static_cast<Value *>($1); }
459        |       int_value { $$ = static_cast<Value *>($1); }
460        |       float_value { $$ = static_cast<Value *>($1); }
461        |       string_value { $$ = static_cast<Value *>($1); }
462        |       boolean_value { $$ = static_cast<Value *>($1); }
463        |       null_value { $$ = static_cast<Value *>($1); }
464        |       enum_value { $$ = static_cast<Value *>($1); }
465        |       list_value { $$ = static_cast<Value *>($1); }
466        |       object_value { $$ = static_cast<Value *>($1); }
467        ;
468
469int_value:      INTEGER { $$ = new IntValue(@$, strdup($1)); }
470        ;
471
472float_value:    FLOAT { $$ = new FloatValue(@$, strdup($1)); }
473        ;
474
475string_value:   STRING { $$ = new StringValue(@$, strdup($1)); }
476        ;
477
478value_const:    int_value { $$ = static_cast<Value *>($1); }
479        |       float_value { $$ = static_cast<Value *>($1); }
480        |       string_value { $$ = static_cast<Value *>($1); }
481        |       boolean_value { $$ = static_cast<Value *>($1); }
482        |       null_value { $$ = static_cast<Value *>($1); }
483        |       enum_value { $$ = static_cast<Value *>($1); }
484        |       list_value_const { $$ = static_cast<Value *>($1); }
485        |       object_value_const { $$ = static_cast<Value *>($1); }
486        ;
487
488boolean_value:  TRUE { $$ = new BooleanValue(@$, true); }
489        |       FALSE { $$ = new BooleanValue(@$, false); }
490        ;
491
492null_value:     NULL { $$ = new NullValue(@$); }
493        ;
494
495enum_value:     DIRECTIVE { $$ = new EnumValue(@$, strdup($1)); }
496        |       ENUM { $$ = new EnumValue(@$, strdup($1)); }
497        |       EXTEND { $$ = new EnumValue(@$, strdup($1)); }
498        |       FRAGMENT { $$ = new EnumValue(@$, strdup($1)); }
499        |       IDENTIFIER { $$ = new EnumValue(@$, strdup($1)); }
500        |       IMPLEMENTS { $$ = new EnumValue(@$, strdup($1)); }
501        |       INPUT { $$ = new EnumValue(@$, strdup($1)); }
502        |       INTERFACE { $$ = new EnumValue(@$, strdup($1)); }
503        |       MUTATION { $$ = new EnumValue(@$, strdup($1)); }
504        |       ON { $$ = new EnumValue(@$, strdup($1)); }
505        |       QUERY { $$ = new EnumValue(@$, strdup($1)); }
506        |       SCALAR { $$ = new EnumValue(@$, strdup($1)); }
507        |       SCHEMA { $$ = new EnumValue(@$, strdup($1)); }
508        |       SUBSCRIPTION { $$ = new EnumValue(@$, strdup($1)); }
509        |       TYPE { $$ = new EnumValue(@$, strdup($1)); }
510        |       UNION { $$ = new EnumValue(@$, strdup($1)); }
511        ;
512
513/* 2.2.7.6 List Value */
514
515/* REVIEW: the empty case is inefficient; consider implementing
516   ListValue manually. Don't forget to also do list_value_const. */
517list_value:    "[" "]" { $$ = new ListValue(@$, new std::vector<std::unique_ptr<Value>>()); }
518        |       "[" value_list "]" { $$ = new ListValue(@$, $2); }
519        ;
520
521value_list:     value { $$ = new std::vector<std::unique_ptr<Value>>(); $$->emplace_back($1); }
522        |       value_list value { $1->emplace_back($2); $$ = $1; }
523        ;
524
525list_value_const:
526                "[" "]" { $$ = new ListValue(@$, new std::vector<std::unique_ptr<Value>>()); }
527        |       "[" value_const_list "]" { $$ = new ListValue(@$, $2); }
528        ;
529
530value_const_list:
531                value_const { $$ = new std::vector<std::unique_ptr<Value>>(); $$->emplace_back($1); }
532        |       value_const_list value_const { $1->emplace_back($2); $$ = $1; }
533        ;
534
535/* 2.2.7.7 Object Value */
536/* REVIEW: Inefficient, like ListValue. */
537object_value:   "{" "}" { $$ = new ObjectValue(@$, new std::vector<std::unique_ptr<ObjectField>>()); }
538        |       "{" object_field_list "}" { $$ = new ObjectValue(@$, $2); }
539        ;
540
541object_field_list:
542                object_field { $$ = new std::vector<std::unique_ptr<ObjectField>>(); $$->emplace_back($1); }
543        |       object_field_list object_field { $1->emplace_back($2); $$ = $1; }
544        ;
545
546object_field:   name ":" value { $$ = new ObjectField(@$, $1, $3); }
547        ;
548
549object_value_const:
550                "{" "}" { $$ = new ObjectValue(@$, new std::vector<std::unique_ptr<ObjectField>>()); }
551        |       "{" object_field_const_list "}" { $$ = new ObjectValue(@$, $2); }
552        ;
553
554object_field_const_list:
555                object_field_const { $$ = new std::vector<std::unique_ptr<ObjectField>>(); $$->emplace_back($1); }
556        |       object_field_const_list object_field_const { $1->emplace_back($2); $$ = $1; }
557        ;
558
559object_field_const: name ":" value_const { $$ = new ObjectField(@$, $1, $3); }
560        ;
561
562/* 2.2.10 Directives */
563
564directives:     directive_list
565        ;
566
567directives_opt: %empty { $$ = nullptr; }
568        |       directives
569        ;
570
571directive_list: directive { $$ = new std::vector<std::unique_ptr<Directive>>(); $$->emplace_back($1); }
572        |       directive_list directive { $1->emplace_back($2); $$ = $1; }
573        ;
574
575directive:      "@" name arguments_opt { $$ = new Directive(@$, $2, $3); }
576        ;
577
578/* 2.2.9 Types */
579
580type:           type_name { $$ = static_cast<Type *>($1); }
581        |       list_type { $$ = static_cast<Type *>($1); }
582        |       non_null_type { $$ = static_cast<Type *>($1); }
583        ;
584
585type_name:      name { $$ = new NamedType(@$, $1); }
586        ;
587
588list_type:      "[" type "]" { $$ = new ListType(@$, $2); }
589        ;
590
591non_null_type:  type_name "!" { $$ = new NonNullType(@$, $1); }
592        |       list_type "!" { $$ = new NonNullType(@$, $1); }
593        ;
594
595/* Experimental schema parsing support. */
596
597schema_definition: SCHEMA directives_opt "{" operation_type_definition_list "}" { $$ = new SchemaDefinition(@$, $2, $4); }
598                ;
599
600operation_type_definition_list:
601                operation_type_definition { $$ = new std::vector<std::unique_ptr<OperationTypeDefinition>>(); $$->emplace_back($1); }
602        |       operation_type_definition_list operation_type_definition { $1->emplace_back($2); $$ = $1; }
603        ;
604
605operation_type_definition:
606                operation_type ":" type_name { $$ = new OperationTypeDefinition(@$, $1, $3); }
607                ;
608
609scalar_type_definition: SCALAR name directives_opt { $$ = new ScalarTypeDefinition(@$, $2, $3); }
610                ;
611
612object_type_definition: TYPE name implements_interfaces_opt directives_opt "{" field_definition_list "}" { $$ = new ObjectTypeDefinition(@$, $2, $3, $4, $6); }
613                ;
614
615implements_interfaces_opt: %empty { $$ = nullptr; }
616        |       IMPLEMENTS type_name_list { $$ = $2; }
617                ;
618
619type_name_list: type_name { $$ = new std::vector<std::unique_ptr<NamedType>>(); $$->emplace_back($1); }
620        |       type_name_list type_name { $1->emplace_back($2); $$ = $1; }
621                ;
622
623field_definition: name arguments_definition_opt ":" type directives_opt { $$ = new FieldDefinition(@$, $1, $2, $4, $5); }
624                ;
625
626field_definition_list:
627                        field_definition { $$ = new std::vector<std::unique_ptr<FieldDefinition>>(); $$->emplace_back($1); }
628        |       field_definition_list field_definition { $1->emplace_back($2); $$ = $1; }
629        ;
630
631arguments_definition_opt: %empty { $$ = nullptr; }
632        |       arguments_definition { $$ = $1; }
633                ;
634
635arguments_definition: "(" input_value_definition_list ")" { $$ = $2; }
636                ;
637
638input_value_definition_list: input_value_definition { $$ = new std::vector<std::unique_ptr<InputValueDefinition>>(); $$->emplace_back($1); }
639        |       input_value_definition_list input_value_definition { $1->emplace_back($2); $$ = $1; }
640                ;
641
642input_value_definition: name ":" type default_value_opt directives_opt { $$ = new InputValueDefinition(@$, $1, $3, $4, $5); }
643
644interface_type_definition: INTERFACE name directives_opt "{" field_definition_list "}" { $$ = new InterfaceTypeDefinition(@$, $2, $3, $5); }
645                ;
646
647union_type_definition: UNION name directives_opt "=" union_members { $$ = new UnionTypeDefinition(@$, $2, $3, $5); }
648                ;
649
650union_members:  type_name { $$ = new std::vector<std::unique_ptr<NamedType>>();  $$->emplace_back($1); }
651        |       union_members "|" type_name { $1->emplace_back($3); $$ = $1; }
652        ;
653
654enum_type_definition: ENUM name directives_opt "{" enum_value_definition_list "}" { $$ = new EnumTypeDefinition(@$, $2, $3, $5); }
655                ;
656
657enum_value_definition: name directives_opt { $$ = new EnumValueDefinition(@$, $1, $2); }
658                ;
659
660enum_value_definition_list:
661                enum_value_definition { $$ = new std::vector<std::unique_ptr<EnumValueDefinition>>(); $$->emplace_back($1); }
662        |       enum_value_definition_list enum_value_definition { $1->emplace_back($2); $$ = $1; }
663        ;
664
665input_object_type_definition: INPUT name directives_opt "{" input_value_definition_list "}" { $$ = new InputObjectTypeDefinition(@$, $2, $3, $5); }
666                ;
667
668type_extension_definition: EXTEND object_type_definition { $$ = new TypeExtensionDefinition(@$, $2); }
669                ;
670
671directive_definition: DIRECTIVE "@" name arguments_definition_opt ON directive_locations { $$ = new DirectiveDefinition(@$, $3, $4, $6); }
672                ;
673
674directive_locations:
675                name { $$ = new std::vector<std::unique_ptr<Name>>(); $$->emplace_back($1); }
676        |       directive_locations "|" name { $1->emplace_back($3); $$ = $1; }
677        ;
678
679%%
680
681void yy::GraphQLParserImpl::error(const yy::location &loc, const std::string &str) {
682  std::ostringstream out;
683  out << loc << ": " << str;
684  if (outError) {
685    *outError = strdup(out.str().c_str());
686  }
687}
688
689/* Workaround for syntax_error ctor being marked inline, which causes link
690   errors if used from lexer.lpp. */
691yy::GraphQLParserImpl::syntax_error make_error(const yy::location &loc, const std::string &str) {
692  return yy::GraphQLParserImpl::syntax_error(loc, str);
693}
694