edn_turbo 0.5.7 → 0.6.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 +5 -5
- data/.rspec +1 -0
- data/CHANGELOG.md +15 -0
- data/Dockerfile +34 -0
- data/LICENSE +1 -1
- data/README.md +8 -22
- data/Rakefile +22 -19
- data/bin/build_docker_image.sh +11 -0
- data/bin/console.sh +5 -0
- data/docker-compose.yml +10 -0
- data/ext/edn_turbo/edn_parser.cc +336 -314
- data/ext/edn_turbo/edn_parser.rl +63 -41
- data/ext/edn_turbo/extconf.rb +24 -1
- data/ext/edn_turbo/main.cc +189 -166
- data/ext/edn_turbo/parser.h +104 -76
- data/ext/edn_turbo/parser_def.cc +204 -182
- data/ext/edn_turbo/util.cc +241 -219
- data/ext/edn_turbo/util.h +48 -26
- data/ext/edn_turbo/util_unicode.cc +41 -19
- data/ext/edn_turbo/util_unicode.h +29 -7
- data/lib/edn_turbo.rb +22 -0
- data/lib/edn_turbo/edn_parser.rb +22 -0
- data/lib/edn_turbo/version.rb +23 -3
- data/spec/edn_turbo/edn_parser_spec.rb +384 -0
- data/spec/spec_helper.rb +96 -0
- metadata +42 -11
- data/test/test_output_diff.rb +0 -408
data/ext/edn_turbo/util.h
CHANGED
@@ -1,39 +1,61 @@
|
|
1
|
+
// The MIT License (MIT)
|
2
|
+
|
3
|
+
// Copyright (c) 2015-2019 Ed Porras
|
4
|
+
|
5
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
// of this software and associated documentation files (the "Software"), to deal
|
7
|
+
// in the Software without restriction, including without limitation the rights
|
8
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
// copies of the Software, and to permit persons to whom the Software is
|
10
|
+
// furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
// The above copyright notice and this permission notice shall be included in
|
13
|
+
// all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
// THE SOFTWARE.
|
22
|
+
|
1
23
|
#pragma once
|
2
24
|
|
3
25
|
namespace edn
|
4
26
|
{
|
5
|
-
|
6
|
-
|
27
|
+
extern VALUE rb_mEDN;
|
28
|
+
extern VALUE rb_mEDNT;
|
7
29
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
30
|
+
extern VALUE EDN_MAKE_SYMBOL_METHOD;
|
31
|
+
extern VALUE EDN_MAKE_LIST_METHOD;
|
32
|
+
extern VALUE EDN_MAKE_SET_METHOD;
|
33
|
+
extern VALUE EDN_MAKE_BIG_DECIMAL_METHOD;
|
34
|
+
extern VALUE EDN_TAGGED_ELEM_METHOD;
|
35
|
+
extern VALUE EDN_EOF_CONST;
|
14
36
|
|
15
|
-
|
37
|
+
extern VALUE EDNT_EXTENDED_VALUE_METHOD;
|
16
38
|
|
17
|
-
|
18
|
-
|
19
|
-
|
39
|
+
extern VALUE RUBY_STRING_TO_I_METHOD;
|
40
|
+
extern VALUE RUBY_STRING_TO_F_METHOD;
|
41
|
+
extern VALUE RUBY_READ_METHOD;
|
20
42
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
43
|
+
namespace util
|
44
|
+
{
|
45
|
+
// defined in edn_parser_util.cc
|
46
|
+
VALUE integer_to_ruby(const char* str, std::size_t len);
|
47
|
+
VALUE float_to_ruby (const char* str, std::size_t len);
|
26
48
|
|
27
|
-
|
49
|
+
VALUE ruby_io_read(VALUE io);
|
28
50
|
|
29
|
-
|
30
|
-
|
51
|
+
bool parse_byte_stream (const char *p, const char *pe, VALUE& rslt, bool encode);
|
52
|
+
bool parse_escaped_char(const char *p, const char *pe, VALUE& rslt);
|
31
53
|
|
32
|
-
|
33
|
-
|
34
|
-
|
54
|
+
VALUE call_module_fn(VALUE module, ID method);
|
55
|
+
VALUE call_module_fn(VALUE module, ID method, VALUE value);
|
56
|
+
VALUE call_module_fn(VALUE module, ID method, VALUE value1, VALUE value2);
|
35
57
|
|
36
|
-
|
37
|
-
|
38
|
-
|
58
|
+
// edn_parser_util_unicode.cc
|
59
|
+
bool to_utf8(const char *s, uint32_t len, std::string& rslt);
|
60
|
+
}
|
39
61
|
}
|
@@ -1,3 +1,25 @@
|
|
1
|
+
// The MIT License (MIT)
|
2
|
+
|
3
|
+
// Copyright (c) 2015-2019 Ed Porras
|
4
|
+
|
5
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
// of this software and associated documentation files (the "Software"), to deal
|
7
|
+
// in the Software without restriction, including without limitation the rights
|
8
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
// copies of the Software, and to permit persons to whom the Software is
|
10
|
+
// furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
// The above copyright notice and this permission notice shall be included in
|
13
|
+
// all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
// THE SOFTWARE.
|
22
|
+
|
1
23
|
#include <string>
|
2
24
|
|
3
25
|
//
|
@@ -13,24 +35,24 @@
|
|
13
35
|
|
14
36
|
namespace edn
|
15
37
|
{
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
}
|
30
|
-
|
31
|
-
ustr.unescape().toUTF8String(rslt);
|
32
|
-
return true;
|
38
|
+
namespace util
|
39
|
+
{
|
40
|
+
namespace unicode
|
41
|
+
{
|
42
|
+
//
|
43
|
+
// unescapes any values that need to be replaced, saves it to utf8
|
44
|
+
//
|
45
|
+
bool to_utf8(const char *s, uint32_t len, std::string& rslt)
|
46
|
+
{
|
47
|
+
icu::UnicodeString ustr(s, len);
|
48
|
+
|
49
|
+
if (ustr.isBogus()) {
|
50
|
+
return false;
|
33
51
|
}
|
34
|
-
|
35
|
-
|
52
|
+
|
53
|
+
ustr.unescape().toUTF8String(rslt);
|
54
|
+
return true;
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
36
58
|
}
|
@@ -1,14 +1,36 @@
|
|
1
|
+
// The MIT License (MIT)
|
2
|
+
|
3
|
+
// Copyright (c) 2015-2019 Ed Porras
|
4
|
+
|
5
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
// of this software and associated documentation files (the "Software"), to deal
|
7
|
+
// in the Software without restriction, including without limitation the rights
|
8
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
// copies of the Software, and to permit persons to whom the Software is
|
10
|
+
// furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
// The above copyright notice and this permission notice shall be included in
|
13
|
+
// all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
// THE SOFTWARE.
|
22
|
+
|
1
23
|
#pragma once
|
2
24
|
|
3
25
|
#include <string>
|
4
26
|
|
5
27
|
namespace edn
|
6
28
|
{
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
29
|
+
namespace util
|
30
|
+
{
|
31
|
+
namespace unicode
|
32
|
+
{
|
33
|
+
bool to_utf8(const char *s, uint32_t len, std::string& rslt);
|
34
|
+
}
|
35
|
+
}
|
14
36
|
}
|
data/lib/edn_turbo.rb
CHANGED
@@ -1,5 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# The MIT License (MIT)
|
4
|
+
#
|
5
|
+
# Copyright (c) 2015-2019 Ed Porras
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in
|
15
|
+
# all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
# THE SOFTWARE.
|
24
|
+
|
3
25
|
require 'edn'
|
4
26
|
require 'edn_turbo/version'
|
5
27
|
require 'edn_turbo/edn_parser'
|
data/lib/edn_turbo/edn_parser.rb
CHANGED
@@ -1,5 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# The MIT License (MIT)
|
4
|
+
#
|
5
|
+
# Copyright (c) 2015-2019 Ed Porras
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in
|
15
|
+
# all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
# THE SOFTWARE.
|
24
|
+
|
3
25
|
#
|
4
26
|
# methods specific to edn_turbo
|
5
27
|
module EDNT
|
data/lib/edn_turbo/version.rb
CHANGED
@@ -1,6 +1,26 @@
|
|
1
|
-
#
|
1
|
+
# The MIT License (MIT)
|
2
|
+
#
|
3
|
+
# Copyright (c) 2015-2019 Ed Porras
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
# THE SOFTWARE.
|
2
22
|
|
3
23
|
module EDNT
|
4
|
-
VERSION = '0.
|
5
|
-
RELEASE_DATE = '2019-
|
24
|
+
VERSION = '0.6.0'.freeze
|
25
|
+
RELEASE_DATE = '2019-05-13'.freeze
|
6
26
|
end
|
@@ -0,0 +1,384 @@
|
|
1
|
+
require 'edn_turbo'
|
2
|
+
require 'pry-byebug'
|
3
|
+
|
4
|
+
module EDNT
|
5
|
+
RSpec.describe Parser do
|
6
|
+
let(:subject) { described_class.new }
|
7
|
+
|
8
|
+
def fixture_path(*fixture_filename)
|
9
|
+
File.join(__dir__, '../fixtures', fixture_filename)
|
10
|
+
end
|
11
|
+
|
12
|
+
def fixture(*fixture_filename)
|
13
|
+
File.read(fixture_path(fixture_filename))
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'setting input' do
|
17
|
+
it 'File' do
|
18
|
+
io = File.open(fixture_path('true.edn'))
|
19
|
+
expect(io.class).to eq(File)
|
20
|
+
subject.set_input(io)
|
21
|
+
expect(subject.read).to eq(true)
|
22
|
+
end
|
23
|
+
it 'String' do
|
24
|
+
io = File.read(fixture_path('true.edn'))
|
25
|
+
expect(io.class).to eq(String)
|
26
|
+
subject.set_input(io)
|
27
|
+
expect(subject.read).to eq(true)
|
28
|
+
end
|
29
|
+
it 'IO that responds to read' do
|
30
|
+
io = StringIO.new(fixture('true.edn'))
|
31
|
+
expect(io.respond_to?('read')).to be_truthy
|
32
|
+
subject.set_input(io)
|
33
|
+
io.rewind
|
34
|
+
expect(subject.read).to eq(true)
|
35
|
+
end
|
36
|
+
it 'raises ArgumentError if IO input does not respond to read()' do
|
37
|
+
expect { subject.set_input(4) }.to raise_error(ArgumentError)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'comments' do
|
42
|
+
it 'semicolon' do
|
43
|
+
data = <<-EDN
|
44
|
+
; ignore me
|
45
|
+
23 ; ignore me too
|
46
|
+
EDN
|
47
|
+
expect(subject.parse(data)).to eq(23)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'built-in keywords' do
|
52
|
+
it 'true' do
|
53
|
+
expect(subject.parse('true')).to eq(true)
|
54
|
+
expect(subject.parse(' true ')).to eq(true)
|
55
|
+
end
|
56
|
+
it 'false' do
|
57
|
+
expect(subject.parse('false')).to eq(false)
|
58
|
+
expect(subject.parse(' false ')).to eq(false)
|
59
|
+
end
|
60
|
+
it 'nil' do
|
61
|
+
expect(subject.parse('nil')).to eq(nil)
|
62
|
+
expect(subject.parse(' nil')).to eq(nil)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'escaped character keywords' do
|
67
|
+
it 'formfeed' do
|
68
|
+
expect(subject.parse('\formfeed')).to eq("\f")
|
69
|
+
end
|
70
|
+
it 'space' do
|
71
|
+
expect(subject.parse('\space')).to eq(' ')
|
72
|
+
end
|
73
|
+
it 'newline' do
|
74
|
+
expect(subject.parse('\newline')).to eq("\n")
|
75
|
+
end
|
76
|
+
it 'tab' do
|
77
|
+
expect(subject.parse('\tab')).to eq("\t")
|
78
|
+
end
|
79
|
+
it 'return' do
|
80
|
+
expect(subject.parse('\return')).to eq("\r")
|
81
|
+
end
|
82
|
+
it 'backspace' do
|
83
|
+
expect(subject.parse('\backspace')).to eq("\b")
|
84
|
+
end
|
85
|
+
# it 'verticaltab' do
|
86
|
+
# expect(subject.parse('\verticaltab')).to eq("\v")
|
87
|
+
# end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'strings' do
|
91
|
+
it 'simple' do
|
92
|
+
expect(subject.parse(' "abc" ')).to eq('abc')
|
93
|
+
end
|
94
|
+
it 'with unicode' do
|
95
|
+
test_file = fixture('string.edn')
|
96
|
+
expect(subject.parse(test_file)).to eq("abc\"➪舦")
|
97
|
+
end
|
98
|
+
it 'with unicode in ascii range' do
|
99
|
+
test_file = fixture('unicode.edn')
|
100
|
+
expect(subject.parse(test_file)).to eq("Page \u0018,")
|
101
|
+
end
|
102
|
+
it 'with escaped characters' do
|
103
|
+
test_file = fixture('escaped_string.edn')
|
104
|
+
expect(subject.parse(test_file)).to eq("this\tis\\only\ta\ttest\rof\"various\nescaped\\values")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'keywords' do
|
109
|
+
it 'basic' do
|
110
|
+
expect(subject.parse(' :key1 ')).to eq(:key1)
|
111
|
+
end
|
112
|
+
it 'with underscore' do
|
113
|
+
expect(subject.parse(' :key_3 ')).to eq(:key_3)
|
114
|
+
end
|
115
|
+
it 'with dash' do
|
116
|
+
expect(subject.parse(' :key-4 ')).to eq(:'key-4')
|
117
|
+
end
|
118
|
+
it 'with namespace' do
|
119
|
+
expect(subject.parse(':key_2/adsd2')).to eq(:"key_2/adsd2")
|
120
|
+
end
|
121
|
+
it 'with long namespace' do
|
122
|
+
expect(subject.parse(' :namespace.of.some_length/keyword-name ')).to eq(:"namespace.of.some_length/keyword-name")
|
123
|
+
end
|
124
|
+
it 'with #' do
|
125
|
+
expect(subject.parse(' :#/:a ')).to eq(:'#/:a')
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'numbers' do
|
130
|
+
it 'zero' do
|
131
|
+
expect(subject.parse(' 0 ')).to eq(0)
|
132
|
+
end
|
133
|
+
it 'neg zero' do
|
134
|
+
expect(subject.parse(' -0 ')).to eq(-0)
|
135
|
+
end
|
136
|
+
it 'integer' do
|
137
|
+
expect(subject.parse(' 5 ')).to eq(5)
|
138
|
+
end
|
139
|
+
it 'positive integer' do
|
140
|
+
expect(subject.parse(' +5 ')).to eq(5)
|
141
|
+
end
|
142
|
+
it 'negative integer' do
|
143
|
+
expect(subject.parse(' -98798 ')).to eq(-98_798)
|
144
|
+
end
|
145
|
+
it 'decimal' do
|
146
|
+
expect(subject.parse(' 231.312 ')).to eq(231.312)
|
147
|
+
end
|
148
|
+
it 'positive decimal' do
|
149
|
+
expect(subject.parse(' +231.312 ')).to eq(231.312)
|
150
|
+
end
|
151
|
+
it 'negative decimal' do
|
152
|
+
expect(subject.parse(' -2321.0 ')).to eq(-2321.0)
|
153
|
+
end
|
154
|
+
it 'scientific notation with E' do
|
155
|
+
val = subject.parse('2.74877906944E11')
|
156
|
+
expect(val).to eq(274_877_906_944.0)
|
157
|
+
expect(val.class).to eq(Float)
|
158
|
+
end
|
159
|
+
it 'scientific notation with e' do
|
160
|
+
val = subject.parse('2.74877906944e11')
|
161
|
+
expect(val).to eq(274_877_906_944.0)
|
162
|
+
expect(val.class).to eq(Float)
|
163
|
+
end
|
164
|
+
it 'scientific notation with E-' do
|
165
|
+
val = subject.parse('1.35E-12')
|
166
|
+
expect(val).to eq(1.35e-12)
|
167
|
+
expect(val.class).to eq(Float)
|
168
|
+
end
|
169
|
+
it 'scientific notation with e-' do
|
170
|
+
val = subject.parse('1.35e-12')
|
171
|
+
expect(val).to eq(1.35e-12)
|
172
|
+
expect(val.class).to eq(Float)
|
173
|
+
end
|
174
|
+
it 'arbitrary precision integer' do
|
175
|
+
val = subject.parse(' 432N ')
|
176
|
+
expect(val).to eq(432)
|
177
|
+
expect(val.class).to eq(Integer)
|
178
|
+
end
|
179
|
+
it 'exact precision decimal' do
|
180
|
+
val = subject.parse(' 12M ')
|
181
|
+
expect(val).to eq(12)
|
182
|
+
expect(val.class).to eq(Integer)
|
183
|
+
end
|
184
|
+
# TODO: fix?
|
185
|
+
# it 'exact precision scientific notation' do
|
186
|
+
# val = subject.parse('45.4e+43M')
|
187
|
+
# expect(val).to eq(4.54e+44)
|
188
|
+
# expect(val.class).to eq(Float)
|
189
|
+
# end
|
190
|
+
end
|
191
|
+
|
192
|
+
context 'operators' do
|
193
|
+
it '/' do
|
194
|
+
expect(subject.parse('/')).to eq(EDN::Type::Symbol.new('/'))
|
195
|
+
end
|
196
|
+
it '.' do
|
197
|
+
expect(subject.parse('.')).to eq(EDN::Type::Symbol.new('.'))
|
198
|
+
end
|
199
|
+
it '*' do
|
200
|
+
expect(subject.parse('*')).to eq(EDN::Type::Symbol.new('*'))
|
201
|
+
end
|
202
|
+
it '!' do
|
203
|
+
expect(subject.parse('!')).to eq(EDN::Type::Symbol.new('!'))
|
204
|
+
end
|
205
|
+
it '_' do
|
206
|
+
expect(subject.parse('_')).to eq(EDN::Type::Symbol.new('_'))
|
207
|
+
end
|
208
|
+
it '?' do
|
209
|
+
expect(subject.parse('?')).to eq(EDN::Type::Symbol.new('?'))
|
210
|
+
end
|
211
|
+
it '$' do
|
212
|
+
expect(subject.parse('$')).to eq(EDN::Type::Symbol.new('$'))
|
213
|
+
end
|
214
|
+
it '%' do
|
215
|
+
expect(subject.parse('%')).to eq(EDN::Type::Symbol.new('%'))
|
216
|
+
end
|
217
|
+
it '>' do
|
218
|
+
expect(subject.parse('>')).to eq(EDN::Type::Symbol.new('>'))
|
219
|
+
end
|
220
|
+
it '<' do
|
221
|
+
expect(subject.parse('<')).to eq(EDN::Type::Symbol.new('<'))
|
222
|
+
end
|
223
|
+
it '&' do
|
224
|
+
expect(subject.parse('&')).to eq(EDN::Type::Symbol.new('&'))
|
225
|
+
end
|
226
|
+
it '=' do
|
227
|
+
expect(subject.parse('=')).to eq(EDN::Type::Symbol.new('='))
|
228
|
+
end
|
229
|
+
it '-' do
|
230
|
+
expect(subject.parse('-')).to eq(EDN::Type::Symbol.new('-'))
|
231
|
+
end
|
232
|
+
it '+' do
|
233
|
+
expect(subject.parse('+')).to eq(EDN::Type::Symbol.new('+'))
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
context 'built-in tagged' do
|
238
|
+
it 'rfc3339 dates' do
|
239
|
+
test = [
|
240
|
+
' #inst "1985-04-12T23:20:50.52Z" ',
|
241
|
+
' #inst "1996-12-19T16:39:57-08:00" ',
|
242
|
+
' #inst "1990-12-31T23:59:60Z" ',
|
243
|
+
' #inst "1990-12-31T15:59:60-08:00" ',
|
244
|
+
' #inst "1937-01-01T12:00:27.87+00:20" '
|
245
|
+
]
|
246
|
+
|
247
|
+
expected = [
|
248
|
+
DateTime.rfc3339('1985-04-12T23:20:50.52Z'),
|
249
|
+
DateTime.rfc3339('1996-12-19T16:39:57-08:00'),
|
250
|
+
DateTime.rfc3339('1990-12-31T23:59:60Z'),
|
251
|
+
DateTime.rfc3339('1990-12-31T15:59:60-08:00'),
|
252
|
+
DateTime.rfc3339('1937-01-01T12:00:27.87+00:20')
|
253
|
+
]
|
254
|
+
|
255
|
+
test.each_with_index do |str, i|
|
256
|
+
expect(subject.parse(str)).to eq(expected[i])
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'uuid' do
|
261
|
+
expect(subject.parse(' #uuid "f81d4fae-7dec-11d0-a765-00a0c91e6bf6" ')).to eq('f81d4fae-7dec-11d0-a765-00a0c91e6bf6')
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
context 'collections' do
|
266
|
+
it 'empty set' do
|
267
|
+
expect(subject.parse(' #{} ')).to eq(Set.new)
|
268
|
+
end
|
269
|
+
it 'single-element set' do
|
270
|
+
expect(subject.parse(' #{ 1 } ')).to eq(Set.new([1]))
|
271
|
+
end
|
272
|
+
it 'multi-element set' do
|
273
|
+
expect(subject.parse(' #{ 1 "abc" } ')).to eq(Set.new([1, 'abc']))
|
274
|
+
end
|
275
|
+
it 'nested set' do
|
276
|
+
expect(subject.parse(' #{1 #{:abc}}')).to eq(Set.new([1, Set.new([:abc])]))
|
277
|
+
end
|
278
|
+
it 'empty vector' do
|
279
|
+
expect(subject.parse('[]')).to eq([])
|
280
|
+
end
|
281
|
+
it 'nested vectors' do
|
282
|
+
expect(subject.parse('[1 2 [3 4]]')).to eq([1, 2, [3, 4]])
|
283
|
+
end
|
284
|
+
it 'vector with other collection' do
|
285
|
+
expect(subject.parse('[1 2 #{3}]')).to eq([1, 2, Set.new([3])])
|
286
|
+
end
|
287
|
+
it 'empty list' do
|
288
|
+
expect(subject.parse('()')).to eq([])
|
289
|
+
end
|
290
|
+
it 'nested lists' do
|
291
|
+
expect(subject.parse('(1 2 (3 4))')).to eq([1, 2, [3, 4]])
|
292
|
+
end
|
293
|
+
it 'list with other collection' do
|
294
|
+
expect(subject.parse('(1 2 [3 4 #{5}])')).to eq([1, 2, [3, 4, Set.new([5])]])
|
295
|
+
end
|
296
|
+
it 'empty map' do
|
297
|
+
expect(subject.parse('{}')).to eq({})
|
298
|
+
end
|
299
|
+
it 'nested map' do
|
300
|
+
expect(subject.parse('{:a 1 :b {:c 2}}')).to eq(a: 1, b: { c: 2 })
|
301
|
+
end
|
302
|
+
it 'map with other collection' do
|
303
|
+
expect(subject.parse('{:a #{1}}')).to eq(a: Set.new([1]))
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
context 'symbols' do
|
308
|
+
it 'simple' do
|
309
|
+
expect(subject.parse('asymbol')).to eq(EDN::Type::Symbol.new('asymbol'))
|
310
|
+
end
|
311
|
+
it 'with a leading period' do
|
312
|
+
expect(subject.parse('.asymbol')).to eq(EDN::Type::Symbol.new('.asymbol'))
|
313
|
+
end
|
314
|
+
it 'with single quotes' do
|
315
|
+
expect(subject.parse("with'_a_'")).to eq(EDN::Type::Symbol.new("with'_a_'"))
|
316
|
+
end
|
317
|
+
it 'with a period in the middle' do
|
318
|
+
expect(subject.parse('with.123')).to eq(EDN::Type::Symbol.new('with.123'))
|
319
|
+
end
|
320
|
+
it 'with a leading dash' do
|
321
|
+
expect(subject.parse('-with.123')).to eq(EDN::Type::Symbol.new('-with.123'))
|
322
|
+
end
|
323
|
+
it 'slash' do
|
324
|
+
expect(subject.parse('/')).to eq(EDN::Type::Symbol.new('/'))
|
325
|
+
end
|
326
|
+
it 'with mathematical operators' do
|
327
|
+
expect(subject.parse('>:FOuy/+')).to eq(EDN::Type::Symbol.new('>:FOuy/+'))
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
context 'metadata' do
|
332
|
+
it 'array with meta' do
|
333
|
+
rslt = subject.parse('^{:doc "This is my vector" :rel :temps} [98.6 99.7]')
|
334
|
+
expect(rslt.metadata).to eq(doc: 'This is my vector', rel: :temps)
|
335
|
+
end
|
336
|
+
it 'object tags' do
|
337
|
+
rslt = subject.parse('^String ^:foo ^{:foo false :tag Boolean :bar 2} [1 2]')
|
338
|
+
expect(rslt.metadata).to eq(foo: true, tag: EDN::Type::Symbol.new('String'), bar: 2)
|
339
|
+
end
|
340
|
+
it 'meta in vector' do
|
341
|
+
rslt = subject.parse('[ [ ^{:a :b} c, :d, true ], #inst "1390-09-07T21:27:03+00:00" ]')
|
342
|
+
expect(rslt).to eq([[EDN::Type::Symbol.new('c'), :d, true],
|
343
|
+
DateTime.rfc3339('1390-09-07T21:27:03+00:00')])
|
344
|
+
expect(rslt.first.first.metadata).to eq(a: :b)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
context 'tagged element' do
|
349
|
+
class Tagged
|
350
|
+
def initialize(data)
|
351
|
+
@item = data[:item]
|
352
|
+
@other = data[:other]
|
353
|
+
end
|
354
|
+
|
355
|
+
def to_s
|
356
|
+
[@item, @other]
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
it 'with user-defined type' do
|
361
|
+
# register the tag
|
362
|
+
EDN.register('edn_turbo/test_tagged') { |data| Tagged.new(data).to_s }
|
363
|
+
|
364
|
+
# test
|
365
|
+
expect(subject.parse('#edn_turbo/test_tagged { :item 345 :other :a }')).to eq([345, :a])
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
context 'discard' do
|
370
|
+
it 'single discard' do
|
371
|
+
expect(subject.parse('#_ :foo')).to eq(EDN::EOF)
|
372
|
+
end
|
373
|
+
it 'in vector' do
|
374
|
+
expect(subject.parse('[:a :b #_ :foo 42 [ :c #_dd]]')).to eq([:a, :b, 42, [:c]])
|
375
|
+
end
|
376
|
+
it 'at beginning of line' do
|
377
|
+
expect(subject.parse('#_ > 456')).to eq(456)
|
378
|
+
end
|
379
|
+
it 'collection' do
|
380
|
+
expect(subject.parse('[ 1 2 3 4 #_ { :a 1 } ]')).to eq([1, 2, 3, 4])
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|