tinygql 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,598 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tinygql/lexer"
4
+ require "tinygql/nodes"
5
+
6
+ module TinyGQL
7
+ class Parser
8
+ class UnexpectedToken < StandardError; end
9
+
10
+ attr_reader :token_name
11
+
12
+ def initialize doc
13
+ @lexer = Lexer.new doc
14
+ @lexer.advance
15
+ @token_name = @lexer.token_name
16
+ end
17
+
18
+ def parse
19
+ document
20
+ end
21
+
22
+ private
23
+
24
+ def document
25
+ Nodes::Document.new definition_list
26
+ end
27
+
28
+ def definition_list
29
+ list = []
30
+ while !@lexer.done?
31
+ list << definition
32
+ end
33
+ list
34
+ end
35
+
36
+ def definition
37
+ case token_name
38
+ when :FRAGMENT, :QUERY, :MUTATION, :SUBSCRIPTION, :LCURLY
39
+ executable_definition
40
+ when :EXTEND
41
+ type_system_extension
42
+ else
43
+ type_system_definition
44
+ end
45
+ end
46
+
47
+ def type_system_extension
48
+ expect_token :EXTEND
49
+ case token_name
50
+ when :TYPE then object_type_extension
51
+ else
52
+ expect_token :FAIL
53
+ end
54
+ end
55
+
56
+ def object_type_extension
57
+ expect_token :TYPE
58
+ name = self.name
59
+ implements_interfaces = if at?(:IMPLEMENTS); self.implements_interfaces; end
60
+ directives = if at?(:DIR_SIGN); self.directives; end
61
+ fields_definition = if at?(:LCURLY); self.fields_definition; end
62
+ Nodes::ObjectTypeExtension.new(name, implements_interfaces, directives, fields_definition)
63
+ end
64
+
65
+ def type_system_definition
66
+ case token_name
67
+ when :SCHEMA then schema_definition
68
+ when :DIRECTIVE then directive_defintion(nil)
69
+ else
70
+ type_definition(nil)
71
+ end
72
+ end
73
+
74
+ def directive_defintion desc
75
+ expect_token :DIRECTIVE
76
+ expect_token :DIR_SIGN
77
+ name = self.name
78
+ arguments_definition = if at?(:LPAREN); self.arguments_definition; end
79
+ expect_token :ON
80
+ directive_locations = self.directive_locations
81
+ Nodes::DirectiveDefinition.new(desc, name, arguments_definition, directive_locations)
82
+ end
83
+
84
+ def directive_locations
85
+ list = [directive_location]
86
+ while at?(:PIPE)
87
+ accept_token
88
+ list << directive_location
89
+ end
90
+ list
91
+ end
92
+
93
+ def directive_location
94
+ case token_name
95
+ when "QUERY", "MUTATION", "SUBSCRIPTION", "FIELD", "FRAGMENT_DEFINITION", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"
96
+ Nodes::ExecutableDirectiveLocation.new(accept_token_value)
97
+ when "SCHEMA",
98
+ "SCALAR",
99
+ "OBJECT",
100
+ "FIELD_DEFINITION",
101
+ "ARGUMENT_DEFINITION",
102
+ "INTERFACE",
103
+ "UNION",
104
+ "ENUM",
105
+ "ENUM_VALUE",
106
+ "INPUT_OBJECT",
107
+ "INPUT_FIELD_DEFINITION"
108
+ Nodes::TypeSystemDirectiveLocation.new(accept_token_value)
109
+ else
110
+ expect_token(:IDENTIFIER); nil # error
111
+ end
112
+ end
113
+
114
+ def type_definition desc
115
+ case token_name
116
+ when :TYPE then object_type_definition(desc)
117
+ when :INTERFACE then interface_type_definition(desc)
118
+ when :UNION then union_type_definition(desc)
119
+ when :SCALAR then scalar_type_definition(desc)
120
+ when :ENUM then enum_type_definition(desc)
121
+ when :INPUT then input_object_type_definition(desc)
122
+ else
123
+ expect_token :FAIL
124
+ end
125
+ end
126
+
127
+ def input_object_type_definition desc
128
+ expect_token :INPUT
129
+ name = self.name
130
+ directives = if at?(:DIR_SIGN); self.directives; end
131
+ input_fields_definition = if at?(:LCURLY); self.input_fields_definition; end
132
+ Nodes::InputObjectTypeDefinition.new(desc, name, directives, input_fields_definition)
133
+ end
134
+
135
+ def input_fields_definition
136
+ expect_token :LCURLY
137
+ list = []
138
+ while !at?(:RCURLY)
139
+ list << input_value_definition
140
+ end
141
+ expect_token :RCURLY
142
+ list
143
+ end
144
+
145
+ def enum_type_definition desc
146
+ expect_token :ENUM
147
+ name = self.name
148
+ directives = if at?(:DIR_SIGN); self.directives; end
149
+ enum_values_definition = if at?(:LCURLY); self.enum_values_definition; end
150
+ Nodes::EnumTypeDefinition.new(desc, name, directives, enum_values_definition)
151
+ end
152
+
153
+ def enum_values_definition
154
+ expect_token :LCURLY
155
+ list = []
156
+ while !at?(:RCURLY)
157
+ list << enum_value_definition
158
+ end
159
+ expect_token :RCURLY
160
+ list
161
+ end
162
+
163
+ def enum_value_definition
164
+ description = if at?(:STRING); accept_token_value; end
165
+ enum_value = self.enum_value
166
+ directives = if at?(:DIR_SIGN); self.directives; end
167
+ Nodes::EnumValueDefinition.new(description, enum_value, directives)
168
+ end
169
+
170
+ def scalar_type_definition desc
171
+ expect_token :SCALAR
172
+ name = self.name
173
+ directives = if at?(:DIR_SIGN); self.directives; end
174
+ Nodes::ScalarTypeDefinition.new(desc, name, directives)
175
+ end
176
+
177
+ def union_type_definition desc
178
+ expect_token :UNION
179
+ name = self.name
180
+ directives = if at?(:DIR_SIGN); self.directives; end
181
+ union_member_types = if at?(:EQUALS); self.union_member_types; end
182
+ Nodes::UnionTypeDefinition.new(desc, name, directives, union_member_types)
183
+ end
184
+
185
+ def union_member_types
186
+ expect_token :EQUALS
187
+ list = [named_type]
188
+ while at?(:PIPE)
189
+ accept_token
190
+ list << named_type
191
+ end
192
+ list
193
+ end
194
+
195
+ def interface_type_definition desc
196
+ expect_token :INTERFACE
197
+ name = self.name
198
+ directives = if at?(:DIR_SIGN); self.directives; end
199
+ fields_definition = if at?(:LCURLY); self.fields_definition; end
200
+ Nodes::InterfaceTypeDefinition.new(desc, name, directives, fields_definition)
201
+ end
202
+
203
+ def object_type_definition desc
204
+ expect_token :TYPE
205
+ name = self.name
206
+ implements_interfaces = if at?(:IMPLEMENTS); self.implements_interfaces; end
207
+ directives = if at?(:DIR_SIGN); self.directives; end
208
+ fields_definition = if at?(:LCURLY); self.fields_definition; end
209
+
210
+ Nodes::ObjectTypeDefinition.new(desc, name, implements_interfaces, directives, fields_definition)
211
+ end
212
+
213
+ def fields_definition
214
+ expect_token :LCURLY
215
+ list = []
216
+ while !at?(:RCURLY)
217
+ list << field_definition
218
+ end
219
+ expect_token :RCURLY
220
+ list
221
+ end
222
+
223
+ def field_definition
224
+ description = if at?(:STRING); accept_token_value; end
225
+ name = self.name
226
+ arguments_definition = if at?(:LPAREN); self.arguments_definition; end
227
+ expect_token :COLON
228
+ type = self.type
229
+ directives = if at?(:DIR_SIGN); self.directives; end
230
+
231
+ Nodes::FieldDefinition.new(description, name, arguments_definition, type, directives)
232
+ end
233
+
234
+ def arguments_definition
235
+ expect_token :LPAREN
236
+ list = []
237
+ while !at?(:RPAREN)
238
+ list << input_value_definition
239
+ end
240
+ expect_token :RPAREN
241
+ list
242
+ end
243
+
244
+ def input_value_definition
245
+ description = if at?(:STRING); accept_token_value; end
246
+ name = self.name
247
+ expect_token :COLON
248
+ type = self.type
249
+ default_value = if at?(:EQUALS); self.default_value; end
250
+ directives = if at?(:DIR_SIGN); self.directives; end
251
+ Nodes::InputValueDefinition.new(description, name, type, default_value, directives)
252
+ end
253
+
254
+ def implements_interfaces
255
+ expect_token :IMPLEMENTS
256
+ list = [self.named_type]
257
+ while at?(:AMP)
258
+ accept_token
259
+ list << self.named_type
260
+ end
261
+ list
262
+ end
263
+
264
+ def schema_definition
265
+ expect_token :SCHEMA
266
+
267
+ directives = if at?(:DIR_SIGN); self.directives; end
268
+ expect_token :LCURLY
269
+ defs = root_operation_type_definition
270
+ expect_token :RCURLY
271
+ Nodes::SchemaDefinition.new(directives, defs)
272
+ end
273
+
274
+ def root_operation_type_definition
275
+ list = []
276
+ while !at?(:RCURLY)
277
+ operation_type = self.operation_type
278
+ expect_token :COLON
279
+ list << Nodes::RootOperationTypeDefinition.new(operation_type, named_type)
280
+ end
281
+ list
282
+ end
283
+
284
+ def executable_definition
285
+ if at?(:FRAGMENT)
286
+ fragment_definition
287
+ else
288
+ operation_definition
289
+ end
290
+ end
291
+
292
+ def fragment_definition
293
+ expect_token :FRAGMENT
294
+ expect_token(:FAIL) if at?(:ON)
295
+ name = self.name
296
+ tc = self.type_condition
297
+ directives = if at?(:DIR_SIGN)
298
+ self.directives
299
+ end
300
+
301
+ Nodes::FragmentDefinition.new(name, tc, directives, selection_set)
302
+ end
303
+
304
+ def operation_definition
305
+ case token_name
306
+ when :QUERY, :MUTATION, :SUBSCRIPTION
307
+ type = self.operation_type
308
+ ident = if at?(:IDENTIFIER); name; end
309
+ variable_definitions = if at?(:LPAREN); self.variable_definitions; end
310
+ directives = if at?(:DIR_SIGN); self.directives; end
311
+ end
312
+
313
+ Nodes::OperationDefinition.new(
314
+ type,
315
+ ident,
316
+ variable_definitions,
317
+ directives,
318
+ selection_set
319
+ )
320
+ end
321
+
322
+ def selection_set
323
+ expect_token(:LCURLY)
324
+ list = []
325
+ while !at?(:RCURLY)
326
+ list << selection
327
+ end
328
+ expect_token(:RCURLY)
329
+ list
330
+ end
331
+
332
+ def selection
333
+ if at?(:ELLIPSIS)
334
+ selection_fragment
335
+ else
336
+ field
337
+ end
338
+ end
339
+
340
+ def selection_fragment
341
+ expect_token :ELLIPSIS
342
+
343
+ case token_name
344
+ when :ON, :DIR_SIGN, :LCURLY then inline_fragment
345
+ when :IDENTIFIER then fragment_spread
346
+ else
347
+ expect_token :FAIL
348
+ end
349
+ end
350
+
351
+ def fragment_spread
352
+ name = self.name
353
+ directives = if at?(:DIR_SIGN)
354
+ self.directives
355
+ end
356
+
357
+ Nodes::FragmentSpread.new(name, directives)
358
+ end
359
+
360
+ def inline_fragment
361
+ type_condition = if at?(:ON)
362
+ self.type_condition
363
+ end
364
+
365
+ directives = if at?(:DIR_SIGN)
366
+ self.directives
367
+ end
368
+
369
+ Nodes::InlineFragment.new(type_condition, directives, selection_set)
370
+ end
371
+
372
+ def type_condition
373
+ expect_token :ON
374
+ Nodes::TypeCondition.new(named_type)
375
+ end
376
+
377
+ def field
378
+ name = self.name
379
+
380
+ aliaz = nil
381
+
382
+ if at?(:COLON)
383
+ expect_token(:COLON)
384
+ aliaz = name
385
+ name = self.name
386
+ end
387
+
388
+ arguments = if at?(:LPAREN); self.arguments; end
389
+ directives = if at?(:DIR_SIGN); self.directives; end
390
+ selection_set = if at?(:LCURLY); self.selection_set; end
391
+
392
+ Nodes::Field.new(aliaz, name, arguments, directives, selection_set)
393
+ end
394
+
395
+ def operation_type
396
+ expect_tokens([:QUERY, :MUTATION, :SUBSCRIPTION])
397
+ end
398
+
399
+ def directives
400
+ list = []
401
+ while at?(:DIR_SIGN)
402
+ list << directive
403
+ end
404
+ list
405
+ end
406
+
407
+ def directive
408
+ expect_token(:DIR_SIGN)
409
+ name = self.name
410
+ arguments = if at?(:LPAREN)
411
+ self.arguments
412
+ end
413
+
414
+ Nodes::Directive.new(name, arguments)
415
+ end
416
+
417
+ def arguments
418
+ expect_token(:LPAREN)
419
+ args = []
420
+ while !at?(:RPAREN)
421
+ args << argument
422
+ end
423
+ expect_token(:RPAREN)
424
+ args
425
+ end
426
+
427
+ def argument
428
+ name = self.name
429
+ expect_token(:COLON)
430
+ Nodes::Argument.new(name, value)
431
+ end
432
+
433
+ def variable_definitions
434
+ expect_token(:LPAREN)
435
+ defs = []
436
+ while !at?(:RPAREN)
437
+ defs << variable_definition
438
+ end
439
+ expect_token(:RPAREN)
440
+ defs
441
+ end
442
+
443
+ def variable_definition
444
+ var = variable
445
+ expect_token(:COLON)
446
+ type = self.type
447
+ default_value = if at?(:EQUALS)
448
+ self.default_value
449
+ end
450
+
451
+ Nodes::VariableDefinition.new(var, type, default_value)
452
+ end
453
+
454
+ def default_value
455
+ expect_token(:EQUALS)
456
+ value
457
+ end
458
+
459
+ def value
460
+ case token_name
461
+ when :INT then int_value
462
+ when :FLOAT then float_value
463
+ when :STRING then string_value
464
+ when :TRUE, :FALSE then boolean_value
465
+ when :NULL then null_value
466
+ when :IDENTIFIER then enum_value
467
+ when :LBRACKET then list_value
468
+ when :LCURLY then object_value
469
+ when :VAR_SIGN then variable
470
+ else
471
+ expect_token :FAIL
472
+ end
473
+ end
474
+
475
+ def object_value
476
+ expect_token(:LCURLY)
477
+ list = []
478
+ while !at?(:RCURLY)
479
+ n = name
480
+ expect_token(:COLON)
481
+ list << Nodes::ObjectField.new(n, value)
482
+ end
483
+ expect_token(:RCURLY)
484
+ Nodes::ObjectValue.new(list)
485
+ end
486
+
487
+ def list_value
488
+ expect_token(:LBRACKET)
489
+ list = []
490
+ while !at?(:RBRACKET)
491
+ list << value
492
+ end
493
+ expect_token(:RBRACKET)
494
+ Nodes::ListValue.new(list)
495
+ end
496
+
497
+ def enum_value
498
+ Nodes::EnumValue.new(expect_token_value(:IDENTIFIER))
499
+ end
500
+
501
+ def float_value
502
+ Nodes::FloatValue.new(expect_token_value(:FLOAT))
503
+ end
504
+
505
+ def int_value
506
+ Nodes::IntValue.new(expect_token_value(:INT))
507
+ end
508
+
509
+ def string_value
510
+ Nodes::StringValue.new(expect_token_value(:STRING))
511
+ end
512
+
513
+ def boolean_value
514
+ Nodes::BooleanValue.new(expect_tokens([:TRUE, :FALSE]))
515
+ end
516
+
517
+ def null_value
518
+ Nodes::NullValue.new(expect_token_value(:NULL))
519
+ end
520
+
521
+ def type
522
+ type = case token_name
523
+ when :IDENTIFIER then named_type
524
+ when :LBRACKET then list_type
525
+ end
526
+
527
+ if at?(:BANG)
528
+ Nodes::NotNullType.new type
529
+ expect_token(:BANG)
530
+ end
531
+ type
532
+ end
533
+
534
+ def list_type
535
+ expect_token(:LBRACKET)
536
+ type = Nodes::ListType.new(self.type)
537
+ expect_token(:RBRACKET)
538
+ type
539
+ end
540
+
541
+ def named_type
542
+ Nodes::NamedType.new(name)
543
+ end
544
+
545
+ def variable
546
+ return unless at?(:VAR_SIGN)
547
+ accept_token
548
+ Nodes::Variable.new name
549
+ end
550
+
551
+ def name
552
+ case token_name
553
+ when :IDENTIFIER, :INPUT, :QUERY, :TYPE then accept_token_value
554
+ else
555
+ expect_token_value(:IDENTIFIER)
556
+ end
557
+ end
558
+
559
+ def accept_token
560
+ @lexer.advance
561
+ @token_name = @lexer.token_name
562
+ end
563
+
564
+ # Only use when we care about the accepted token's value
565
+ def accept_token_value
566
+ token_value = @lexer.token_value
567
+ accept_token
568
+ token_value
569
+ end
570
+
571
+ def expect_token tok
572
+ unless at?(tok)
573
+ raise UnexpectedToken, "Expected token #{tok}, actual: #{token_name} line: #{@lexer.line}"
574
+ end
575
+ accept_token
576
+ end
577
+
578
+ # Only use when we care about the expected token's value
579
+ def expect_token_value tok
580
+ token_value = @lexer.token_value
581
+ expect_token tok
582
+ token_value
583
+ end
584
+
585
+ def expect_tokens toks
586
+ token_value = @lexer.token_value
587
+ unless toks.any? { |tok| at?(tok) }
588
+ raise UnexpectedToken, "Expected token #{tok}, actual: #{token_name}"
589
+ end
590
+ accept_token
591
+ token_value
592
+ end
593
+
594
+ def at? tok
595
+ token_name == tok
596
+ end
597
+ end
598
+ end
@@ -0,0 +1,3 @@
1
+ module TinyGQL
2
+ VERSION = '0.1.0'
3
+ end