tomlrb 2.0.3 → 2.0.4
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 +4 -4
- data/lib/tomlrb/generated_parser.rb +322 -224
- data/lib/tomlrb/handler.rb +26 -13
- data/lib/tomlrb/local_date.rb +7 -4
- data/lib/tomlrb/local_date_time.rb +10 -6
- data/lib/tomlrb/local_time.rb +9 -6
- data/lib/tomlrb/parser.rb +3 -1
- data/lib/tomlrb/parser.y +64 -30
- data/lib/tomlrb/scanner.rb +44 -26
- data/lib/tomlrb/string_utils.rb +4 -3
- data/lib/tomlrb/version.rb +3 -1
- data/lib/tomlrb.rb +7 -5
- metadata +3 -6
data/lib/tomlrb/handler.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
1
3
|
module Tomlrb
|
|
2
4
|
class Handler
|
|
3
5
|
attr_reader :output, :symbolize_keys
|
|
@@ -58,7 +60,7 @@ module Tomlrb
|
|
|
58
60
|
def assign(k)
|
|
59
61
|
@keys.add_pair_key k, @current_table
|
|
60
62
|
current = @current
|
|
61
|
-
while key = k.shift
|
|
63
|
+
while (key = k.shift)
|
|
62
64
|
key = key.to_sym if @symbolize_keys
|
|
63
65
|
current = assign_key_path(current, key, k.empty?)
|
|
64
66
|
end
|
|
@@ -70,16 +72,21 @@ module Tomlrb
|
|
|
70
72
|
|
|
71
73
|
def push_inline(inline_arrays)
|
|
72
74
|
merged_inline = {}
|
|
75
|
+
keys = Keys.new
|
|
73
76
|
|
|
74
77
|
inline_arrays.each do |inline_array|
|
|
75
78
|
current = merged_inline
|
|
76
79
|
value = inline_array.pop
|
|
80
|
+
keys.add_table_key inline_array, value.is_a?(Array)
|
|
81
|
+
|
|
77
82
|
inline_array.each_with_index do |inline_key, inline_index|
|
|
78
83
|
inline_key = inline_key.to_sym if @symbolize_keys
|
|
79
84
|
last_key = inline_index == inline_array.size - 1
|
|
80
85
|
|
|
81
86
|
if last_key
|
|
82
87
|
if current[inline_key].nil?
|
|
88
|
+
keys.add_pair_key [inline_key], []
|
|
89
|
+
|
|
83
90
|
current[inline_key] = value
|
|
84
91
|
else
|
|
85
92
|
raise Key::KeyConflict, "Inline key #{inline_key} is already used"
|
|
@@ -102,6 +109,7 @@ module Tomlrb
|
|
|
102
109
|
array = []
|
|
103
110
|
while (value = @stack.pop) != [type]
|
|
104
111
|
raise ParseError, 'Unclosed table' if @stack.empty?
|
|
112
|
+
|
|
105
113
|
array.unshift(value)
|
|
106
114
|
end
|
|
107
115
|
array
|
|
@@ -116,15 +124,18 @@ module Tomlrb
|
|
|
116
124
|
private
|
|
117
125
|
|
|
118
126
|
def assign_key_path(current, key, key_emptied)
|
|
127
|
+
existed = current.key?(key)
|
|
128
|
+
raise ParseError, "Cannot overwrite value with key #{key}" if existed && !current[key].is_a?(Hash)
|
|
119
129
|
if key_emptied
|
|
130
|
+
raise ParseError, "Cannot overwrite value with key #{key}" unless current.is_a?(Hash)
|
|
120
131
|
|
|
121
|
-
|
|
122
|
-
current[key]
|
|
132
|
+
value = @stack.pop
|
|
133
|
+
raise ParseError, "Cannot overwrite value with key #{key}" if current[key].is_a?(Hash) && !value.is_a?(Hash)
|
|
134
|
+
current[key] = value
|
|
123
135
|
return current
|
|
124
136
|
end
|
|
125
137
|
current[key] ||= {}
|
|
126
|
-
current
|
|
127
|
-
current
|
|
138
|
+
current[key]
|
|
128
139
|
end
|
|
129
140
|
end
|
|
130
141
|
|
|
@@ -153,10 +164,10 @@ module Tomlrb
|
|
|
153
164
|
def append_table_keys(current, table_keys, pair_keys_empty, is_array_of_tables)
|
|
154
165
|
table_keys.each_with_index do |key, index|
|
|
155
166
|
declared = (index == table_keys.length - 1) && pair_keys_empty
|
|
156
|
-
if index
|
|
167
|
+
if index.zero?
|
|
157
168
|
current = find_or_create_first_table_key(current, key, declared, is_array_of_tables)
|
|
158
169
|
else
|
|
159
|
-
current
|
|
170
|
+
current <<= [key, :table, declared, is_array_of_tables]
|
|
160
171
|
end
|
|
161
172
|
end
|
|
162
173
|
|
|
@@ -173,6 +184,7 @@ module Tomlrb
|
|
|
173
184
|
raise Key::KeyConflict, "Key #{key} is already used"
|
|
174
185
|
end
|
|
175
186
|
k = existed || Key.new(key, :table, declared)
|
|
187
|
+
k.declared = k.declared? || declared
|
|
176
188
|
current[key] = k
|
|
177
189
|
k
|
|
178
190
|
end
|
|
@@ -180,7 +192,7 @@ module Tomlrb
|
|
|
180
192
|
def append_pair_keys(current, pair_keys, table_keys_empty, is_array_of_tables)
|
|
181
193
|
pair_keys.each_with_index do |key, index|
|
|
182
194
|
declared = index == pair_keys.length - 1
|
|
183
|
-
if index
|
|
195
|
+
if index.zero? && table_keys_empty
|
|
184
196
|
current = find_or_create_first_pair_key(current, key, declared, table_keys_empty)
|
|
185
197
|
else
|
|
186
198
|
key = current << [key, :pair, declared, is_array_of_tables]
|
|
@@ -204,6 +216,7 @@ module Tomlrb
|
|
|
204
216
|
class KeyConflict < ParseError; end
|
|
205
217
|
|
|
206
218
|
attr_reader :key, :type
|
|
219
|
+
attr_writer :declared
|
|
207
220
|
|
|
208
221
|
def initialize(key, type, declared = false)
|
|
209
222
|
@key = key
|
|
@@ -233,32 +246,32 @@ module Tomlrb
|
|
|
233
246
|
|
|
234
247
|
private
|
|
235
248
|
|
|
236
|
-
def validate_already_declared_as_different_key(type,
|
|
249
|
+
def validate_already_declared_as_different_key(type, _declared, existed)
|
|
237
250
|
if existed && existed.declared? && existed.type != type
|
|
238
251
|
raise KeyConflict, "Key #{existed.key} is already used as #{existed.type} key"
|
|
239
252
|
end
|
|
240
253
|
end
|
|
241
254
|
|
|
242
255
|
def validate_already_declared_as_non_array_table(type, is_array_of_tables, declared, existed)
|
|
243
|
-
if declared && type == :table && existed && existed.declared? && !
|
|
256
|
+
if declared && type == :table && existed && existed.declared? && !is_array_of_tables
|
|
244
257
|
raise KeyConflict, "Key #{existed.key} is already used"
|
|
245
258
|
end
|
|
246
259
|
end
|
|
247
260
|
|
|
248
261
|
def validate_path_already_created_as_different_type(type, declared, existed)
|
|
249
|
-
if declared && (type == :table) && existed && (existed.type == :pair) &&
|
|
262
|
+
if declared && (type == :table) && existed && (existed.type == :pair) && !existed.declared?
|
|
250
263
|
raise KeyConflict, "Key #{existed.key} is already used as #{existed.type} key"
|
|
251
264
|
end
|
|
252
265
|
end
|
|
253
266
|
|
|
254
267
|
def validate_path_already_declared_as_different_type(type, declared, existed)
|
|
255
|
-
if !
|
|
268
|
+
if !declared && (type == :pair) && existed && (existed.type == :pair) && existed.declared?
|
|
256
269
|
raise KeyConflict, "Key #{key} is already used as #{type} key"
|
|
257
270
|
end
|
|
258
271
|
end
|
|
259
272
|
|
|
260
273
|
def validate_already_declared_as_same_key(declared, existed)
|
|
261
|
-
if existed && !
|
|
274
|
+
if existed && !existed.declared? && declared
|
|
262
275
|
raise KeyConflict, "Key #{existed.key} is already used as #{existed.type} key"
|
|
263
276
|
end
|
|
264
277
|
end
|
data/lib/tomlrb/local_date.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
1
3
|
require 'forwardable'
|
|
2
4
|
|
|
3
5
|
module Tomlrb
|
|
@@ -7,12 +9,13 @@ module Tomlrb
|
|
|
7
9
|
def_delegators :@time, :year, :month, :day
|
|
8
10
|
|
|
9
11
|
def initialize(year, month, day)
|
|
10
|
-
@time = Time.
|
|
12
|
+
@time = Time.utc(year, month, day, 0, 0, 0)
|
|
13
|
+
raise ArgumentError, "Invalid Local Date: #{year}-#{month}-#{day}" unless day.to_i == @time.day && month.to_i == @time.month && year.to_i == @time.year
|
|
11
14
|
end
|
|
12
15
|
|
|
13
16
|
# @param offset see {LocalDateTime#to_time}
|
|
14
17
|
# @return [Time] 00:00:00 of the date
|
|
15
|
-
def to_time(offset='-00:00')
|
|
18
|
+
def to_time(offset = '-00:00')
|
|
16
19
|
return @time if offset == '-00:00'
|
|
17
20
|
Time.new(year, month, day, 0, 0, 0, offset)
|
|
18
21
|
end
|
|
@@ -22,12 +25,12 @@ module Tomlrb
|
|
|
22
25
|
end
|
|
23
26
|
|
|
24
27
|
def ==(other)
|
|
25
|
-
other.
|
|
28
|
+
other.is_a?(self.class) &&
|
|
26
29
|
to_time == other.to_time
|
|
27
30
|
end
|
|
28
31
|
|
|
29
32
|
def inspect
|
|
30
|
-
"#<#{self.class}: #{
|
|
33
|
+
"#<#{self.class}: #{self}>"
|
|
31
34
|
end
|
|
32
35
|
end
|
|
33
36
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
1
3
|
require 'forwardable'
|
|
2
4
|
|
|
3
5
|
module Tomlrb
|
|
@@ -7,7 +9,9 @@ module Tomlrb
|
|
|
7
9
|
def_delegators :@time, :year, :month, :day, :hour, :min, :sec, :usec, :nsec
|
|
8
10
|
|
|
9
11
|
def initialize(year, month, day, hour, min, sec) # rubocop:disable Metrics/ParameterLists
|
|
10
|
-
@time = Time.
|
|
12
|
+
@time = Time.utc(year, month, day, hour, min, sec)
|
|
13
|
+
raise ArgumentError, "Invalid Local Date-Time: #{year}-#{month}-#{day}T#{hour}:#{min}:#{sec}" unless min.to_i == @time.min && hour.to_i == @time.hour && day.to_i == @time.day && month.to_i == @time.month && year.to_i == @time.year
|
|
14
|
+
|
|
11
15
|
@sec = sec
|
|
12
16
|
end
|
|
13
17
|
|
|
@@ -17,24 +21,24 @@ module Tomlrb
|
|
|
17
21
|
# * when +Numeric+, it is time zone offset in second.
|
|
18
22
|
# * when +nil+, local time zone offset is used.
|
|
19
23
|
# @return [Time]
|
|
20
|
-
def to_time(offset='-00:00')
|
|
24
|
+
def to_time(offset = '-00:00')
|
|
21
25
|
return @time if offset == '-00:00'
|
|
22
26
|
Time.new(year, month, day, hour, min, @sec, offset)
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
def to_s
|
|
26
30
|
frac = (@sec - sec)
|
|
27
|
-
frac_str = frac
|
|
28
|
-
@time.strftime(
|
|
31
|
+
frac_str = frac.zero? ? '' : frac.to_s[1..-1]
|
|
32
|
+
@time.strftime('%FT%T') << frac_str
|
|
29
33
|
end
|
|
30
34
|
|
|
31
35
|
def ==(other)
|
|
32
|
-
other.
|
|
36
|
+
other.is_a?(self.class) &&
|
|
33
37
|
to_time == other.to_time
|
|
34
38
|
end
|
|
35
39
|
|
|
36
40
|
def inspect
|
|
37
|
-
"#<#{self.class}: #{
|
|
41
|
+
"#<#{self.class}: #{self}>"
|
|
38
42
|
end
|
|
39
43
|
end
|
|
40
44
|
end
|
data/lib/tomlrb/local_time.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
1
3
|
require 'forwardable'
|
|
2
4
|
|
|
3
5
|
module Tomlrb
|
|
@@ -7,7 +9,8 @@ module Tomlrb
|
|
|
7
9
|
def_delegators :@time, :hour, :min, :sec, :usec, :nsec
|
|
8
10
|
|
|
9
11
|
def initialize(hour, min, sec)
|
|
10
|
-
@time = Time.
|
|
12
|
+
@time = Time.utc(0, 1, 1, hour, min, sec)
|
|
13
|
+
raise ArgumentError, "Invalid Local Time: #{hour}-#{min}-#{sec}" unless min.to_i == @time.min && hour.to_i == @time.hour
|
|
11
14
|
@sec = sec
|
|
12
15
|
end
|
|
13
16
|
|
|
@@ -16,23 +19,23 @@ module Tomlrb
|
|
|
16
19
|
# @param day [Integer]
|
|
17
20
|
# @param offset see {LocalDateTime#to_time}
|
|
18
21
|
# @return [Time] the time of the date specified by params
|
|
19
|
-
def to_time(year, month, day, offset='-00:00')
|
|
22
|
+
def to_time(year, month, day, offset = '-00:00')
|
|
20
23
|
Time.new(year, month, day, hour, min, @sec, offset)
|
|
21
24
|
end
|
|
22
25
|
|
|
23
26
|
def to_s
|
|
24
27
|
frac = (@sec - sec)
|
|
25
|
-
frac_str = frac
|
|
26
|
-
@time.strftime(
|
|
28
|
+
frac_str = frac.zero? ? '' : frac.to_s[1..-1]
|
|
29
|
+
@time.strftime('%T') << frac_str
|
|
27
30
|
end
|
|
28
31
|
|
|
29
32
|
def ==(other)
|
|
30
|
-
other.
|
|
33
|
+
other.is_a?(self.class) &&
|
|
31
34
|
@time == other.to_time(0, 1, 1)
|
|
32
35
|
end
|
|
33
36
|
|
|
34
37
|
def inspect
|
|
35
|
-
"#<#{self.class}: #{
|
|
38
|
+
"#<#{self.class}: #{self}>"
|
|
36
39
|
end
|
|
37
40
|
end
|
|
38
41
|
end
|
data/lib/tomlrb/parser.rb
CHANGED
data/lib/tomlrb/parser.y
CHANGED
|
@@ -12,22 +12,19 @@ rule
|
|
|
12
12
|
| NEWLINE
|
|
13
13
|
;
|
|
14
14
|
table
|
|
15
|
-
: table_start
|
|
16
|
-
| table_start
|
|
15
|
+
: table_start table_identifier table_end newlines
|
|
16
|
+
| table_start table_identifier table_end EOS
|
|
17
|
+
| table_start table_end newlines
|
|
18
|
+
| table_start table_end EOS
|
|
17
19
|
;
|
|
18
20
|
table_start
|
|
19
21
|
: '[' '[' { @handler.start_(:array_of_tables) }
|
|
20
22
|
| '[' { @handler.start_(:table) }
|
|
21
23
|
;
|
|
22
|
-
table_continued
|
|
23
|
-
: ']' ']' { array = @handler.end_(:array_of_tables); @handler.set_context(array, is_array_of_tables: true) }
|
|
24
|
-
| ']' { array = @handler.end_(:table); @handler.set_context(array) }
|
|
25
|
-
| table_identifier table_next
|
|
26
24
|
;
|
|
27
|
-
|
|
25
|
+
table_end
|
|
28
26
|
: ']' ']' { array = @handler.end_(:array_of_tables); @handler.set_context(array, is_array_of_tables: true) }
|
|
29
27
|
| ']' { array = @handler.end_(:table); @handler.set_context(array) }
|
|
30
|
-
| '.' table_continued
|
|
31
28
|
;
|
|
32
29
|
table_identifier
|
|
33
30
|
: table_identifier '.' table_identifier_component { @handler.push(val[2]) }
|
|
@@ -47,6 +44,8 @@ rule
|
|
|
47
44
|
| NON_DEC_INTEGER
|
|
48
45
|
| FLOAT_KEYWORD
|
|
49
46
|
| BOOLEAN
|
|
47
|
+
| DATETIME { result = val[0][0] }
|
|
48
|
+
| LOCAL_TIME { result = val[0][0] }
|
|
50
49
|
;
|
|
51
50
|
inline_table
|
|
52
51
|
: inline_table_start inline_table_end
|
|
@@ -123,34 +122,66 @@ rule
|
|
|
123
122
|
| NON_DEC_INTEGER
|
|
124
123
|
| FLOAT_KEYWORD
|
|
125
124
|
| BOOLEAN
|
|
125
|
+
| DATETIME { result = val[0][0] }
|
|
126
|
+
| LOCAL_TIME { result = val[0][0] }
|
|
126
127
|
;
|
|
127
128
|
array
|
|
128
|
-
: start_array
|
|
129
|
+
: start_array array_first_value array_values comma end_array
|
|
130
|
+
| start_array array_first_value array_values end_array
|
|
131
|
+
| start_array array_first_value comma end_array
|
|
132
|
+
| start_array array_first_value end_array
|
|
133
|
+
| start_array end_array
|
|
129
134
|
;
|
|
130
|
-
|
|
131
|
-
:
|
|
132
|
-
|
|
|
133
|
-
| NEWLINE array_continued
|
|
135
|
+
array_first_value
|
|
136
|
+
: newlines non_nil_value
|
|
137
|
+
| non_nil_value
|
|
134
138
|
;
|
|
135
|
-
|
|
136
|
-
:
|
|
137
|
-
|
|
|
138
|
-
|
|
139
|
+
array_values
|
|
140
|
+
: array_values array_value
|
|
141
|
+
| array_value
|
|
142
|
+
;
|
|
143
|
+
array_value
|
|
144
|
+
: comma newlines non_nil_value
|
|
145
|
+
| comma non_nil_value
|
|
139
146
|
;
|
|
140
147
|
start_array
|
|
141
148
|
: '[' { @handler.start_(:array) }
|
|
142
149
|
;
|
|
150
|
+
end_array
|
|
151
|
+
: newlines ']' { array = @handler.end_(:array); @handler.push(array.compact) }
|
|
152
|
+
| ']' { array = @handler.end_(:array); @handler.push(array.compact) }
|
|
153
|
+
;
|
|
154
|
+
comma
|
|
155
|
+
: newlines ','
|
|
156
|
+
| ','
|
|
157
|
+
;
|
|
158
|
+
newlines
|
|
159
|
+
: newlines NEWLINE
|
|
160
|
+
| NEWLINE
|
|
161
|
+
;
|
|
143
162
|
value
|
|
144
163
|
: scalar { @handler.push(val[0]) }
|
|
145
164
|
| array
|
|
146
165
|
| inline_table
|
|
147
166
|
;
|
|
167
|
+
non_nil_value
|
|
168
|
+
: non_nil_scalar { @handler.push(val[0]) }
|
|
169
|
+
| array
|
|
170
|
+
| inline_table
|
|
171
|
+
;
|
|
148
172
|
scalar
|
|
149
173
|
: string
|
|
150
174
|
| literal
|
|
151
175
|
;
|
|
176
|
+
non_nil_scalar
|
|
177
|
+
: string
|
|
178
|
+
| non_nil_literal
|
|
179
|
+
;
|
|
152
180
|
literal
|
|
153
|
-
|
|
|
181
|
+
| non_nil_literal
|
|
182
|
+
;
|
|
183
|
+
non_nil_literal
|
|
184
|
+
: FLOAT { result = val[0].to_f }
|
|
154
185
|
| FLOAT_KEYWORD {
|
|
155
186
|
v = val[0]
|
|
156
187
|
result = if v.end_with?('nan')
|
|
@@ -162,31 +193,34 @@ rule
|
|
|
162
193
|
| INTEGER { result = val[0].to_i }
|
|
163
194
|
| NON_DEC_INTEGER {
|
|
164
195
|
base = case val[0][1]
|
|
165
|
-
when
|
|
166
|
-
when
|
|
167
|
-
when
|
|
196
|
+
when 'x' then 16
|
|
197
|
+
when 'o' then 8
|
|
198
|
+
when 'b' then 2
|
|
168
199
|
end
|
|
169
200
|
result = val[0].to_i(base)
|
|
170
201
|
}
|
|
171
202
|
| BOOLEAN { result = val[0] == 'true' ? true : false }
|
|
172
203
|
| DATETIME {
|
|
173
|
-
|
|
174
|
-
result = if
|
|
175
|
-
if
|
|
176
|
-
LocalDate.new(
|
|
204
|
+
_str, year, month, day, hour, min, sec, offset = val[0]
|
|
205
|
+
result = if offset.nil?
|
|
206
|
+
if hour.nil?
|
|
207
|
+
LocalDate.new(year, month, day)
|
|
177
208
|
else
|
|
178
|
-
LocalDateTime.new(
|
|
209
|
+
LocalDateTime.new(year, month, day, hour, min || 0, sec.to_f)
|
|
179
210
|
end
|
|
180
211
|
else
|
|
181
212
|
# Patch for 24:00:00 which Ruby parses
|
|
182
|
-
if
|
|
183
|
-
|
|
213
|
+
if hour.to_i == 24 && min.to_i == 0 && sec.to_i == 0
|
|
214
|
+
hour = (hour.to_i + 1).to_s
|
|
184
215
|
end
|
|
185
216
|
|
|
186
|
-
Time.new(
|
|
217
|
+
time = Time.new(year, month, day, hour || 0, min || 0, sec.to_f, offset)
|
|
218
|
+
# Should be out of parser.y?
|
|
219
|
+
raise ArgumentError, "Invalid Offset Date-Time: #{year}-#{month}-#{day}T#{hour}:#{min}:#{sec}#{offset}" unless min.to_i == time.min && hour.to_i == time.hour && day.to_i == time.day && month.to_i == time.month && year.to_i == time.year
|
|
220
|
+
time
|
|
187
221
|
end
|
|
188
222
|
}
|
|
189
|
-
| LOCAL_TIME { result = LocalTime.new(*val[0]) }
|
|
223
|
+
| LOCAL_TIME { result = LocalTime.new(*val[0][1..-1]) }
|
|
190
224
|
;
|
|
191
225
|
string
|
|
192
226
|
: STRING_MULTI { result = StringUtils.replace_escaped_chars(StringUtils.multiline_replacements(val[0])) }
|
data/lib/tomlrb/scanner.rb
CHANGED
|
@@ -1,25 +1,45 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
1
3
|
require 'strscan'
|
|
2
4
|
|
|
3
5
|
module Tomlrb
|
|
4
6
|
class Scanner
|
|
5
|
-
COMMENT =
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
7
|
+
COMMENT =
|
|
8
|
+
/#[^\u0000-\u0008\u000A-\u001F\u007F]*/.freeze
|
|
9
|
+
IDENTIFIER =
|
|
10
|
+
/[A-Za-z0-9_-]+/.freeze
|
|
11
|
+
SPACE =
|
|
12
|
+
/[ \t]/.freeze
|
|
13
|
+
NEWLINE =
|
|
14
|
+
/(?:[ \t]*(?:\r?\n)[ \t]*)+/.freeze
|
|
15
|
+
STRING_BASIC =
|
|
16
|
+
/(")(?:\\?[^\u0000-\u0008\u000A-\u001F\u007F\\]|(?:\\[^\u0000-\u0008\u000A-\u001F\u007F]))*?\1/.freeze
|
|
17
|
+
STRING_MULTI =
|
|
18
|
+
/"{3}([^\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]*?(?<!\\)"{3,5})/m.freeze
|
|
19
|
+
STRING_LITERAL =
|
|
20
|
+
/(')(?:\\?[^\u0000-\u0008\u000A-\u001F\u007F])*?\1/.freeze
|
|
21
|
+
STRING_LITERAL_MULTI =
|
|
22
|
+
/'{3}([^\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]*?'{3,5})/m.freeze
|
|
23
|
+
DATETIME =
|
|
24
|
+
/(-?\d{4})-([01]\d)-([0-3]\d)(?:(?:t|\s)([0-2]\d):([0-5]\d):([0-6]\d(?:\.\d+)?))?(z|[-+][01]\d:\d{2})?/i.freeze
|
|
25
|
+
LOCAL_TIME =
|
|
26
|
+
/([0-2]\d):([0-5]\d):([0-6]\d(?:\.\d+)?)/.freeze
|
|
27
|
+
FLOAT =
|
|
28
|
+
/[+-]?(?:(?:\d|[1-9](?:_?\d)*)\.\d(?:_?\d)*|\d+(?=[eE]))(?:[eE][+-]?[0-9]+(_[0-9])*[0-9]*)?(?!\w)/.freeze
|
|
29
|
+
FLOAT_KEYWORD =
|
|
30
|
+
/[+-]?(?:inf|nan)\b/.freeze
|
|
31
|
+
INTEGER =
|
|
32
|
+
/[+-]?([1-9](_?\d)*|0)(?![A-Za-z0-9_-]+)/.freeze
|
|
33
|
+
NON_DEC_INTEGER =
|
|
34
|
+
/0(?:x[0-9A-Fa-f](_?[0-9A-Fa-f])*|o[0-7](_?[0-7])*|b[01](_?[01])*)/.freeze
|
|
35
|
+
BOOLEAN =
|
|
36
|
+
/true|false/.freeze
|
|
37
|
+
SPACED_ARRAY_OF_TABLES_START =
|
|
38
|
+
/^\[[ \t]+\[(#{IDENTIFIER}|#{STRING_BASIC}|#{STRING_LITERAL}|#{INTEGER}|#{NON_DEC_INTEGER}|#{FLOAT_KEYWORD}|#{BOOLEAN})\]\]$/.freeze
|
|
39
|
+
SPACED_ARRAY_OF_TABLES_END =
|
|
40
|
+
/^\[\[(#{IDENTIFIER}|#{STRING_BASIC}|#{STRING_LITERAL}|#{INTEGER}|#{NON_DEC_INTEGER}|#{FLOAT_KEYWORD}|#{BOOLEAN})\][ \t]+\]$/.freeze
|
|
41
|
+
SPACED_ARRAY_OF_TABLES_BOTH =
|
|
42
|
+
/^\[[ \t]+\[(#{IDENTIFIER}|#{STRING_BASIC}|#{STRING_LITERAL}|#{INTEGER}|#{NON_DEC_INTEGER}|#{FLOAT_KEYWORD}|#{BOOLEAN})\][ \t]+\]$/.freeze
|
|
23
43
|
|
|
24
44
|
def initialize(io)
|
|
25
45
|
@ss = StringScanner.new(io.read)
|
|
@@ -29,9 +49,9 @@ module Tomlrb
|
|
|
29
49
|
def next_token
|
|
30
50
|
case
|
|
31
51
|
when @ss.scan(NEWLINE) then [:NEWLINE, nil]
|
|
32
|
-
when @ss.scan(SPACED_ARRAY_OF_TABLES_START) then raise ParseError.new(
|
|
33
|
-
when @ss.scan(SPACED_ARRAY_OF_TABLES_END) then raise ParseError.new(
|
|
34
|
-
when @ss.scan(SPACED_ARRAY_OF_TABLES_BOTH) then raise ParseError.new(
|
|
52
|
+
when @ss.scan(SPACED_ARRAY_OF_TABLES_START) then raise ParseError.new('Array of tables has spaces in starting brackets')
|
|
53
|
+
when @ss.scan(SPACED_ARRAY_OF_TABLES_END) then raise ParseError.new('Array of tables has spaces in ending brackets')
|
|
54
|
+
when @ss.scan(SPACED_ARRAY_OF_TABLES_BOTH) then raise ParseError.new('Array of tables has spaces in starting and ending brackets')
|
|
35
55
|
when @ss.scan(SPACE) then next_token
|
|
36
56
|
when @ss.scan(COMMENT) then next_token
|
|
37
57
|
when @ss.scan(DATETIME) then process_datetime
|
|
@@ -52,15 +72,13 @@ module Tomlrb
|
|
|
52
72
|
end
|
|
53
73
|
|
|
54
74
|
def process_datetime
|
|
55
|
-
if @ss[7]
|
|
56
|
-
|
|
57
|
-
end
|
|
58
|
-
args = [@ss[1], @ss[2], @ss[3], @ss[4], @ss[5], @ss[6], offset]
|
|
75
|
+
offset = @ss[7].gsub(/[zZ]/, '+00:00') if @ss[7]
|
|
76
|
+
args = [@ss[0], @ss[1], @ss[2], @ss[3], @ss[4], @ss[5], @ss[6], offset]
|
|
59
77
|
[:DATETIME, args]
|
|
60
78
|
end
|
|
61
79
|
|
|
62
80
|
def process_local_time
|
|
63
|
-
args = [@ss[1], @ss[2], @ss[3].to_f]
|
|
81
|
+
args = [@ss[0], @ss[1], @ss[2], @ss[3].to_f]
|
|
64
82
|
[:LOCAL_TIME, args]
|
|
65
83
|
end
|
|
66
84
|
|
data/lib/tomlrb/string_utils.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
1
3
|
module Tomlrb
|
|
2
4
|
class StringUtils
|
|
3
|
-
|
|
4
5
|
SPECIAL_CHARS = {
|
|
5
6
|
'\\t' => "\t",
|
|
6
7
|
'\\b' => "\b",
|
|
@@ -12,13 +13,13 @@ module Tomlrb
|
|
|
12
13
|
}.freeze
|
|
13
14
|
|
|
14
15
|
def self.multiline_replacements(str)
|
|
15
|
-
strip_spaces(str).gsub(/\\+\s*\n\s*/)
|
|
16
|
+
strip_spaces(str).gsub(/\\+\s*\n\s*/) do |matched|
|
|
16
17
|
if matched.match(/\\+/)[0].length.odd?
|
|
17
18
|
matched.gsub(/\\\s*\n\s*/, '')
|
|
18
19
|
else
|
|
19
20
|
matched
|
|
20
21
|
end
|
|
21
|
-
|
|
22
|
+
end
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
def self.replace_escaped_chars(str)
|
data/lib/tomlrb/version.rb
CHANGED
data/lib/tomlrb.rb
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
1
3
|
require 'time'
|
|
2
4
|
require 'stringio'
|
|
3
|
-
require
|
|
5
|
+
require 'tomlrb/version'
|
|
4
6
|
require 'tomlrb/local_date_time'
|
|
5
7
|
require 'tomlrb/local_date'
|
|
6
8
|
require 'tomlrb/local_time'
|
|
7
9
|
require 'tomlrb/string_utils'
|
|
8
|
-
require
|
|
9
|
-
require
|
|
10
|
-
require
|
|
10
|
+
require 'tomlrb/scanner'
|
|
11
|
+
require 'tomlrb/parser'
|
|
12
|
+
require 'tomlrb/handler'
|
|
11
13
|
|
|
12
14
|
module Tomlrb
|
|
13
15
|
class ParseError < StandardError; end
|
|
@@ -41,7 +43,7 @@ module Tomlrb
|
|
|
41
43
|
# By default Ruby sets the external encoding of an IO object to the
|
|
42
44
|
# default external encoding. The default external encoding is set by
|
|
43
45
|
# locale encoding or the interpreter -E option.
|
|
44
|
-
tmp = File.read(path, :
|
|
46
|
+
tmp = File.read(path, encoding: 'utf-8')
|
|
45
47
|
Tomlrb.parse(tmp, **options)
|
|
46
48
|
end
|
|
47
49
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tomlrb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Francois Bernier
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: psych
|
|
@@ -47,7 +46,6 @@ homepage: https://github.com/fbernier/tomlrb
|
|
|
47
46
|
licenses:
|
|
48
47
|
- MIT
|
|
49
48
|
metadata: {}
|
|
50
|
-
post_install_message:
|
|
51
49
|
rdoc_options: []
|
|
52
50
|
require_paths:
|
|
53
51
|
- lib
|
|
@@ -62,8 +60,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
62
60
|
- !ruby/object:Gem::Version
|
|
63
61
|
version: '0'
|
|
64
62
|
requirements: []
|
|
65
|
-
rubygems_version: 3.
|
|
66
|
-
signing_key:
|
|
63
|
+
rubygems_version: 3.6.9
|
|
67
64
|
specification_version: 4
|
|
68
65
|
summary: A racc based toml parser
|
|
69
66
|
test_files: []
|