tinygql 0.1.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -13,8 +13,7 @@ module TinyGQL
13
13
 
14
14
  def initialize doc
15
15
  @lexer = Lexer.new doc
16
- @lexer.advance
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
- Nodes::Document.new definition_list
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
- expect_tokens([:QUERY, :MUTATION, :SUBSCRIPTION])
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
- var = variable
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(expect_token_value(:STRING))
610
+ Nodes::StringValue.new(pos, expect_string_value)
565
611
  end
566
612
 
567
613
  def boolean_value
568
- Nodes::BooleanValue.new(expect_tokens([:TRUE, :FALSE]))
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
- Nodes::NullValue.new(expect_token_value(:NULL))
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
- return unless at?(:VAR_SIGN)
601
- accept_token
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, :INPUT, :QUERY, :TYPE then accept_token_value
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
- expect_token_value(:IDENTIFIER)
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 expect_tokens toks
640
- token_value = @lexer.token_value
641
- unless toks.any? { |tok| at?(tok) }
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
 
@@ -1,3 +1,3 @@
1
1
  module TinyGQL
2
- VERSION = '0.1.4'
2
+ VERSION = '0.3.0'
3
3
  end
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 {