Class: Graphlyte::Parser
Overview
A parser of GraphQL documents from a stream of lexical tokens.
Instance Attribute Summary
#max_depth, #tokens
Instance Method Summary
collapse
#advance, #bracket, #current, #expect, #initialize, #inspect, #many, #name, #next_token, #one_of, #optional, #optional_list, #peek, #punctuator, #some, #subfeature, #to_s, #too_deep?, #try_parse
Instance Method Details
#arguments ⇒ Object
117
118
119
|
# File 'lib/graphlyte/parser.rb', line 117
def arguments
bracket('(', ')') { some { parse_argument } }
end
|
#default_value ⇒ Object
211
212
213
214
215
|
# File 'lib/graphlyte/parser.rb', line 211
def default_value
expect(:PUNCTUATOR, '=')
parse_value
end
|
#definition ⇒ Object
30
31
32
|
# File 'lib/graphlyte/parser.rb', line 30
def definition
one_of(:executable_definition, :type_definition)
end
|
#directives ⇒ Object
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
# File 'lib/graphlyte/parser.rb', line 173
def directives
ret = []
while peek(offset: 1).punctuator?('@')
d = Graphlyte::Syntax::Directive.new
expect(:PUNCTUATOR, '@')
d.name = name
d.arguments = optional { arguments }
ret << d
end
ret
end
|
#document ⇒ Object
11
12
13
14
15
16
17
18
|
# File 'lib/graphlyte/parser.rb', line 11
def document
doc = Graphlyte::Document.new
doc.definitions = some { definition }
expect(:EOF)
doc
end
|
#executable_definition ⇒ Object
34
35
36
|
# File 'lib/graphlyte/parser.rb', line 34
def executable_definition
one_of(:fragment, :operation)
end
|
#field_selection ⇒ Object
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
# File 'lib/graphlyte/parser.rb', line 99
def field_selection
field = Graphlyte::Syntax::Field.new
field.as = optional do
n = name
punctuator(':')
n
end
field.name = name
field.arguments = optional_list { arguments }
field.directives = directives
field.selection = optional_list { selection_set }
field
end
|
#fragment ⇒ Object
250
251
252
253
254
255
256
257
258
259
260
261
262
263
|
# File 'lib/graphlyte/parser.rb', line 250
def fragment
frag = Graphlyte::Syntax::Fragment.new
expect(:NAME, 'fragment')
frag.name = name
expect(:NAME, 'on')
frag.type_name = name
frag.directives = directives
frag.selection = selection_set
frag
end
|
#fragment_spread ⇒ Object
76
77
78
79
80
81
82
83
84
|
# File 'lib/graphlyte/parser.rb', line 76
def fragment_spread
frag = Graphlyte::Syntax::FragmentSpread.new
punctuator('...')
frag.name = name
frag.directives = directives
frag
end
|
#implicit_query ⇒ Object
52
53
54
|
# File 'lib/graphlyte/parser.rb', line 52
def implicit_query
Graphlyte::Syntax::Operation.new(type: :query, selection: selection_set)
end
|
#inline_fragment ⇒ Object
86
87
88
89
90
91
92
93
94
95
96
97
|
# File 'lib/graphlyte/parser.rb', line 86
def inline_fragment
punctuator('...')
name('on')
frag = Graphlyte::Syntax::InlineFragment.new
frag.type_name = name
frag.directives = directives
frag.selection = selection_set
frag
end
|
#list_type_name ⇒ Object
241
242
243
244
245
246
247
248
|
# File 'lib/graphlyte/parser.rb', line 241
def list_type_name
type = bracket('[', ']') { type_name(list: true) }
t = peek(offset: 1)
type.non_null_list = t.punctuator?('!')
advance if type.non_null_list
type
end
|
#operation ⇒ Object
38
39
40
41
42
43
44
45
46
47
48
49
50
|
# File 'lib/graphlyte/parser.rb', line 38
def operation
t = next_token
case t.type
when :PUNCTUATOR
@index -= 1
implicit_query
when :NAME
operation_from_kind(t.value.to_sym)
else
raise Unexpected, t
end
end
|
#operation_from_kind(kind) ⇒ Object
56
57
58
59
60
61
62
63
64
65
66
67
68
|
# File 'lib/graphlyte/parser.rb', line 56
def operation_from_kind(kind)
op = Graphlyte::Syntax::Operation.new
try_parse do
op.type = kind
op.name = optional { name }
op.variables = optional { variable_definitions }
op.directives = directives
op.selection = selection_set
end
op
end
|
#operation_type ⇒ Object
188
189
190
191
192
|
# File 'lib/graphlyte/parser.rb', line 188
def operation_type
raise Unexpected, current unless current.type == :NAME
current.value.to_sym
end
|
#parse_argument ⇒ Object
121
122
123
124
125
126
127
128
129
|
# File 'lib/graphlyte/parser.rb', line 121
def parse_argument
arg = Graphlyte::Syntax::Argument.new
arg.name = name
expect(:PUNCTUATOR, ':')
arg.value = parse_value
arg
end
|
#parse_array_value ⇒ Object
157
158
159
|
# File 'lib/graphlyte/parser.rb', line 157
def parse_array_value
bracket('[', ']') { many { parse_value } }
end
|
#parse_object_value ⇒ Object
161
162
163
164
165
166
167
168
169
170
171
|
# File 'lib/graphlyte/parser.rb', line 161
def parse_object_value
bracket('{', '}') do
many do
n = name
expect(:PUNCTUATOR, ':')
value = parse_value
[n, value]
end.to_h
end
end
|
#parse_value ⇒ Object
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
# File 'lib/graphlyte/parser.rb', line 131
def parse_value
t = next_token
case t.type
when :STRING, :NUMBER
Graphlyte::Syntax::Value.new(t.value, t.type)
when :NAME
Graphlyte::Syntax::Value.from_name(t.value)
when :PUNCTUATOR
case t.value
when '$'
Graphlyte::Syntax::VariableReference.new(name)
when '{'
@index -= 1
parse_object_value
when '['
@index -= 1
parse_array_value
else
raise Unexpected, t
end
else
raise Unexpected, t
end
end
|
#query ⇒ Object
Restricted parser: only parses executable definitions
21
22
23
24
25
26
27
28
|
# File 'lib/graphlyte/parser.rb', line 21
def query
doc = Graphlyte::Document.new
doc.definitions = some { executable_definition }
expect(:EOF)
doc
end
|
#selection_set ⇒ Object
70
71
72
73
74
|
# File 'lib/graphlyte/parser.rb', line 70
def selection_set
bracket('{', '}') do
some { one_of(:inline_fragment, :fragment_spread, :field_selection) }
end
end
|
#type_definition ⇒ Object
265
266
267
|
# File 'lib/graphlyte/parser.rb', line 265
def type_definition
raise ParseError, "TODO: #{current.location}"
end
|
#type_name(list: false) ⇒ Object
223
224
225
226
227
228
229
230
231
232
|
# File 'lib/graphlyte/parser.rb', line 223
def type_name(list: false)
ty = Graphlyte::Syntax::Type.new(name)
t = peek(offset: 1)
ty.non_null = t.punctuator?('!')
ty.is_list = list
advance if ty.non_null
ty
end
|
#type_name! ⇒ Object
234
235
236
237
238
239
|
# File 'lib/graphlyte/parser.rb', line 234
def type_name!
ty = type_name
expect(:EOF)
ty
end
|
#variable_definitions ⇒ Object
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
|
# File 'lib/graphlyte/parser.rb', line 194
def variable_definitions
bracket('(', ')') do
some do
var = Graphlyte::Syntax::VariableDefinition.new
var.variable = variable_name
expect(:PUNCTUATOR, ':')
var.type = one_of(:list_type_name, :type_name)
var.default_value = optional { default_value }
var.directives = directives
var
end
end
end
|
#variable_name ⇒ Object
217
218
219
220
221
|
# File 'lib/graphlyte/parser.rb', line 217
def variable_name
expect(:PUNCTUATOR, '$')
name
end
|