tomlrb 2.0.0 → 2.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/tomlrb/generated_parser.rb +341 -378
- data/lib/tomlrb/handler.rb +45 -5
- data/lib/tomlrb/local_date.rb +1 -1
- data/lib/tomlrb/local_date_time.rb +1 -1
- data/lib/tomlrb/local_time.rb +1 -1
- data/lib/tomlrb/parser.y +74 -46
- data/lib/tomlrb/scanner.rb +20 -38
- data/lib/tomlrb/version.rb +1 -1
- metadata +18 -4
data/lib/tomlrb/handler.rb
CHANGED
@@ -13,6 +13,10 @@ module Tomlrb
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def set_context(identifiers, is_array_of_tables: false)
|
16
|
+
if identifiers.empty?
|
17
|
+
raise ParseError, 'Array needs a name'
|
18
|
+
end
|
19
|
+
|
16
20
|
@current_table = identifiers.dup
|
17
21
|
@keys.add_table_key identifiers, is_array_of_tables
|
18
22
|
@current = @output
|
@@ -21,7 +25,6 @@ module Tomlrb
|
|
21
25
|
identifierz.each do |k|
|
22
26
|
k = k.to_sym if @symbolize_keys
|
23
27
|
if @current[k].is_a?(Array)
|
24
|
-
@current[k] << {} if @current[k].empty?
|
25
28
|
@current = @current[k].last
|
26
29
|
else
|
27
30
|
@current[k] ||= {}
|
@@ -32,7 +35,6 @@ module Tomlrb
|
|
32
35
|
end
|
33
36
|
|
34
37
|
def deal_with_array_of_tables(identifiers, is_array_of_tables)
|
35
|
-
identifiers.map!{|n| n.gsub("\"", '')}
|
36
38
|
stringified_identifier = identifiers.join('.')
|
37
39
|
|
38
40
|
if is_array_of_tables
|
@@ -66,6 +68,32 @@ module Tomlrb
|
|
66
68
|
@stack << o
|
67
69
|
end
|
68
70
|
|
71
|
+
def push_inline(inline_arrays)
|
72
|
+
merged_inline = {}
|
73
|
+
|
74
|
+
inline_arrays.each do |inline_array|
|
75
|
+
current = merged_inline
|
76
|
+
value = inline_array.pop
|
77
|
+
inline_array.each_with_index do |inline_key, inline_index|
|
78
|
+
inline_key = inline_key.to_sym if @symbolize_keys
|
79
|
+
last_key = inline_index == inline_array.size - 1
|
80
|
+
|
81
|
+
if last_key
|
82
|
+
if current[inline_key].nil?
|
83
|
+
current[inline_key] = value
|
84
|
+
else
|
85
|
+
raise Key::KeyConflict, "Inline key #{inline_key} is already used"
|
86
|
+
end
|
87
|
+
else
|
88
|
+
current[inline_key] ||= {}
|
89
|
+
current = current[inline_key]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
push(merged_inline)
|
95
|
+
end
|
96
|
+
|
69
97
|
def start_(type)
|
70
98
|
push([type])
|
71
99
|
end
|
@@ -73,16 +101,23 @@ module Tomlrb
|
|
73
101
|
def end_(type)
|
74
102
|
array = []
|
75
103
|
while (value = @stack.pop) != [type]
|
76
|
-
raise ParseError, 'Unclosed table' if
|
104
|
+
raise ParseError, 'Unclosed table' if @stack.empty?
|
77
105
|
array.unshift(value)
|
78
106
|
end
|
79
107
|
array
|
80
108
|
end
|
81
109
|
|
110
|
+
def validate_value(value)
|
111
|
+
if value.nil?
|
112
|
+
raise ParseError, 'Value must be present'
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
82
116
|
private
|
83
117
|
|
84
118
|
def assign_key_path(current, key, key_emptied)
|
85
119
|
if key_emptied
|
120
|
+
|
86
121
|
raise ParseError, "Cannot overwrite value with key #{key}" unless current.kind_of?(Hash)
|
87
122
|
current[key] = @stack.pop
|
88
123
|
return current
|
@@ -125,6 +160,7 @@ module Tomlrb
|
|
125
160
|
end
|
126
161
|
end
|
127
162
|
|
163
|
+
current.clear_children if is_array_of_tables
|
128
164
|
current
|
129
165
|
end
|
130
166
|
|
@@ -155,7 +191,7 @@ module Tomlrb
|
|
155
191
|
|
156
192
|
def find_or_create_first_pair_key(current, key, declared, table_keys_empty)
|
157
193
|
existed = current[key]
|
158
|
-
if existed &&
|
194
|
+
if existed && (existed.type == :pair) && declared && table_keys_empty
|
159
195
|
raise Key::KeyConflict, "Key #{key} is already used"
|
160
196
|
end
|
161
197
|
k = Key.new(key, :pair, declared)
|
@@ -191,10 +227,14 @@ module Tomlrb
|
|
191
227
|
@children[key] = existed || self.class.new(key, type, declared)
|
192
228
|
end
|
193
229
|
|
230
|
+
def clear_children
|
231
|
+
@children.clear
|
232
|
+
end
|
233
|
+
|
194
234
|
private
|
195
235
|
|
196
236
|
def validate_already_declared_as_different_key(type, declared, existed)
|
197
|
-
if
|
237
|
+
if existed && existed.declared? && existed.type != type
|
198
238
|
raise KeyConflict, "Key #{existed.key} is already used as #{existed.type} key"
|
199
239
|
end
|
200
240
|
end
|
data/lib/tomlrb/local_date.rb
CHANGED
data/lib/tomlrb/local_time.rb
CHANGED
data/lib/tomlrb/parser.y
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class Tomlrb::GeneratedParser
|
2
|
-
token IDENTIFIER STRING_MULTI STRING_BASIC STRING_LITERAL_MULTI STRING_LITERAL DATETIME
|
2
|
+
token IDENTIFIER STRING_MULTI STRING_BASIC STRING_LITERAL_MULTI STRING_LITERAL DATETIME LOCAL_TIME INTEGER NON_DEC_INTEGER FLOAT FLOAT_KEYWORD BOOLEAN NEWLINE EOS
|
3
3
|
rule
|
4
4
|
expressions
|
5
5
|
| expressions expression
|
@@ -12,7 +12,8 @@ rule
|
|
12
12
|
| NEWLINE
|
13
13
|
;
|
14
14
|
table
|
15
|
-
: table_start table_continued
|
15
|
+
: table_start table_continued NEWLINE
|
16
|
+
| table_start table_continued EOS
|
16
17
|
;
|
17
18
|
table_start
|
18
19
|
: '[' '[' { @handler.start_(:array_of_tables) }
|
@@ -40,16 +41,12 @@ rule
|
|
40
41
|
;
|
41
42
|
table_identifier_component
|
42
43
|
: IDENTIFIER
|
43
|
-
| STRING_BASIC
|
44
|
+
| STRING_BASIC { result = StringUtils.replace_escaped_chars(val[0]) }
|
44
45
|
| STRING_LITERAL
|
45
46
|
| INTEGER
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
| FLOAT_INF
|
50
|
-
| FLOAT_NAN
|
51
|
-
| TRUE
|
52
|
-
| FALSE
|
47
|
+
| NON_DEC_INTEGER
|
48
|
+
| FLOAT_KEYWORD
|
49
|
+
| BOOLEAN
|
53
50
|
;
|
54
51
|
inline_table
|
55
52
|
: inline_table_start inline_table_end
|
@@ -61,38 +58,50 @@ rule
|
|
61
58
|
inline_table_end
|
62
59
|
: '}' {
|
63
60
|
array = @handler.end_(:inline)
|
64
|
-
|
65
|
-
@handler.push(Hash[*array])
|
61
|
+
@handler.push_inline(array)
|
66
62
|
}
|
67
63
|
;
|
68
64
|
inline_continued
|
69
|
-
:
|
70
|
-
|
|
65
|
+
: inline_assignment
|
66
|
+
| inline_assignment inline_next
|
71
67
|
;
|
72
68
|
inline_next
|
73
69
|
: ',' inline_continued
|
74
70
|
;
|
75
|
-
|
76
|
-
: inline_assignment_key '
|
77
|
-
|
78
|
-
|
79
|
-
@handler.start_(:inline)
|
80
|
-
@handler.push(val[2])
|
71
|
+
inline_assignment
|
72
|
+
: inline_assignment_key '=' value {
|
73
|
+
keys = @handler.end_(:inline_keys)
|
74
|
+
@handler.push(keys)
|
81
75
|
}
|
82
|
-
| IDENTIFIER { @handler.push(val[0]) }
|
83
76
|
;
|
84
|
-
|
85
|
-
: '
|
77
|
+
inline_assignment_key
|
78
|
+
: inline_assignment_key '.' assignment_key_component {
|
79
|
+
@handler.push(val[2])
|
80
|
+
}
|
81
|
+
| inline_assignment_key '.' FLOAT { val[2].split('.').each { |k| @handler.push(k) } }
|
82
|
+
| FLOAT {
|
83
|
+
keys = val[0].split('.')
|
84
|
+
@handler.start_(:inline_keys)
|
85
|
+
keys.each { |key| @handler.push(key) }
|
86
|
+
}
|
87
|
+
| assignment_key_component {
|
88
|
+
@handler.start_(:inline_keys)
|
89
|
+
@handler.push(val[0])
|
90
|
+
}
|
86
91
|
;
|
87
92
|
assignment
|
88
93
|
: assignment_key '=' value EOS {
|
89
94
|
keys = @handler.end_(:keys)
|
90
|
-
|
95
|
+
value = keys.pop
|
96
|
+
@handler.validate_value(value)
|
97
|
+
@handler.push(value)
|
91
98
|
@handler.assign(keys)
|
92
99
|
}
|
93
100
|
| assignment_key '=' value NEWLINE {
|
94
101
|
keys = @handler.end_(:keys)
|
95
|
-
|
102
|
+
value = keys.pop
|
103
|
+
@handler.validate_value(value)
|
104
|
+
@handler.push(value)
|
96
105
|
@handler.assign(keys)
|
97
106
|
}
|
98
107
|
;
|
@@ -108,30 +117,25 @@ rule
|
|
108
117
|
;
|
109
118
|
assignment_key_component
|
110
119
|
: IDENTIFIER
|
111
|
-
| STRING_BASIC
|
120
|
+
| STRING_BASIC { result = StringUtils.replace_escaped_chars(val[0]) }
|
112
121
|
| STRING_LITERAL
|
113
122
|
| INTEGER
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
| FLOAT_INF
|
118
|
-
| FLOAT_NAN
|
119
|
-
| TRUE
|
120
|
-
| FALSE
|
123
|
+
| NON_DEC_INTEGER
|
124
|
+
| FLOAT_KEYWORD
|
125
|
+
| BOOLEAN
|
121
126
|
;
|
122
127
|
array
|
123
128
|
: start_array array_continued
|
124
129
|
;
|
125
130
|
array_continued
|
126
|
-
: ']' { array = @handler.end_(:array); @handler.push(array) }
|
131
|
+
: ']' { array = @handler.end_(:array); @handler.push(array.compact) }
|
127
132
|
| value array_next
|
128
133
|
| NEWLINE array_continued
|
129
134
|
;
|
130
135
|
array_next
|
131
|
-
: ']' { array = @handler.end_(:array); @handler.push(array) }
|
136
|
+
: ']' { array = @handler.end_(:array); @handler.push(array.compact) }
|
132
137
|
| ',' array_continued
|
133
138
|
| NEWLINE array_continued
|
134
|
-
| ',' NEWLINE array_continued
|
135
139
|
;
|
136
140
|
start_array
|
137
141
|
: '[' { @handler.start_(:array) }
|
@@ -147,17 +151,41 @@ rule
|
|
147
151
|
;
|
148
152
|
literal
|
149
153
|
| FLOAT { result = val[0].to_f }
|
150
|
-
|
|
151
|
-
|
154
|
+
| FLOAT_KEYWORD {
|
155
|
+
v = val[0]
|
156
|
+
result = if v.end_with?('nan')
|
157
|
+
Float::NAN
|
158
|
+
else
|
159
|
+
(v[0] == '-' ? -1 : 1) * Float::INFINITY
|
160
|
+
end
|
161
|
+
}
|
152
162
|
| INTEGER { result = val[0].to_i }
|
153
|
-
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
163
|
+
| NON_DEC_INTEGER {
|
164
|
+
base = case val[0][1]
|
165
|
+
when "x" then 16
|
166
|
+
when "o" then 8
|
167
|
+
when "b" then 2
|
168
|
+
end
|
169
|
+
result = val[0].to_i(base)
|
170
|
+
}
|
171
|
+
| BOOLEAN { result = val[0] == 'true' ? true : false }
|
172
|
+
| DATETIME {
|
173
|
+
v = val[0]
|
174
|
+
result = if v[6].nil?
|
175
|
+
if v[4].nil?
|
176
|
+
LocalDate.new(v[0], v[1], v[2])
|
177
|
+
else
|
178
|
+
LocalDateTime.new(v[0], v[1], v[2], v[3] || 0, v[4] || 0, v[5].to_f)
|
179
|
+
end
|
180
|
+
else
|
181
|
+
# Patch for 24:00:00 which Ruby parses
|
182
|
+
if v[3].to_i == 24 && v[4].to_i == 0 && v[5].to_i == 0
|
183
|
+
v[3] = (v[3].to_i + 1).to_s
|
184
|
+
end
|
185
|
+
|
186
|
+
Time.new(v[0], v[1], v[2], v[3] || 0, v[4] || 0, v[5].to_f, v[6])
|
187
|
+
end
|
188
|
+
}
|
161
189
|
| LOCAL_TIME { result = LocalTime.new(*val[0]) }
|
162
190
|
;
|
163
191
|
string
|
data/lib/tomlrb/scanner.rb
CHANGED
@@ -5,24 +5,21 @@ module Tomlrb
|
|
5
5
|
COMMENT = /#[^\u0000-\u0008\u000A-\u001F\u007F]*/
|
6
6
|
IDENTIFIER = /[A-Za-z0-9_-]+/
|
7
7
|
SPACE = /[ \t]/
|
8
|
-
NEWLINE = /(\r?\n)
|
8
|
+
NEWLINE = /(?:[ \t]*(?:\r?\n)[ \t]*)+/
|
9
9
|
STRING_BASIC = /(["])(?:\\?[^\u0000-\u0008\u000A-\u001F\u007F])*?\1/
|
10
10
|
STRING_MULTI = /"{3}([^\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]*?(?<!\\)"{3,5})/m
|
11
11
|
STRING_LITERAL = /(['])(?:\\?[^\u0000-\u0008\u000A-\u001F\u007F])*?\1/
|
12
12
|
STRING_LITERAL_MULTI = /'{3}([^\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]*?'{3,5})/m
|
13
|
-
DATETIME = /(-?\d{4})-(\d{2})-(\d{2})(?:(?:t|\s)(\d{2}):(\d{2}):(\d{2}(?:\.\d+)?))?(z|[-+]\d{2}:\d{2})
|
14
|
-
LOCAL_DATETIME = /(-?\d{4})-(\d{2})-(\d{2})(?:t|\s)(\d{2}):(\d{2}):(\d{2}(?:\.\d+)?)/i
|
15
|
-
LOCAL_DATE = /(-?\d{4})-(\d{2})-(\d{2})/
|
13
|
+
DATETIME = /(-?\d{4})-(\d{2})-(\d{2})(?:(?:t|\s)(\d{2}):(\d{2}):(\d{2}(?:\.\d+)?))?(z|[-+]\d{2}:\d{2})?/i
|
16
14
|
LOCAL_TIME = /(\d{2}):(\d{2}):(\d{2}(?:\.\d+)?)/
|
17
|
-
FLOAT = /[+-]?(?:(?:\d|[1-9](?:_?\d)*)\.\d(?:_?\d)*|\d+(?=[eE]))(?:[eE][+-]?[0-
|
18
|
-
|
19
|
-
FLOAT_NAN = /[+-]?nan\b/
|
15
|
+
FLOAT = /[+-]?(?:(?:\d|[1-9](?:_?\d)*)\.\d(?:_?\d)*|\d+(?=[eE]))(?:[eE][+-]?[0-9]+(_[0-9])*[0-9]*)?(?!\w)/
|
16
|
+
FLOAT_KEYWORD = /[+-]?(?:inf|nan)\b/
|
20
17
|
INTEGER = /[+-]?([1-9](_?\d)*|0)(?![A-Za-z0-9_-]+)/
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
18
|
+
NON_DEC_INTEGER = /0(?:x[0-9A-Fa-f]+(?:_[0-9A-Fa-f])*[0-9A-Fa-f]*|o[0-7]+(?:_[0-7])*[0-7]*|b[01]+(?:_[01])*[01]*)/
|
19
|
+
BOOLEAN = /true|false/
|
20
|
+
SPACED_ARRAY_OF_TABLES_START = /^\[[ \t]+\[(#{IDENTIFIER}|#{STRING_BASIC}|#{STRING_LITERAL}|#{INTEGER}|#{NON_DEC_INTEGER}|#{FLOAT_KEYWORD}|#{BOOLEAN})\]\]$/
|
21
|
+
SPACED_ARRAY_OF_TABLES_END = /^\[\[(#{IDENTIFIER}|#{STRING_BASIC}|#{STRING_LITERAL}|#{INTEGER}|#{NON_DEC_INTEGER}|#{FLOAT_KEYWORD}|#{BOOLEAN})\][ \t]+\]$/
|
22
|
+
SPACED_ARRAY_OF_TABLES_BOTH = /^\[[ \t]+\[(#{IDENTIFIER}|#{STRING_BASIC}|#{STRING_LITERAL}|#{INTEGER}|#{NON_DEC_INTEGER}|#{FLOAT_KEYWORD}|#{BOOLEAN})\][ \t]+\]$/
|
26
23
|
|
27
24
|
def initialize(io)
|
28
25
|
@ss = StringScanner.new(io.read)
|
@@ -31,52 +28,37 @@ module Tomlrb
|
|
31
28
|
|
32
29
|
def next_token
|
33
30
|
case
|
34
|
-
when @ss.
|
31
|
+
when @ss.scan(NEWLINE) then [:NEWLINE, nil]
|
32
|
+
when @ss.scan(SPACED_ARRAY_OF_TABLES_START) then raise ParseError.new("Array of tables has spaces in starting brackets")
|
33
|
+
when @ss.scan(SPACED_ARRAY_OF_TABLES_END) then raise ParseError.new("Array of tables has spaces in ending brackets")
|
34
|
+
when @ss.scan(SPACED_ARRAY_OF_TABLES_BOTH) then raise ParseError.new("Array of tables has spaces in starting and ending brackets")
|
35
35
|
when @ss.scan(SPACE) then next_token
|
36
36
|
when @ss.scan(COMMENT) then next_token
|
37
37
|
when @ss.scan(DATETIME) then process_datetime
|
38
|
-
when @ss.scan(LOCAL_DATETIME) then process_local_datetime
|
39
|
-
when @ss.scan(LOCAL_DATE) then process_local_date
|
40
38
|
when @ss.scan(LOCAL_TIME) then process_local_time
|
41
39
|
when text = @ss.scan(STRING_MULTI) then [:STRING_MULTI, text[3..-4]]
|
42
40
|
when text = @ss.scan(STRING_BASIC) then [:STRING_BASIC, text[1..-2]]
|
43
41
|
when text = @ss.scan(STRING_LITERAL_MULTI) then [:STRING_LITERAL_MULTI, text[3..-4]]
|
44
42
|
when text = @ss.scan(STRING_LITERAL) then [:STRING_LITERAL, text[1..-2]]
|
45
43
|
when text = @ss.scan(FLOAT) then [:FLOAT, text]
|
46
|
-
when text = @ss.scan(
|
47
|
-
when text = @ss.scan(FLOAT_NAN) then [:FLOAT_NAN, text]
|
44
|
+
when text = @ss.scan(FLOAT_KEYWORD) then [:FLOAT_KEYWORD, text]
|
48
45
|
when text = @ss.scan(INTEGER) then [:INTEGER, text]
|
49
|
-
when text = @ss.scan(
|
50
|
-
when text = @ss.scan(
|
51
|
-
when text = @ss.scan(BIN_INTEGER) then [:BIN_INTEGER, text]
|
52
|
-
when text = @ss.scan(TRUE) then [:TRUE, text]
|
53
|
-
when text = @ss.scan(FALSE) then [:FALSE, text]
|
54
|
-
when text = @ss.scan(NEWLINE) then [:NEWLINE, text]
|
46
|
+
when text = @ss.scan(NON_DEC_INTEGER) then [:NON_DEC_INTEGER, text]
|
47
|
+
when text = @ss.scan(BOOLEAN) then [:BOOLEAN, text]
|
55
48
|
when text = @ss.scan(IDENTIFIER) then [:IDENTIFIER, text]
|
49
|
+
when @ss.eos? then process_eos
|
56
50
|
else x = @ss.getch; [x, x]
|
57
51
|
end
|
58
52
|
end
|
59
53
|
|
60
54
|
def process_datetime
|
61
|
-
if @ss[7]
|
62
|
-
offset = '+00:00'
|
63
|
-
else
|
64
|
-
offset = @ss[7].gsub('Z', '+00:00')
|
55
|
+
if @ss[7]
|
56
|
+
offset = @ss[7].gsub(/[zZ]/, '+00:00')
|
65
57
|
end
|
66
|
-
args = [@ss[1], @ss[2], @ss[3], @ss[4]
|
58
|
+
args = [@ss[1], @ss[2], @ss[3], @ss[4], @ss[5], @ss[6], offset]
|
67
59
|
[:DATETIME, args]
|
68
60
|
end
|
69
61
|
|
70
|
-
def process_local_datetime
|
71
|
-
args = [@ss[1], @ss[2], @ss[3], @ss[4] || 0, @ss[5] || 0, @ss[6].to_f]
|
72
|
-
[:LOCAL_DATETIME, args]
|
73
|
-
end
|
74
|
-
|
75
|
-
def process_local_date
|
76
|
-
args = [@ss[1], @ss[2], @ss[3]]
|
77
|
-
[:LOCAL_DATE, args]
|
78
|
-
end
|
79
|
-
|
80
62
|
def process_local_time
|
81
63
|
args = [@ss[1], @ss[2], @ss[3].to_f]
|
82
64
|
[:LOCAL_TIME, args]
|
data/lib/tomlrb/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
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.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Francois Bernier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
11
|
+
date: 2022-05-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: psych
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4'
|
13
27
|
description: A racc based toml parser
|
14
28
|
email:
|
15
29
|
- frankbernier@gmail.com
|
@@ -48,7 +62,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
48
62
|
- !ruby/object:Gem::Version
|
49
63
|
version: '0'
|
50
64
|
requirements: []
|
51
|
-
rubygems_version: 3.
|
65
|
+
rubygems_version: 3.3.7
|
52
66
|
signing_key:
|
53
67
|
specification_version: 4
|
54
68
|
summary: A racc based toml parser
|