tomlrb 2.0.2 → 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 +27 -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,15 +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|
|
|
83
|
+
inline_key = inline_key.to_sym if @symbolize_keys
|
|
78
84
|
last_key = inline_index == inline_array.size - 1
|
|
79
85
|
|
|
80
86
|
if last_key
|
|
81
87
|
if current[inline_key].nil?
|
|
88
|
+
keys.add_pair_key [inline_key], []
|
|
89
|
+
|
|
82
90
|
current[inline_key] = value
|
|
83
91
|
else
|
|
84
92
|
raise Key::KeyConflict, "Inline key #{inline_key} is already used"
|
|
@@ -101,6 +109,7 @@ module Tomlrb
|
|
|
101
109
|
array = []
|
|
102
110
|
while (value = @stack.pop) != [type]
|
|
103
111
|
raise ParseError, 'Unclosed table' if @stack.empty?
|
|
112
|
+
|
|
104
113
|
array.unshift(value)
|
|
105
114
|
end
|
|
106
115
|
array
|
|
@@ -115,15 +124,18 @@ module Tomlrb
|
|
|
115
124
|
private
|
|
116
125
|
|
|
117
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)
|
|
118
129
|
if key_emptied
|
|
130
|
+
raise ParseError, "Cannot overwrite value with key #{key}" unless current.is_a?(Hash)
|
|
119
131
|
|
|
120
|
-
|
|
121
|
-
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
|
|
122
135
|
return current
|
|
123
136
|
end
|
|
124
137
|
current[key] ||= {}
|
|
125
|
-
current
|
|
126
|
-
current
|
|
138
|
+
current[key]
|
|
127
139
|
end
|
|
128
140
|
end
|
|
129
141
|
|
|
@@ -152,10 +164,10 @@ module Tomlrb
|
|
|
152
164
|
def append_table_keys(current, table_keys, pair_keys_empty, is_array_of_tables)
|
|
153
165
|
table_keys.each_with_index do |key, index|
|
|
154
166
|
declared = (index == table_keys.length - 1) && pair_keys_empty
|
|
155
|
-
if index
|
|
167
|
+
if index.zero?
|
|
156
168
|
current = find_or_create_first_table_key(current, key, declared, is_array_of_tables)
|
|
157
169
|
else
|
|
158
|
-
current
|
|
170
|
+
current <<= [key, :table, declared, is_array_of_tables]
|
|
159
171
|
end
|
|
160
172
|
end
|
|
161
173
|
|
|
@@ -172,6 +184,7 @@ module Tomlrb
|
|
|
172
184
|
raise Key::KeyConflict, "Key #{key} is already used"
|
|
173
185
|
end
|
|
174
186
|
k = existed || Key.new(key, :table, declared)
|
|
187
|
+
k.declared = k.declared? || declared
|
|
175
188
|
current[key] = k
|
|
176
189
|
k
|
|
177
190
|
end
|
|
@@ -179,7 +192,7 @@ module Tomlrb
|
|
|
179
192
|
def append_pair_keys(current, pair_keys, table_keys_empty, is_array_of_tables)
|
|
180
193
|
pair_keys.each_with_index do |key, index|
|
|
181
194
|
declared = index == pair_keys.length - 1
|
|
182
|
-
if index
|
|
195
|
+
if index.zero? && table_keys_empty
|
|
183
196
|
current = find_or_create_first_pair_key(current, key, declared, table_keys_empty)
|
|
184
197
|
else
|
|
185
198
|
key = current << [key, :pair, declared, is_array_of_tables]
|
|
@@ -203,6 +216,7 @@ module Tomlrb
|
|
|
203
216
|
class KeyConflict < ParseError; end
|
|
204
217
|
|
|
205
218
|
attr_reader :key, :type
|
|
219
|
+
attr_writer :declared
|
|
206
220
|
|
|
207
221
|
def initialize(key, type, declared = false)
|
|
208
222
|
@key = key
|
|
@@ -232,32 +246,32 @@ module Tomlrb
|
|
|
232
246
|
|
|
233
247
|
private
|
|
234
248
|
|
|
235
|
-
def validate_already_declared_as_different_key(type,
|
|
249
|
+
def validate_already_declared_as_different_key(type, _declared, existed)
|
|
236
250
|
if existed && existed.declared? && existed.type != type
|
|
237
251
|
raise KeyConflict, "Key #{existed.key} is already used as #{existed.type} key"
|
|
238
252
|
end
|
|
239
253
|
end
|
|
240
254
|
|
|
241
255
|
def validate_already_declared_as_non_array_table(type, is_array_of_tables, declared, existed)
|
|
242
|
-
if declared && type == :table && existed && existed.declared? && !
|
|
256
|
+
if declared && type == :table && existed && existed.declared? && !is_array_of_tables
|
|
243
257
|
raise KeyConflict, "Key #{existed.key} is already used"
|
|
244
258
|
end
|
|
245
259
|
end
|
|
246
260
|
|
|
247
261
|
def validate_path_already_created_as_different_type(type, declared, existed)
|
|
248
|
-
if declared && (type == :table) && existed && (existed.type == :pair) &&
|
|
262
|
+
if declared && (type == :table) && existed && (existed.type == :pair) && !existed.declared?
|
|
249
263
|
raise KeyConflict, "Key #{existed.key} is already used as #{existed.type} key"
|
|
250
264
|
end
|
|
251
265
|
end
|
|
252
266
|
|
|
253
267
|
def validate_path_already_declared_as_different_type(type, declared, existed)
|
|
254
|
-
if !
|
|
268
|
+
if !declared && (type == :pair) && existed && (existed.type == :pair) && existed.declared?
|
|
255
269
|
raise KeyConflict, "Key #{key} is already used as #{type} key"
|
|
256
270
|
end
|
|
257
271
|
end
|
|
258
272
|
|
|
259
273
|
def validate_already_declared_as_same_key(declared, existed)
|
|
260
|
-
if existed && !
|
|
274
|
+
if existed && !existed.declared? && declared
|
|
261
275
|
raise KeyConflict, "Key #{existed.key} is already used as #{existed.type} key"
|
|
262
276
|
end
|
|
263
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: []
|