gql 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +60 -60
- data/lib/gql/call.rb +46 -7
- data/lib/gql/config.rb +23 -0
- data/lib/gql/connection.rb +22 -22
- data/lib/gql/errors.rb +15 -11
- data/lib/gql/executor.rb +8 -7
- data/lib/gql/field.rb +26 -2
- data/lib/gql/fields/connection.rb +26 -12
- data/lib/gql/fields/object.rb +28 -8
- data/lib/gql/node.rb +75 -90
- data/lib/gql/parser.rb +214 -284
- data/lib/gql/parser.y +40 -110
- data/lib/gql/version.rb +1 -1
- data/lib/gql.rb +33 -16
- metadata +3 -3
- data/lib/gql/schema.rb +0 -21
data/lib/gql/parser.y
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
class GQL::Parser
|
2
2
|
token STRING NUMBER TRUE FALSE NULL AS IDENT
|
3
3
|
rule
|
4
|
-
|
5
|
-
: variables
|
4
|
+
root
|
5
|
+
: variables node variables { result = Root.new(val[1], val[0].merge(val[2])) }
|
6
|
+
| variables { result = Root.new(Node.new(nil, nil), val[0] ) }
|
6
7
|
;
|
7
8
|
|
8
|
-
|
9
|
-
:
|
10
|
-
|
|
11
|
-
| identifier arguments { result = CallNode.new(val[0], val[1], nil, nil) }
|
9
|
+
node
|
10
|
+
: call { result = Node.new(val[0], nil ) }
|
11
|
+
| fields { result = Node.new(nil, val[0].presence) }
|
12
12
|
;
|
13
13
|
|
14
|
-
|
15
|
-
:
|
14
|
+
call
|
15
|
+
: identifier arguments fields { result = Call.new(val[0], val[1], nil, val[2].presence) }
|
16
|
+
| identifier arguments '.' call { result = Call.new(val[0], val[1], val[3], nil ) }
|
17
|
+
| identifier arguments { result = Call.new(val[0], val[1], nil, nil ) }
|
16
18
|
;
|
17
19
|
|
18
20
|
arguments
|
@@ -28,7 +30,7 @@ rule
|
|
28
30
|
|
29
31
|
argument
|
30
32
|
: variable_identifier
|
31
|
-
|
|
33
|
+
| json_value
|
32
34
|
;
|
33
35
|
|
34
36
|
fields
|
@@ -42,30 +44,30 @@ rule
|
|
42
44
|
;
|
43
45
|
|
44
46
|
field
|
45
|
-
: identifier fields alias_identifier { result =
|
46
|
-
| identifier
|
47
|
-
| identifier alias_identifier { result =
|
48
|
-
| identifier fields { result =
|
49
|
-
| identifier
|
50
|
-
| identifier { result =
|
47
|
+
: identifier fields alias_identifier { result = Field.new(val[0], val[2], nil, val[1].presence) }
|
48
|
+
| identifier '.' call alias_identifier { result = Field.new(val[0], val[3], val[2], nil ) }
|
49
|
+
| identifier alias_identifier { result = Field.new(val[0], val[1], nil, nil ) }
|
50
|
+
| identifier fields { result = Field.new(val[0], nil, nil, val[1].presence) }
|
51
|
+
| identifier '.' call { result = Field.new(val[0], nil, val[2], nil ) }
|
52
|
+
| identifier { result = Field.new(val[0], nil, nil, nil ) }
|
51
53
|
;
|
52
54
|
|
53
55
|
alias_identifier
|
54
|
-
: AS identifier { result = val[1]
|
56
|
+
: AS identifier { result = val[1] }
|
55
57
|
;
|
56
58
|
|
57
59
|
variables
|
58
|
-
: /* empty */ { result =
|
59
|
-
| variable_list
|
60
|
+
: /* empty */ { result = {} }
|
61
|
+
| variable_list
|
60
62
|
;
|
61
63
|
|
62
64
|
variable_list
|
63
|
-
: variable
|
64
|
-
| variable_list variable { result.
|
65
|
+
: variable
|
66
|
+
| variable_list variable { result.update val[1] }
|
65
67
|
;
|
66
68
|
|
67
69
|
variable
|
68
|
-
: variable_identifier '=' variable_value { result =
|
70
|
+
: variable_identifier '=' variable_value { result = { val[0] => val[2] } }
|
69
71
|
;
|
70
72
|
|
71
73
|
variable_identifier
|
@@ -73,12 +75,9 @@ rule
|
|
73
75
|
;
|
74
76
|
|
75
77
|
variable_value
|
76
|
-
:
|
78
|
+
: json_value
|
77
79
|
;
|
78
80
|
|
79
|
-
json_text
|
80
|
-
: json_value { result = @json.result }
|
81
|
-
|
82
81
|
json_value
|
83
82
|
: object
|
84
83
|
| array
|
@@ -86,51 +85,40 @@ rule
|
|
86
85
|
;
|
87
86
|
|
88
87
|
object
|
89
|
-
:
|
90
|
-
|
|
88
|
+
: '{' '}' { result = {} }
|
89
|
+
| '{' pairs '}' { result = val[1] }
|
91
90
|
;
|
92
91
|
|
93
|
-
start_object : '{' { @json.start_object } ;
|
94
|
-
end_object : '}' { @json.end_object } ;
|
95
|
-
|
96
92
|
pairs
|
97
|
-
: pairs ',' pair
|
93
|
+
: pairs ',' pair { result.update val[2] }
|
98
94
|
| pair
|
99
95
|
;
|
100
96
|
|
101
97
|
pair
|
102
|
-
: string ':' json_value
|
98
|
+
: string ':' json_value { result = { val[0] => val[2] } }
|
103
99
|
;
|
104
100
|
|
105
101
|
array
|
106
|
-
:
|
107
|
-
|
|
102
|
+
: '[' ']' { result = [] }
|
103
|
+
| '[' values ']' { result = val[1] }
|
108
104
|
;
|
109
105
|
|
110
|
-
start_array : '[' { @json.start_array } ;
|
111
|
-
end_array : ']' { @json.end_array } ;
|
112
|
-
|
113
106
|
values
|
114
|
-
: values ',' json_value
|
115
|
-
| json_value
|
107
|
+
: values ',' json_value { result.push val[2] }
|
108
|
+
| json_value { result = val }
|
116
109
|
;
|
117
110
|
|
118
111
|
scalar
|
119
112
|
: string
|
120
|
-
|
|
121
|
-
;
|
122
|
-
|
123
|
-
string
|
124
|
-
: STRING { @json.scalar unescape_string(val[0]) }
|
125
|
-
;
|
126
|
-
|
127
|
-
literal
|
128
|
-
: NUMBER { result = convert_number(val[0]) }
|
113
|
+
| NUMBER { result = convert_number(val[0]) }
|
129
114
|
| TRUE { result = true }
|
130
115
|
| FALSE { result = false }
|
131
116
|
| NULL { result = nil }
|
132
117
|
;
|
133
118
|
|
119
|
+
string
|
120
|
+
: STRING { result = unescape_string(val[0]) }
|
121
|
+
|
134
122
|
identifier
|
135
123
|
: IDENT { result = val[0].to_sym }
|
136
124
|
;
|
@@ -143,69 +131,16 @@ require 'active_support/core_ext/object/blank'
|
|
143
131
|
|
144
132
|
---- inner
|
145
133
|
|
146
|
-
class
|
134
|
+
class Root < Struct.new(:node, :variables)
|
147
135
|
end
|
148
136
|
|
149
|
-
class
|
137
|
+
class Node < Struct.new(:call, :fields)
|
150
138
|
end
|
151
139
|
|
152
|
-
class
|
140
|
+
class Field < Struct.new(:name, :alias_name, :call, :fields)
|
153
141
|
end
|
154
142
|
|
155
|
-
class
|
156
|
-
attr_reader :stack
|
157
|
-
|
158
|
-
def initialize
|
159
|
-
clear
|
160
|
-
end
|
161
|
-
|
162
|
-
def start_object
|
163
|
-
push [:hash]
|
164
|
-
end
|
165
|
-
|
166
|
-
def start_array
|
167
|
-
push [:array]
|
168
|
-
end
|
169
|
-
|
170
|
-
def end_array
|
171
|
-
@stack.pop
|
172
|
-
end
|
173
|
-
|
174
|
-
alias :end_object :end_array
|
175
|
-
|
176
|
-
def scalar(s)
|
177
|
-
@stack.last << [:scalar, s]
|
178
|
-
end
|
179
|
-
|
180
|
-
def push(o)
|
181
|
-
@stack.last << o
|
182
|
-
@stack << o
|
183
|
-
end
|
184
|
-
|
185
|
-
def result
|
186
|
-
root = @stack.first.last
|
187
|
-
value = process(root.first, root.drop(1))
|
188
|
-
clear
|
189
|
-
value
|
190
|
-
end
|
191
|
-
|
192
|
-
private
|
193
|
-
def clear
|
194
|
-
@stack = [[:json]]
|
195
|
-
end
|
196
|
-
|
197
|
-
def process(type, rest)
|
198
|
-
case type
|
199
|
-
when :array
|
200
|
-
rest.map { |x| process(x.first, x.drop(1)) }
|
201
|
-
when :hash
|
202
|
-
Hash[rest.map { |x|
|
203
|
-
process(x.first, x.drop(1))
|
204
|
-
}.each_slice(2).to_a]
|
205
|
-
when :scalar
|
206
|
-
rest.first
|
207
|
-
end
|
208
|
-
end
|
143
|
+
class Call < Struct.new(:name, :arguments, :call, :fields)
|
209
144
|
end
|
210
145
|
|
211
146
|
UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
|
@@ -239,7 +174,6 @@ require 'active_support/core_ext/object/blank'
|
|
239
174
|
end
|
240
175
|
|
241
176
|
def parse
|
242
|
-
@json = JSONHandler.new
|
243
177
|
do_parse
|
244
178
|
end
|
245
179
|
|
@@ -275,7 +209,3 @@ require 'active_support/core_ext/object/blank'
|
|
275
209
|
def convert_number(str)
|
276
210
|
str.count('.') > 0 ? str.to_f : str.to_i
|
277
211
|
end
|
278
|
-
|
279
|
-
def convert_variables(arr1, arr2)
|
280
|
-
Hash[*arr1.flatten(1)].merge Hash[*arr2.flatten(1)]
|
281
|
-
end
|
data/lib/gql/version.rb
CHANGED
data/lib/gql.rb
CHANGED
@@ -1,21 +1,22 @@
|
|
1
1
|
module GQL
|
2
2
|
autoload :Call, 'gql/call'
|
3
|
+
autoload :Config, 'gql/config'
|
3
4
|
autoload :Connection, 'gql/connection'
|
4
5
|
autoload :Executor, 'gql/executor'
|
5
6
|
autoload :Field, 'gql/field'
|
6
7
|
autoload :Node, 'gql/node'
|
7
8
|
autoload :Parser, 'gql/parser'
|
8
|
-
autoload :Schema, 'gql/schema'
|
9
9
|
autoload :Tokenizer, 'gql/tokenizer'
|
10
10
|
autoload :VERSION, 'gql/version'
|
11
11
|
|
12
12
|
module Errors
|
13
|
-
autoload :InvalidNodeClass,
|
14
|
-
autoload :ParseError,
|
15
|
-
autoload :UndefinedCall,
|
16
|
-
autoload :UndefinedField,
|
17
|
-
autoload :
|
18
|
-
autoload :
|
13
|
+
autoload :InvalidNodeClass, 'gql/errors'
|
14
|
+
autoload :ParseError, 'gql/errors'
|
15
|
+
autoload :UndefinedCall, 'gql/errors'
|
16
|
+
autoload :UndefinedField, 'gql/errors'
|
17
|
+
autoload :UndefinedNodeClass, 'gql/errors'
|
18
|
+
autoload :UndefinedRoot, 'gql/errors'
|
19
|
+
autoload :UndefinedFieldType, 'gql/errors'
|
19
20
|
end
|
20
21
|
|
21
22
|
module Fields
|
@@ -27,16 +28,23 @@ module GQL
|
|
27
28
|
autoload :String, 'gql/fields/string'
|
28
29
|
end
|
29
30
|
|
30
|
-
Schema.fields.update(
|
31
|
-
boolean: Fields::Boolean,
|
32
|
-
connection: Fields::Connection,
|
33
|
-
float: Fields::Float,
|
34
|
-
integer: Fields::Integer,
|
35
|
-
object: Fields::Object,
|
36
|
-
string: Fields::String
|
37
|
-
)
|
38
|
-
|
39
31
|
extend(Module.new {
|
32
|
+
def config
|
33
|
+
Thread.current[:gql_config] ||= Config.new
|
34
|
+
end
|
35
|
+
|
36
|
+
%w(root_node_class field_types).each do |method|
|
37
|
+
module_eval <<-DELEGATORS, __FILE__, __LINE__ + 1
|
38
|
+
def #{method}
|
39
|
+
config.#{method}
|
40
|
+
end
|
41
|
+
|
42
|
+
def #{method}=(value)
|
43
|
+
config.#{method} = (value)
|
44
|
+
end
|
45
|
+
DELEGATORS
|
46
|
+
end
|
47
|
+
|
40
48
|
def execute(input, context = {})
|
41
49
|
ast = parse(input)
|
42
50
|
|
@@ -65,4 +73,13 @@ module GQL
|
|
65
73
|
end
|
66
74
|
end
|
67
75
|
})
|
76
|
+
|
77
|
+
self.field_types.update(
|
78
|
+
boolean: Fields::Boolean,
|
79
|
+
connection: Fields::Connection,
|
80
|
+
float: Fields::Float,
|
81
|
+
integer: Fields::Integer,
|
82
|
+
object: Fields::Object,
|
83
|
+
string: Fields::String
|
84
|
+
)
|
68
85
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Andert
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -111,6 +111,7 @@ files:
|
|
111
111
|
- gql.gemspec
|
112
112
|
- lib/gql.rb
|
113
113
|
- lib/gql/call.rb
|
114
|
+
- lib/gql/config.rb
|
114
115
|
- lib/gql/connection.rb
|
115
116
|
- lib/gql/errors.rb
|
116
117
|
- lib/gql/executor.rb
|
@@ -124,7 +125,6 @@ files:
|
|
124
125
|
- lib/gql/node.rb
|
125
126
|
- lib/gql/parser.rb
|
126
127
|
- lib/gql/parser.y
|
127
|
-
- lib/gql/schema.rb
|
128
128
|
- lib/gql/tokenizer.rb
|
129
129
|
- lib/gql/tokenizer.rex
|
130
130
|
- lib/gql/version.rb
|
data/lib/gql/schema.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'singleton'
|
2
|
-
require 'forwardable'
|
3
|
-
|
4
|
-
module GQL
|
5
|
-
class Schema
|
6
|
-
include Singleton
|
7
|
-
|
8
|
-
class << self
|
9
|
-
extend Forwardable
|
10
|
-
|
11
|
-
delegate [:root, :root=, :fields] => :instance
|
12
|
-
end
|
13
|
-
|
14
|
-
attr_accessor :root
|
15
|
-
attr_reader :fields
|
16
|
-
|
17
|
-
def initialize
|
18
|
-
@fields = {}
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|