tinygql 0.1.4 → 0.3.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.
- checksums.yaml +4 -4
- data/README.md +23 -0
- data/bin/bench.rb +38 -0
- data/bin/make_hash.rb +51 -0
- data/lib/tinygql/lexer.rb +115 -42
- data/lib/tinygql/nodes.rb +130 -81
- data/lib/tinygql/nodes.rb.erb +15 -2
- data/lib/tinygql/parser.rb +119 -65
- data/lib/tinygql/version.rb +1 -1
- data/test/lexer_test.rb +101 -0
- data/test/parser_test.rb +17 -0
- metadata +3 -2
data/lib/tinygql/parser.rb
CHANGED
@@ -13,8 +13,7 @@ module TinyGQL
|
|
13
13
|
|
14
14
|
def initialize doc
|
15
15
|
@lexer = Lexer.new doc
|
16
|
-
|
17
|
-
@token_name = @lexer.token_name
|
16
|
+
accept_token
|
18
17
|
end
|
19
18
|
|
20
19
|
def parse
|
@@ -25,8 +24,13 @@ module TinyGQL
|
|
25
24
|
|
26
25
|
attr_reader :token_name
|
27
26
|
|
27
|
+
def pos
|
28
|
+
@lexer.start
|
29
|
+
end
|
30
|
+
|
28
31
|
def document
|
29
|
-
|
32
|
+
loc = pos
|
33
|
+
Nodes::Document.new loc, definition_list
|
30
34
|
end
|
31
35
|
|
32
36
|
def definition_list
|
@@ -65,52 +69,58 @@ module TinyGQL
|
|
65
69
|
end
|
66
70
|
|
67
71
|
def input_object_type_extension
|
72
|
+
loc = pos
|
68
73
|
expect_token :INPUT
|
69
74
|
name = self.name
|
70
75
|
directives = if at?(:DIR_SIGN); self.directives; end
|
71
76
|
input_fields_definition = if at?(:LCURLY); self.input_fields_definition; end
|
72
|
-
Nodes::InputObjectTypeExtension.new(name, directives, input_fields_definition)
|
77
|
+
Nodes::InputObjectTypeExtension.new(loc, name, directives, input_fields_definition)
|
73
78
|
end
|
74
79
|
|
75
80
|
def enum_type_extension
|
81
|
+
loc = pos
|
76
82
|
expect_token :ENUM
|
77
83
|
name = self.name
|
78
84
|
directives = if at?(:DIR_SIGN); self.directives; end
|
79
85
|
enum_values_definition = if at?(:LCURLY); self.enum_values_definition; end
|
80
|
-
Nodes::EnumTypeExtension.new(name, directives, enum_values_definition)
|
86
|
+
Nodes::EnumTypeExtension.new(loc, name, directives, enum_values_definition)
|
81
87
|
end
|
82
88
|
|
83
89
|
def union_type_extension
|
90
|
+
loc = pos
|
84
91
|
expect_token :UNION
|
85
92
|
name = self.name
|
86
93
|
directives = if at?(:DIR_SIGN); self.directives; end
|
87
94
|
union_member_types = if at?(:EQUALS); self.union_member_types; end
|
88
|
-
Nodes::UnionTypeExtension.new(name, directives, union_member_types)
|
95
|
+
Nodes::UnionTypeExtension.new(loc, name, directives, union_member_types)
|
89
96
|
end
|
90
97
|
|
91
98
|
def interface_type_extension
|
99
|
+
loc = pos
|
92
100
|
expect_token :INTERFACE
|
93
101
|
name = self.name
|
94
102
|
implements_interfaces = if at?(:IMPLEMENTS); self.implements_interfaces; end
|
95
103
|
directives = if at?(:DIR_SIGN); self.directives; end
|
96
104
|
fields_definition = if at?(:LCURLY); self.fields_definition; end
|
97
|
-
Nodes::InterfaceTypeExtension.new(name, implements_interfaces, directives, fields_definition)
|
105
|
+
Nodes::InterfaceTypeExtension.new(loc, name, implements_interfaces, directives, fields_definition)
|
98
106
|
end
|
99
107
|
|
100
108
|
def scalar_type_extension
|
109
|
+
loc = pos
|
101
110
|
expect_token :SCALAR
|
102
111
|
name = self.name
|
103
112
|
directives = if at?(:DIR_SIGN); self.directives; end
|
104
|
-
Nodes::ScalarTypeExtension.new(name, directives)
|
113
|
+
Nodes::ScalarTypeExtension.new(loc, name, directives)
|
105
114
|
end
|
106
115
|
|
107
116
|
def object_type_extension
|
117
|
+
loc = pos
|
108
118
|
expect_token :TYPE
|
109
119
|
name = self.name
|
110
120
|
implements_interfaces = if at?(:IMPLEMENTS); self.implements_interfaces; end
|
111
121
|
directives = if at?(:DIR_SIGN); self.directives; end
|
112
122
|
fields_definition = if at?(:LCURLY); self.fields_definition; end
|
113
|
-
Nodes::ObjectTypeExtension.new(name, implements_interfaces, directives, fields_definition)
|
123
|
+
Nodes::ObjectTypeExtension.new(loc, name, implements_interfaces, directives, fields_definition)
|
114
124
|
end
|
115
125
|
|
116
126
|
def type_system_definition desc
|
@@ -123,13 +133,14 @@ module TinyGQL
|
|
123
133
|
end
|
124
134
|
|
125
135
|
def directive_defintion desc
|
136
|
+
loc = pos
|
126
137
|
expect_token :DIRECTIVE
|
127
138
|
expect_token :DIR_SIGN
|
128
139
|
name = self.name
|
129
140
|
arguments_definition = if at?(:LPAREN); self.arguments_definition; end
|
130
141
|
expect_token :ON
|
131
142
|
directive_locations = self.directive_locations
|
132
|
-
Nodes::DirectiveDefinition.new(desc, name, arguments_definition, directive_locations)
|
143
|
+
Nodes::DirectiveDefinition.new(loc, desc, name, arguments_definition, directive_locations)
|
133
144
|
end
|
134
145
|
|
135
146
|
def directive_locations
|
@@ -142,11 +153,12 @@ module TinyGQL
|
|
142
153
|
end
|
143
154
|
|
144
155
|
def directive_location
|
156
|
+
loc = pos
|
145
157
|
directive = expect_token_value :IDENTIFIER
|
146
158
|
|
147
159
|
case directive
|
148
160
|
when "QUERY", "MUTATION", "SUBSCRIPTION", "FIELD", "FRAGMENT_DEFINITION", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"
|
149
|
-
Nodes::ExecutableDirectiveLocation.new(directive)
|
161
|
+
Nodes::ExecutableDirectiveLocation.new(loc, directive)
|
150
162
|
when "SCHEMA",
|
151
163
|
"SCALAR",
|
152
164
|
"OBJECT",
|
@@ -158,7 +170,7 @@ module TinyGQL
|
|
158
170
|
"ENUM_VALUE",
|
159
171
|
"INPUT_OBJECT",
|
160
172
|
"INPUT_FIELD_DEFINITION"
|
161
|
-
Nodes::TypeSystemDirectiveLocation.new(directive)
|
173
|
+
Nodes::TypeSystemDirectiveLocation.new(loc, directive)
|
162
174
|
else
|
163
175
|
raise UnexpectedToken, "Expected directive #{directive}"
|
164
176
|
end
|
@@ -178,11 +190,12 @@ module TinyGQL
|
|
178
190
|
end
|
179
191
|
|
180
192
|
def input_object_type_definition desc
|
193
|
+
loc = pos
|
181
194
|
expect_token :INPUT
|
182
195
|
name = self.name
|
183
196
|
directives = if at?(:DIR_SIGN); self.directives; end
|
184
197
|
input_fields_definition = if at?(:LCURLY); self.input_fields_definition; end
|
185
|
-
Nodes::InputObjectTypeDefinition.new(desc, name, directives, input_fields_definition)
|
198
|
+
Nodes::InputObjectTypeDefinition.new(loc, desc, name, directives, input_fields_definition)
|
186
199
|
end
|
187
200
|
|
188
201
|
def input_fields_definition
|
@@ -196,11 +209,12 @@ module TinyGQL
|
|
196
209
|
end
|
197
210
|
|
198
211
|
def enum_type_definition desc
|
212
|
+
loc = pos
|
199
213
|
expect_token :ENUM
|
200
214
|
name = self.name
|
201
215
|
directives = if at?(:DIR_SIGN); self.directives; end
|
202
216
|
enum_values_definition = if at?(:LCURLY); self.enum_values_definition; end
|
203
|
-
Nodes::EnumTypeDefinition.new(desc, name, directives, enum_values_definition)
|
217
|
+
Nodes::EnumTypeDefinition.new(loc, desc, name, directives, enum_values_definition)
|
204
218
|
end
|
205
219
|
|
206
220
|
def enum_values_definition
|
@@ -214,25 +228,28 @@ module TinyGQL
|
|
214
228
|
end
|
215
229
|
|
216
230
|
def enum_value_definition
|
231
|
+
loc = pos
|
217
232
|
description = if at?(:STRING); string_value; end
|
218
233
|
enum_value = self.enum_value
|
219
234
|
directives = if at?(:DIR_SIGN); self.directives; end
|
220
|
-
Nodes::EnumValueDefinition.new(description, enum_value, directives)
|
235
|
+
Nodes::EnumValueDefinition.new(loc, description, enum_value, directives)
|
221
236
|
end
|
222
237
|
|
223
238
|
def scalar_type_definition desc
|
239
|
+
loc = pos
|
224
240
|
expect_token :SCALAR
|
225
241
|
name = self.name
|
226
242
|
directives = if at?(:DIR_SIGN); self.directives; end
|
227
|
-
Nodes::ScalarTypeDefinition.new(desc, name, directives)
|
243
|
+
Nodes::ScalarTypeDefinition.new(loc, desc, name, directives)
|
228
244
|
end
|
229
245
|
|
230
246
|
def union_type_definition desc
|
247
|
+
loc = pos
|
231
248
|
expect_token :UNION
|
232
249
|
name = self.name
|
233
250
|
directives = if at?(:DIR_SIGN); self.directives; end
|
234
251
|
union_member_types = if at?(:EQUALS); self.union_member_types; end
|
235
|
-
Nodes::UnionTypeDefinition.new(desc, name, directives, union_member_types)
|
252
|
+
Nodes::UnionTypeDefinition.new(loc, desc, name, directives, union_member_types)
|
236
253
|
end
|
237
254
|
|
238
255
|
def union_member_types
|
@@ -246,21 +263,23 @@ module TinyGQL
|
|
246
263
|
end
|
247
264
|
|
248
265
|
def interface_type_definition desc
|
266
|
+
loc = pos
|
249
267
|
expect_token :INTERFACE
|
250
268
|
name = self.name
|
251
269
|
directives = if at?(:DIR_SIGN); self.directives; end
|
252
270
|
fields_definition = if at?(:LCURLY); self.fields_definition; end
|
253
|
-
Nodes::InterfaceTypeDefinition.new(desc, name, directives, fields_definition)
|
271
|
+
Nodes::InterfaceTypeDefinition.new(loc, desc, name, directives, fields_definition)
|
254
272
|
end
|
255
273
|
|
256
274
|
def object_type_definition desc
|
275
|
+
loc = pos
|
257
276
|
expect_token :TYPE
|
258
277
|
name = self.name
|
259
278
|
implements_interfaces = if at?(:IMPLEMENTS); self.implements_interfaces; end
|
260
279
|
directives = if at?(:DIR_SIGN); self.directives; end
|
261
280
|
fields_definition = if at?(:LCURLY); self.fields_definition; end
|
262
281
|
|
263
|
-
Nodes::ObjectTypeDefinition.new(desc, name, implements_interfaces, directives, fields_definition)
|
282
|
+
Nodes::ObjectTypeDefinition.new(loc, desc, name, implements_interfaces, directives, fields_definition)
|
264
283
|
end
|
265
284
|
|
266
285
|
def fields_definition
|
@@ -274,6 +293,7 @@ module TinyGQL
|
|
274
293
|
end
|
275
294
|
|
276
295
|
def field_definition
|
296
|
+
loc = pos
|
277
297
|
description = if at?(:STRING); string_value; end
|
278
298
|
name = self.name
|
279
299
|
arguments_definition = if at?(:LPAREN); self.arguments_definition; end
|
@@ -281,7 +301,7 @@ module TinyGQL
|
|
281
301
|
type = self.type
|
282
302
|
directives = if at?(:DIR_SIGN); self.directives; end
|
283
303
|
|
284
|
-
Nodes::FieldDefinition.new(description, name, arguments_definition, type, directives)
|
304
|
+
Nodes::FieldDefinition.new(loc, description, name, arguments_definition, type, directives)
|
285
305
|
end
|
286
306
|
|
287
307
|
def arguments_definition
|
@@ -295,13 +315,14 @@ module TinyGQL
|
|
295
315
|
end
|
296
316
|
|
297
317
|
def input_value_definition
|
318
|
+
loc = pos
|
298
319
|
description = if at?(:STRING); string_value; end
|
299
320
|
name = self.name
|
300
321
|
expect_token :COLON
|
301
322
|
type = self.type
|
302
323
|
default_value = if at?(:EQUALS); self.default_value; end
|
303
324
|
directives = if at?(:DIR_SIGN); self.directives; end
|
304
|
-
Nodes::InputValueDefinition.new(description, name, type, default_value, directives)
|
325
|
+
Nodes::InputValueDefinition.new(loc, description, name, type, default_value, directives)
|
305
326
|
end
|
306
327
|
|
307
328
|
def implements_interfaces
|
@@ -316,21 +337,23 @@ module TinyGQL
|
|
316
337
|
end
|
317
338
|
|
318
339
|
def schema_definition desc
|
340
|
+
loc = pos
|
319
341
|
expect_token :SCHEMA
|
320
342
|
|
321
343
|
directives = if at?(:DIR_SIGN); self.directives; end
|
322
344
|
expect_token :LCURLY
|
323
345
|
defs = root_operation_type_definition
|
324
346
|
expect_token :RCURLY
|
325
|
-
Nodes::SchemaDefinition.new(desc, directives, defs)
|
347
|
+
Nodes::SchemaDefinition.new(loc, desc, directives, defs)
|
326
348
|
end
|
327
349
|
|
328
350
|
def root_operation_type_definition
|
329
351
|
list = []
|
330
352
|
while !at?(:RCURLY)
|
353
|
+
loc = pos
|
331
354
|
operation_type = self.operation_type
|
332
355
|
expect_token :COLON
|
333
|
-
list << Nodes::RootOperationTypeDefinition.new(operation_type, named_type)
|
356
|
+
list << Nodes::RootOperationTypeDefinition.new(loc, operation_type, named_type)
|
334
357
|
end
|
335
358
|
list
|
336
359
|
end
|
@@ -344,6 +367,7 @@ module TinyGQL
|
|
344
367
|
end
|
345
368
|
|
346
369
|
def fragment_definition
|
370
|
+
loc = pos
|
347
371
|
expect_token :FRAGMENT
|
348
372
|
expect_token(:IDENTIFIER) if at?(:ON)
|
349
373
|
name = self.name
|
@@ -352,10 +376,11 @@ module TinyGQL
|
|
352
376
|
self.directives
|
353
377
|
end
|
354
378
|
|
355
|
-
Nodes::FragmentDefinition.new(name, tc, directives, selection_set)
|
379
|
+
Nodes::FragmentDefinition.new(loc, name, tc, directives, selection_set)
|
356
380
|
end
|
357
381
|
|
358
382
|
def operation_definition
|
383
|
+
loc = pos
|
359
384
|
case token_name
|
360
385
|
when :QUERY, :MUTATION, :SUBSCRIPTION
|
361
386
|
type = self.operation_type
|
@@ -365,6 +390,7 @@ module TinyGQL
|
|
365
390
|
end
|
366
391
|
|
367
392
|
Nodes::OperationDefinition.new(
|
393
|
+
loc,
|
368
394
|
type,
|
369
395
|
ident,
|
370
396
|
variable_definitions,
|
@@ -403,15 +429,17 @@ module TinyGQL
|
|
403
429
|
end
|
404
430
|
|
405
431
|
def fragment_spread
|
432
|
+
loc = pos
|
406
433
|
name = self.name
|
407
434
|
directives = if at?(:DIR_SIGN); self.directives; end
|
408
435
|
|
409
436
|
expect_token(:IDENTIFIER) if at?(:ON)
|
410
437
|
|
411
|
-
Nodes::FragmentSpread.new(name, directives)
|
438
|
+
Nodes::FragmentSpread.new(loc, name, directives)
|
412
439
|
end
|
413
440
|
|
414
441
|
def inline_fragment
|
442
|
+
loc = pos
|
415
443
|
type_condition = if at?(:ON)
|
416
444
|
self.type_condition
|
417
445
|
end
|
@@ -420,15 +448,17 @@ module TinyGQL
|
|
420
448
|
self.directives
|
421
449
|
end
|
422
450
|
|
423
|
-
Nodes::InlineFragment.new(type_condition, directives, selection_set)
|
451
|
+
Nodes::InlineFragment.new(loc, type_condition, directives, selection_set)
|
424
452
|
end
|
425
453
|
|
426
454
|
def type_condition
|
455
|
+
loc = pos
|
427
456
|
expect_token :ON
|
428
|
-
Nodes::TypeCondition.new(named_type)
|
457
|
+
Nodes::TypeCondition.new(loc, named_type)
|
429
458
|
end
|
430
459
|
|
431
460
|
def field
|
461
|
+
loc = pos
|
432
462
|
name = self.name
|
433
463
|
|
434
464
|
aliaz = nil
|
@@ -443,11 +473,21 @@ module TinyGQL
|
|
443
473
|
directives = if at?(:DIR_SIGN); self.directives; end
|
444
474
|
selection_set = if at?(:LCURLY); self.selection_set; end
|
445
475
|
|
446
|
-
Nodes::Field.new(aliaz, name, arguments, directives, selection_set)
|
476
|
+
Nodes::Field.new(loc, aliaz, name, arguments, directives, selection_set)
|
447
477
|
end
|
448
478
|
|
449
479
|
def operation_type
|
450
|
-
|
480
|
+
val = if at?(:QUERY)
|
481
|
+
"query"
|
482
|
+
elsif at?(:MUTATION)
|
483
|
+
"mutation"
|
484
|
+
elsif at?(:SUBSCRIPTION)
|
485
|
+
"subscription"
|
486
|
+
else
|
487
|
+
expect_token(:QUERY)
|
488
|
+
end
|
489
|
+
accept_token
|
490
|
+
val
|
451
491
|
end
|
452
492
|
|
453
493
|
def directives
|
@@ -459,13 +499,14 @@ module TinyGQL
|
|
459
499
|
end
|
460
500
|
|
461
501
|
def directive
|
502
|
+
loc = pos
|
462
503
|
expect_token(:DIR_SIGN)
|
463
504
|
name = self.name
|
464
505
|
arguments = if at?(:LPAREN)
|
465
506
|
self.arguments
|
466
507
|
end
|
467
508
|
|
468
|
-
Nodes::Directive.new(name, arguments)
|
509
|
+
Nodes::Directive.new(loc, name, arguments)
|
469
510
|
end
|
470
511
|
|
471
512
|
def arguments
|
@@ -479,9 +520,10 @@ module TinyGQL
|
|
479
520
|
end
|
480
521
|
|
481
522
|
def argument
|
523
|
+
loc = pos
|
482
524
|
name = self.name
|
483
525
|
expect_token(:COLON)
|
484
|
-
Nodes::Argument.new(name, value)
|
526
|
+
Nodes::Argument.new(loc, name, value)
|
485
527
|
end
|
486
528
|
|
487
529
|
def variable_definitions
|
@@ -495,14 +537,15 @@ module TinyGQL
|
|
495
537
|
end
|
496
538
|
|
497
539
|
def variable_definition
|
498
|
-
|
540
|
+
loc = pos
|
541
|
+
var = variable if at?(:VAR_SIGN)
|
499
542
|
expect_token(:COLON)
|
500
543
|
type = self.type
|
501
544
|
default_value = if at?(:EQUALS)
|
502
545
|
self.default_value
|
503
546
|
end
|
504
547
|
|
505
|
-
Nodes::VariableDefinition.new(var, type, default_value)
|
548
|
+
Nodes::VariableDefinition.new(loc, var, type, default_value)
|
506
549
|
end
|
507
550
|
|
508
551
|
def default_value
|
@@ -527,49 +570,61 @@ module TinyGQL
|
|
527
570
|
end
|
528
571
|
|
529
572
|
def object_value
|
573
|
+
start = pos
|
530
574
|
expect_token(:LCURLY)
|
531
575
|
list = []
|
532
576
|
while !at?(:RCURLY)
|
577
|
+
loc = pos
|
533
578
|
n = name
|
534
579
|
expect_token(:COLON)
|
535
|
-
list << Nodes::ObjectField.new(n, value)
|
580
|
+
list << Nodes::ObjectField.new(loc, n, value)
|
536
581
|
end
|
537
582
|
expect_token(:RCURLY)
|
538
|
-
Nodes::ObjectValue.new(list)
|
583
|
+
Nodes::ObjectValue.new(start, list)
|
539
584
|
end
|
540
585
|
|
541
586
|
def list_value
|
587
|
+
loc = pos
|
542
588
|
expect_token(:LBRACKET)
|
543
589
|
list = []
|
544
590
|
while !at?(:RBRACKET)
|
545
591
|
list << value
|
546
592
|
end
|
547
593
|
expect_token(:RBRACKET)
|
548
|
-
Nodes::ListValue.new(list)
|
594
|
+
Nodes::ListValue.new(loc, list)
|
549
595
|
end
|
550
596
|
|
551
597
|
def enum_value
|
552
|
-
Nodes::EnumValue.new(expect_token_value(:IDENTIFIER))
|
598
|
+
Nodes::EnumValue.new(pos, expect_token_value(:IDENTIFIER))
|
553
599
|
end
|
554
600
|
|
555
601
|
def float_value
|
556
|
-
Nodes::FloatValue.new(expect_token_value(:FLOAT))
|
602
|
+
Nodes::FloatValue.new(pos, expect_token_value(:FLOAT))
|
557
603
|
end
|
558
604
|
|
559
605
|
def int_value
|
560
|
-
Nodes::IntValue.new(expect_token_value(:INT))
|
606
|
+
Nodes::IntValue.new(pos, expect_token_value(:INT))
|
561
607
|
end
|
562
608
|
|
563
609
|
def string_value
|
564
|
-
Nodes::StringValue.new(
|
610
|
+
Nodes::StringValue.new(pos, expect_string_value)
|
565
611
|
end
|
566
612
|
|
567
613
|
def boolean_value
|
568
|
-
|
614
|
+
if at?(:TRUE)
|
615
|
+
accept_token
|
616
|
+
Nodes::BooleanValue.new(pos, "true")
|
617
|
+
elsif at?(:FALSE)
|
618
|
+
accept_token
|
619
|
+
Nodes::BooleanValue.new(pos, "false")
|
620
|
+
else
|
621
|
+
expect_token(:TRUE)
|
622
|
+
end
|
569
623
|
end
|
570
624
|
|
571
625
|
def null_value
|
572
|
-
|
626
|
+
expect_token :NULL
|
627
|
+
Nodes::NullValue.new(pos, "null")
|
573
628
|
end
|
574
629
|
|
575
630
|
def type
|
@@ -579,47 +634,49 @@ module TinyGQL
|
|
579
634
|
end
|
580
635
|
|
581
636
|
if at?(:BANG)
|
582
|
-
Nodes::NotNullType.new type
|
637
|
+
Nodes::NotNullType.new pos, type
|
583
638
|
expect_token(:BANG)
|
584
639
|
end
|
585
640
|
type
|
586
641
|
end
|
587
642
|
|
588
643
|
def list_type
|
644
|
+
loc = pos
|
589
645
|
expect_token(:LBRACKET)
|
590
|
-
type = Nodes::ListType.new(self.type)
|
646
|
+
type = Nodes::ListType.new(loc, self.type)
|
591
647
|
expect_token(:RBRACKET)
|
592
648
|
type
|
593
649
|
end
|
594
650
|
|
595
651
|
def named_type
|
596
|
-
Nodes::NamedType.new(name)
|
652
|
+
Nodes::NamedType.new(pos, name)
|
597
653
|
end
|
598
654
|
|
599
655
|
def variable
|
600
|
-
|
601
|
-
|
602
|
-
Nodes::Variable.new name
|
656
|
+
loc = pos
|
657
|
+
expect_token(:VAR_SIGN)
|
658
|
+
Nodes::Variable.new loc, name
|
603
659
|
end
|
604
660
|
|
605
661
|
def name
|
606
662
|
case token_name
|
607
|
-
when :IDENTIFIER
|
663
|
+
when :IDENTIFIER then expect_token_value(:IDENTIFIER)
|
664
|
+
when :TYPE then
|
665
|
+
accept_token
|
666
|
+
"type"
|
667
|
+
when :QUERY then
|
668
|
+
accept_token
|
669
|
+
"query"
|
670
|
+
when :INPUT then
|
671
|
+
accept_token
|
672
|
+
"input"
|
608
673
|
else
|
609
|
-
|
674
|
+
expect_token(:IDENTIFIER)
|
610
675
|
end
|
611
676
|
end
|
612
677
|
|
613
678
|
def accept_token
|
614
|
-
@lexer.advance
|
615
|
-
@token_name = @lexer.token_name
|
616
|
-
end
|
617
|
-
|
618
|
-
# Only use when we care about the accepted token's value
|
619
|
-
def accept_token_value
|
620
|
-
token_value = @lexer.token_value
|
621
|
-
accept_token
|
622
|
-
token_value
|
679
|
+
@token_name = @lexer.advance
|
623
680
|
end
|
624
681
|
|
625
682
|
def expect_token tok
|
@@ -636,12 +693,9 @@ module TinyGQL
|
|
636
693
|
token_value
|
637
694
|
end
|
638
695
|
|
639
|
-
def
|
640
|
-
token_value = @lexer.
|
641
|
-
|
642
|
-
raise UnexpectedToken, "Expected token #{tok}, actual: #{token_name}"
|
643
|
-
end
|
644
|
-
accept_token
|
696
|
+
def expect_string_value
|
697
|
+
token_value = @lexer.string_value
|
698
|
+
expect_token :STRING
|
645
699
|
token_value
|
646
700
|
end
|
647
701
|
|
data/lib/tinygql/version.rb
CHANGED
data/test/lexer_test.rb
CHANGED
@@ -101,5 +101,106 @@ eod
|
|
101
101
|
[:RCURLY, "}"],
|
102
102
|
[:RCURLY, "}"]], toks
|
103
103
|
end
|
104
|
+
|
105
|
+
def test_lex_4
|
106
|
+
words = ["true", "null", "enum", "type"]
|
107
|
+
doc = words.join(" ")
|
108
|
+
|
109
|
+
lexer = Lexer.new doc
|
110
|
+
toks = []
|
111
|
+
while tok = lexer.next_token
|
112
|
+
toks << tok
|
113
|
+
end
|
114
|
+
|
115
|
+
assert_equal words.map { |x| [x.upcase.to_sym, x] }, toks
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_lex_5
|
119
|
+
words = ["input", "false", "query", "union"]
|
120
|
+
doc = words.join(" ")
|
121
|
+
|
122
|
+
lexer = Lexer.new doc
|
123
|
+
toks = []
|
124
|
+
while tok = lexer.next_token
|
125
|
+
toks << tok
|
126
|
+
end
|
127
|
+
|
128
|
+
assert_equal words.map { |x| [x.upcase.to_sym, x] }, toks
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_lex_6
|
132
|
+
words = ["extend", "scalar", "schema"]
|
133
|
+
doc = words.join(" ")
|
134
|
+
|
135
|
+
lexer = Lexer.new doc
|
136
|
+
toks = []
|
137
|
+
while tok = lexer.next_token
|
138
|
+
toks << tok
|
139
|
+
end
|
140
|
+
|
141
|
+
assert_equal words.map { |x| [x.upcase.to_sym, x] }, toks
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_lex_8
|
145
|
+
words = ["mutation", "fragment"]
|
146
|
+
doc = words.join(" ")
|
147
|
+
|
148
|
+
lexer = Lexer.new doc
|
149
|
+
toks = []
|
150
|
+
while tok = lexer.next_token
|
151
|
+
toks << tok
|
152
|
+
end
|
153
|
+
|
154
|
+
assert_equal words.map { |x| [x.upcase.to_sym, x] }, toks
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_lex_9
|
158
|
+
words = ["interface", "directive"]
|
159
|
+
doc = words.join(" ")
|
160
|
+
|
161
|
+
lexer = Lexer.new doc
|
162
|
+
toks = []
|
163
|
+
while tok = lexer.next_token
|
164
|
+
toks << tok
|
165
|
+
end
|
166
|
+
|
167
|
+
assert_equal words.map { |x| [x.upcase.to_sym, x] }, toks
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_kw_lex
|
171
|
+
words = ["on", "fragment", "true", "false", "null", "query", "mutation", "subscription", "schema", "scalar", "type", "extend", "implements", "interface", "union", "enum", "input", "directive", "repeatable"]
|
172
|
+
doc = words.join(" ")
|
173
|
+
|
174
|
+
lexer = Lexer.new doc
|
175
|
+
toks = []
|
176
|
+
while tok = lexer.next_token
|
177
|
+
toks << tok
|
178
|
+
end
|
179
|
+
|
180
|
+
assert_equal words.map { |x| [x.upcase.to_sym, x] }, toks
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_looks_like_kw
|
184
|
+
words = ["fragment", "fragments"]
|
185
|
+
doc = words.join(" ")
|
186
|
+
|
187
|
+
lexer = Lexer.new doc
|
188
|
+
toks = []
|
189
|
+
while tok = lexer.advance
|
190
|
+
toks << tok
|
191
|
+
end
|
192
|
+
|
193
|
+
assert_equal [:FRAGMENT, :IDENTIFIER], toks
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_num_with_dots
|
197
|
+
lexer = Lexer.new "1...2"
|
198
|
+
toks = []
|
199
|
+
while tok = lexer.advance
|
200
|
+
toks << tok
|
201
|
+
end
|
202
|
+
|
203
|
+
assert_equal [:INT, :ELLIPSIS, :INT], toks
|
204
|
+
end
|
104
205
|
end
|
105
206
|
end
|
data/test/parser_test.rb
CHANGED
@@ -46,6 +46,23 @@ eod
|
|
46
46
|
assert_equal ["likeStory", "story", "likeCount"], ast.find_all(&:field?).map(&:name)
|
47
47
|
end
|
48
48
|
|
49
|
+
def test_has_position_and_line
|
50
|
+
doc = <<-eod
|
51
|
+
mutation {
|
52
|
+
likeStory(sturyID: 12345) {
|
53
|
+
story {
|
54
|
+
likeCount
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
eod
|
59
|
+
parser = Parser.new doc
|
60
|
+
ast = parser.parse
|
61
|
+
expected = ["likeStory", "story", "likeCount"].map { |str| doc.index(str) }
|
62
|
+
assert_equal expected, ast.find_all(&:field?).map(&:start)
|
63
|
+
assert_equal [2, 3, 4], ast.find_all(&:field?).map { |n| n.line(doc) }
|
64
|
+
end
|
65
|
+
|
49
66
|
def test_field_alias
|
50
67
|
doc = <<-eod
|
51
68
|
mutation {
|