tinygql 0.1.4 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 {
|