edn 1.0.8 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5ce690eba76f21cc1a8d782394d12146204dc48c
4
- data.tar.gz: 2977030dfec8f61693faaf5154638a39295a8063
3
+ metadata.gz: cd10c75b5dfef4dbd63853f1623351d545886b98
4
+ data.tar.gz: aacbe91671af6bb47f02a85e20296ea7888ea127
5
5
  SHA512:
6
- metadata.gz: 48452da36bba5bf2ca48329ea8ea4130681639faa87776189667d887f25228d2b490275c016dea7d4191f0efe3b0faaf167af7e504850e2cfe5ac1855667ec4d
7
- data.tar.gz: c76f699e5f31568281e96c0742d67935752ed8f349b84f4daf4f4bec8b0a033ebadf15a2516d803adc136ee423e69b2e2175fae335f832aaa160209c7531bd83
6
+ metadata.gz: 697d7c7414967e2c6dc07b01213738a2f7447ce4edb09f87fddd4aaee7e53f415a97cdb19c3c339c3a755f71a6c19f3cfa49c2898b312b03c5a4d06d7f5d1dff
7
+ data.tar.gz: a75e25065fde8c7e15c61751614c6d3881a92e3528ab0c0dfb18f117cff3f1fee20906cafa4fdcc2bfda51e3380b7f754c31fbdd50d5095ac25674263f4a2e7c
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in edn.gemspec
4
4
  gemspec
5
+
6
+
data/README.md CHANGED
@@ -21,6 +21,11 @@ Or install it yourself as:
21
21
 
22
22
  $ gem install edn
23
23
 
24
+
25
+ Note that you might also want to look at [edn_turbo](https://github.com/edporras/edn_turbo)
26
+ which provides a much faster EDN parser (It's written in C) with an interface that is largely compatible
27
+ with ths gem.
28
+
24
29
  ## Usage
25
30
 
26
31
  To read a string of EDN:
@@ -19,5 +19,5 @@ Gem::Specification.new do |gem|
19
19
  gem.add_development_dependency 'pry', '~> 0.9.10'
20
20
  gem.add_development_dependency 'rspec', '~> 2.11.0'
21
21
  gem.add_development_dependency 'rantly', '~> 0.3.1'
22
- gem.add_development_dependency 'rake', '~> 10.0.3'
22
+ gem.add_development_dependency 'rake', '~> 10.3'
23
23
  end
data/lib/edn.rb CHANGED
@@ -1,9 +1,11 @@
1
1
  $:.push(File.dirname(__FILE__))
2
+ require 'set'
2
3
  require 'edn/version'
3
4
  require 'edn/core_ext'
4
5
  require 'edn/types'
5
6
  require 'edn/metadata'
6
7
  require 'edn/char_stream'
8
+ require 'edn/ruby_edn_parser'
7
9
  require 'edn/parser'
8
10
  require 'edn/reader'
9
11
 
@@ -51,9 +53,17 @@ module EDN
51
53
  EDN::Type::Symbol.new(text)
52
54
  end
53
55
 
54
- def self.list(*values)
56
+ def self.list(values)
55
57
  EDN::Type::List.new(*values)
56
58
  end
59
+
60
+ def self.set(*elems)
61
+ Set.new(*elems)
62
+ end
63
+
64
+ def self.big_decimal(str)
65
+ BigDecimal.new(str)
66
+ end
57
67
  end
58
68
 
59
69
  EDN.register("inst") do |value|
@@ -63,3 +73,4 @@ end
63
73
  EDN.register("uuid") do |value|
64
74
  EDN::Type::UUID.new(value)
65
75
  end
76
+
@@ -3,6 +3,16 @@ require 'set'
3
3
 
4
4
 
5
5
  module EDN
6
+ Parser = RubyEdnParser
7
+ @parser_class = RubyEdnParser
8
+
9
+ def self.parser=(p)
10
+ @parser_class = p
11
+ end
12
+
13
+ def self.new_parser(*args)
14
+ @parser_class.new(*args)
15
+ end
6
16
 
7
17
  # Object returned when there is nothing to return
8
18
 
@@ -79,265 +89,4 @@ module EDN
79
89
  EDN::Type::Unknown.new(tag, element)
80
90
  end
81
91
  end
82
-
83
- class Parser
84
- def initialize(source, *extra)
85
- io = source.instance_of?(String) ? StringIO.new(source) : source
86
- @s = CharStream.new(io)
87
- end
88
-
89
- def read(return_nothing=false)
90
- meta = read_meta
91
- value = read_basic(return_nothing)
92
- if meta && value != NOTHING
93
- value.extend EDN::Metadata
94
- value.metadata = meta
95
- end
96
- value
97
- end
98
-
99
- def eof?
100
- @s.eof?
101
- end
102
-
103
- def unknown
104
- raise "Don't know what to do with #{@s.current} #{@s.current.class}"
105
- end
106
-
107
- def read_eof
108
- EOF
109
- end
110
-
111
- def read_char
112
- result = @s.advance
113
- @s.advance
114
- until @s.eof?
115
- break unless @s.digit? || @s.alpha?
116
- result += @s.current
117
- @s.advance
118
- end
119
-
120
- return result if result.size == 1
121
-
122
- case result
123
- when 'newline'
124
- "\n"
125
- when 'return'
126
- "\r"
127
- when 'tab'
128
- "\t"
129
- when 'space'
130
- " "
131
- else
132
- raise "Unknown char #{result}"
133
- end
134
- end
135
-
136
- def read_slash
137
- @s.advance
138
- Type::Symbol.new('/')
139
- end
140
-
141
- def read_number_or_symbol
142
- leading = @s.current
143
- @s.advance
144
- return read_number(leading) if @s.digit?
145
- read_symbol(leading)
146
- end
147
-
148
- def read_symbol_chars
149
- result = ''
150
-
151
- ch = @s.current
152
- while SYMBOL_INTERIOR_CHARS.include?(ch)
153
- result << ch
154
- ch = @s.advance
155
- end
156
- return result unless @s.skip_past('/')
157
-
158
- result << '/'
159
- ch = @s.current
160
- while SYMBOL_INTERIOR_CHARS.include?(ch)
161
- result << ch
162
- ch = @s.advance
163
- end
164
-
165
- result
166
- end
167
-
168
- def read_extension
169
- @s.advance
170
- if @s.current == '{'
171
- @s.advance
172
- read_collection(Set, '}')
173
- elsif @s.current == "_"
174
- @s.advance
175
- x = read
176
- NOTHING
177
- else
178
- tag = read_symbol_chars
179
- value = read
180
- EDN.tagged_element(tag, value)
181
- end
182
- end
183
-
184
- def read_symbol(leading='')
185
- token = leading + read_symbol_chars
186
- return true if token == "true"
187
- return false if token == "false"
188
- return nil if token == "nil"
189
- Type::Symbol.new(token)
190
- end
191
-
192
- def read_keyword
193
- @s.advance
194
- read_symbol_chars.to_sym
195
- end
196
-
197
- def escape_char(ch)
198
- return '\\' if ch == '\\'
199
- return "\n" if ch == 'n'
200
- return "\t" if ch == 't'
201
- return "\r" if ch == 'r'
202
- ch
203
- end
204
-
205
- def read_string
206
- @s.advance
207
-
208
- result = ''
209
- until @s.current == '"'
210
- raise "Unexpected eof" if @s.eof?
211
- if @s.current == '\\'
212
- @s.advance
213
- result << escape_char(@s.current)
214
- else
215
- result << @s.current
216
- end
217
- @s.advance
218
- end
219
- @s.advance
220
- result
221
- end
222
-
223
- def call_reader(reader)
224
- if reader.instance_of? Symbol
225
- self.send(reader)
226
- else
227
- self.instance_exec(&reader)
228
- end
229
- end
230
-
231
- def read_basic(return_nothing=false)
232
- @s.skip_ws
233
- ch = @s.current
234
- result = call_reader(READERS[ch])
235
- while NOTHING.equal?(result) && !return_nothing
236
- @s.skip_ws
237
- result = call_reader(READERS[@s.current])
238
- end
239
-
240
- result
241
- end
242
-
243
- def read_digits(min_digits=0)
244
- result = ''
245
-
246
- if @s.current == '+' || @s.current == '-'
247
- result << @s.current
248
- @s.advance
249
- end
250
-
251
- n_digits = 0
252
- while @s.current =~ /[0-9]/
253
- n_digits += 1
254
- result << @s.current
255
- @s.advance
256
- end
257
-
258
- raise "Expected at least #{min_digits} digits, found #{result}" unless n_digits >= min_digits
259
- result
260
- end
261
-
262
- def finish_float(whole_part)
263
- result = whole_part
264
-
265
- if @s.current == '.'
266
- result += '.'
267
- @s.advance
268
- result = @s.digit? ? result + read_digits : result + '0'
269
- #puts "aaa: #{result}"
270
- end
271
-
272
- if @s.current == 'e' || @s.current == 'E'
273
- @s.advance
274
- result = result + 'e' + read_digits
275
- #puts "bbb: #{result}"
276
- end
277
- #puts result
278
- result.to_f
279
- end
280
-
281
- def read_number(leading='')
282
- result = leading + read_digits
283
-
284
- if %w{. e E}.include? @s.current
285
- return finish_float(result)
286
- elsif @s.skip_past('M') || @s.skip_past('N')
287
- result.to_i
288
- else
289
- result.to_i
290
- end
291
- end
292
-
293
- def read_meta
294
- raw_metadata = []
295
- @s.skip_ws
296
- while @s.current == '^'
297
- @s.advance
298
- raw_metadata << read_basic
299
- @s.skip_ws
300
- end
301
-
302
- metadata = raw_metadata.reverse.reduce({}) do |acc, m|
303
- case m
304
- when Symbol then acc.merge(m => true)
305
- when EDN::Type::Symbol then acc.merge(:tag => m)
306
- else acc.merge(m)
307
- end
308
- end
309
- metadata.empty? ? nil : metadata
310
- end
311
-
312
- def read_list
313
- @s.advance
314
- read_collection(EDN::Type::List, ')')
315
- end
316
-
317
- def read_vector
318
- @s.advance
319
- read_collection(Array, ']')
320
- end
321
-
322
- def read_map
323
- @s.advance
324
- array = read_collection(Array, '}')
325
- raise "Need an even number of items for a map" unless array.count.even?
326
- Hash[*array]
327
- end
328
-
329
- def read_collection(clazz, closing)
330
- result = clazz.new
331
-
332
- while true
333
- @s.skip_ws
334
- raise "Unexpected eof" if @s.eof?
335
- break if @s.current == closing
336
- next_value = read(true)
337
- result << next_value unless next_value == NOTHING
338
- end
339
- @s.advance
340
- result
341
- end
342
- end
343
92
  end
@@ -2,7 +2,7 @@ module EDN
2
2
  class Reader
3
3
 
4
4
  def initialize(source)
5
- @parser = Parser.new(source)
5
+ @parser = EDN.new_parser(source)
6
6
  end
7
7
 
8
8
  def read(eof_value = NOTHING)
@@ -0,0 +1,266 @@
1
+ require 'stringio'
2
+ require 'set'
3
+
4
+
5
+ module EDN
6
+ class RubyEdnParser
7
+ def initialize(source, *extra)
8
+ io = source.instance_of?(String) ? StringIO.new(source) : source
9
+ @s = CharStream.new(io)
10
+ end
11
+
12
+ def read(return_nothing=false)
13
+ meta = read_meta
14
+ value = read_basic(return_nothing)
15
+ if meta && value != NOTHING
16
+ value.extend EDN::Metadata
17
+ value.metadata = meta
18
+ end
19
+ value
20
+ end
21
+
22
+ def eof?
23
+ @s.eof?
24
+ end
25
+
26
+ def unknown
27
+ raise "Don't know what to do with #{@s.current} #{@s.current.class}"
28
+ end
29
+
30
+ def read_eof
31
+ EOF
32
+ end
33
+
34
+ def read_char
35
+ result = @s.advance
36
+ @s.advance
37
+ until @s.eof?
38
+ break unless @s.digit? || @s.alpha?
39
+ result += @s.current
40
+ @s.advance
41
+ end
42
+
43
+ return result if result.size == 1
44
+
45
+ case result
46
+ when 'newline'
47
+ "\n"
48
+ when 'return'
49
+ "\r"
50
+ when 'tab'
51
+ "\t"
52
+ when 'space'
53
+ " "
54
+ else
55
+ raise "Unknown char #{result}"
56
+ end
57
+ end
58
+
59
+ def read_slash
60
+ @s.advance
61
+ Type::Symbol.new('/')
62
+ end
63
+
64
+ def read_number_or_symbol
65
+ leading = @s.current
66
+ @s.advance
67
+ return read_number(leading) if @s.digit?
68
+ read_symbol(leading)
69
+ end
70
+
71
+ def read_symbol_chars
72
+ result = ''
73
+
74
+ ch = @s.current
75
+ while SYMBOL_INTERIOR_CHARS.include?(ch)
76
+ result << ch
77
+ ch = @s.advance
78
+ end
79
+ return result unless @s.skip_past('/')
80
+
81
+ result << '/'
82
+ ch = @s.current
83
+ while SYMBOL_INTERIOR_CHARS.include?(ch)
84
+ result << ch
85
+ ch = @s.advance
86
+ end
87
+
88
+ result
89
+ end
90
+
91
+ def read_extension
92
+ @s.advance
93
+ if @s.current == '{'
94
+ @s.advance
95
+ read_collection(Set, '}')
96
+ elsif @s.current == "_"
97
+ @s.advance
98
+ x = read
99
+ NOTHING
100
+ else
101
+ tag = read_symbol_chars
102
+ value = read
103
+ EDN.tagged_element(tag, value)
104
+ end
105
+ end
106
+
107
+ def read_symbol(leading='')
108
+ token = leading + read_symbol_chars
109
+ return true if token == "true"
110
+ return false if token == "false"
111
+ return nil if token == "nil"
112
+ Type::Symbol.new(token)
113
+ end
114
+
115
+ def read_keyword
116
+ @s.advance
117
+ read_symbol_chars.to_sym
118
+ end
119
+
120
+ def escape_char(ch)
121
+ return '\\' if ch == '\\'
122
+ return "\n" if ch == 'n'
123
+ return "\t" if ch == 't'
124
+ return "\r" if ch == 'r'
125
+ ch
126
+ end
127
+
128
+ def read_string
129
+ @s.advance
130
+
131
+ result = ''
132
+ until @s.current == '"'
133
+ raise "Unexpected eof" if @s.eof?
134
+ if @s.current == '\\'
135
+ @s.advance
136
+ result << escape_char(@s.current)
137
+ else
138
+ result << @s.current
139
+ end
140
+ @s.advance
141
+ end
142
+ @s.advance
143
+ result
144
+ end
145
+
146
+ def call_reader(reader)
147
+ if reader.instance_of? Symbol
148
+ self.send(reader)
149
+ else
150
+ self.instance_exec(&reader)
151
+ end
152
+ end
153
+
154
+ def read_basic(return_nothing=false)
155
+ @s.skip_ws
156
+ ch = @s.current
157
+ result = call_reader(READERS[ch])
158
+ while NOTHING.equal?(result) && !return_nothing
159
+ @s.skip_ws
160
+ result = call_reader(READERS[@s.current])
161
+ end
162
+
163
+ result
164
+ end
165
+
166
+ def read_digits(min_digits=0)
167
+ result = ''
168
+
169
+ if @s.current == '+' || @s.current == '-'
170
+ result << @s.current
171
+ @s.advance
172
+ end
173
+
174
+ n_digits = 0
175
+ while @s.current =~ /[0-9]/
176
+ n_digits += 1
177
+ result << @s.current
178
+ @s.advance
179
+ end
180
+
181
+ raise "Expected at least #{min_digits} digits, found #{result}" unless n_digits >= min_digits
182
+ result
183
+ end
184
+
185
+ def finish_float(whole_part)
186
+ result = whole_part
187
+
188
+ if @s.current == '.'
189
+ result += '.'
190
+ @s.advance
191
+ result = @s.digit? ? result + read_digits : result + '0'
192
+ #puts "aaa: #{result}"
193
+ end
194
+
195
+ if @s.current == 'e' || @s.current == 'E'
196
+ @s.advance
197
+ result = result + 'e' + read_digits
198
+ #puts "bbb: #{result}"
199
+ end
200
+ #puts result
201
+ result.to_f
202
+ end
203
+
204
+ def read_number(leading='')
205
+ result = leading + read_digits
206
+
207
+ if %w{. e E}.include? @s.current
208
+ return finish_float(result)
209
+ elsif @s.skip_past('M') || @s.skip_past('N')
210
+ result.to_i
211
+ else
212
+ result.to_i
213
+ end
214
+ end
215
+
216
+ def read_meta
217
+ raw_metadata = []
218
+ @s.skip_ws
219
+ while @s.current == '^'
220
+ @s.advance
221
+ raw_metadata << read_basic
222
+ @s.skip_ws
223
+ end
224
+
225
+ metadata = raw_metadata.reverse.reduce({}) do |acc, m|
226
+ case m
227
+ when Symbol then acc.merge(m => true)
228
+ when EDN::Type::Symbol then acc.merge(:tag => m)
229
+ else acc.merge(m)
230
+ end
231
+ end
232
+ metadata.empty? ? nil : metadata
233
+ end
234
+
235
+ def read_list
236
+ @s.advance
237
+ read_collection(EDN::Type::List, ')')
238
+ end
239
+
240
+ def read_vector
241
+ @s.advance
242
+ read_collection(Array, ']')
243
+ end
244
+
245
+ def read_map
246
+ @s.advance
247
+ array = read_collection(Array, '}')
248
+ raise "Need an even number of items for a map" unless array.count.even?
249
+ Hash[*array]
250
+ end
251
+
252
+ def read_collection(clazz, closing)
253
+ result = clazz.new
254
+
255
+ while true
256
+ @s.skip_ws
257
+ raise "Unexpected eof" if @s.eof?
258
+ break if @s.current == closing
259
+ next_value = read(true)
260
+ result << next_value unless next_value == NOTHING
261
+ end
262
+ @s.advance
263
+ result
264
+ end
265
+ end
266
+ end
@@ -1,3 +1,3 @@
1
1
  module EDN
2
- VERSION = "1.0.8"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe EDN::Parser do
3
+ describe 'edn_parser' do
4
4
  include RantlyHelpers
5
5
 
6
- let(:parser) { EDN::Parser.new }
6
+ let(:parser) { EDN.new_parser }
7
7
 
8
8
  it "can contain comments" do
9
9
  edn = ";; This is some sample data\n[1 2 ;; the first two values\n3]"
@@ -27,28 +27,28 @@ describe EDN do
27
27
 
28
28
 
29
29
  context "#read" do
30
- it "reads from a stream" do
31
- io = StringIO.new("123")
32
- EDN.read(io).should == 123
33
- end
30
+ #it "reads from a stream" do
31
+ # io = StringIO.new("123")
32
+ # EDN.read(io).should == 123
33
+ #end
34
34
 
35
- it "reads mutiple values from a stream" do
36
- io = StringIO.new("123 456 789")
37
- EDN.read(io).should == 123
38
- EDN.read(io).should == 456
39
- EDN.read(io).should == 789
40
- end
35
+ #it "reads mutiple values from a stream" do
36
+ # io = StringIO.new("123 456 789")
37
+ # EDN.read(io).should == 123
38
+ # EDN.read(io).should == 456
39
+ # EDN.read(io).should == 789
40
+ #end
41
41
 
42
42
  it "raises an exception on eof by default" do
43
43
  expect { EDN.read('') }.to raise_error
44
44
  end
45
45
 
46
- it "allows you to specify an eof value" do
47
- io = StringIO.new("123 456")
48
- EDN.read(io, :my_eof).should == 123
49
- EDN.read(io, :my_eof).should == 456
50
- EDN.read(io, :my_eof).should == :my_eof
51
- end
46
+ #it "allows you to specify an eof value" do
47
+ # io = StringIO.new("123 456")
48
+ # EDN.read(io, :my_eof).should == 123
49
+ # EDN.read(io, :my_eof).should == 456
50
+ # EDN.read(io, :my_eof).should == :my_eof
51
+ #end
52
52
 
53
53
  it "allows you to specify nil as an eof value" do
54
54
  EDN.read("", nil).should == nil
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: edn
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.8
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clinton N. Dreisbach & Russ Olsen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-15 00:00:00.000000000 Z
11
+ date: 2015-08-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 10.0.3
61
+ version: '10.3'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 10.0.3
68
+ version: '10.3'
69
69
  description: "'edn implements a reader for Extensible Data Notation by Rich Hickey.'"
70
70
  email:
71
71
  - russ@russolsen.com
@@ -87,6 +87,7 @@ files:
87
87
  - lib/edn/metadata.rb
88
88
  - lib/edn/parser.rb
89
89
  - lib/edn/reader.rb
90
+ - lib/edn/ruby_edn_parser.rb
90
91
  - lib/edn/type/list.rb
91
92
  - lib/edn/type/symbol.rb
92
93
  - lib/edn/type/unknown.rb