tinygql 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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