edn 1.0.8 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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