New Upstream Release - ruby-tomlrb
Ready changes
Summary
Merged new upstream version: 2.0.3 (was: 1.3.0).
Resulting package
Built on 2022-10-17T22:49 (took 5m53s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-releases ruby-tomlrb
Lintian Result
Diff
diff --git a/debian/changelog b/debian/changelog
index 31d9fef..ab5e3b4 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,9 +1,10 @@
-ruby-tomlrb (1.3.0-3) UNRELEASED; urgency=medium
+ruby-tomlrb (2.0.3-1) UNRELEASED; urgency=medium
* Set upstream metadata fields: Repository-Browse.
* Update standards version to 4.6.1, no changes needed.
+ * New upstream release.
- -- Debian Janitor <janitor@jelmer.uk> Mon, 17 Oct 2022 11:57:20 -0000
+ -- Debian Janitor <janitor@jelmer.uk> Mon, 17 Oct 2022 22:43:53 -0000
ruby-tomlrb (1.3.0-2) unstable; urgency=medium
diff --git a/lib/tomlrb.rb b/lib/tomlrb.rb
index 63e4e09..3a48631 100644
--- a/lib/tomlrb.rb
+++ b/lib/tomlrb.rb
@@ -1,6 +1,9 @@
require 'time'
require 'stringio'
require "tomlrb/version"
+require 'tomlrb/local_date_time'
+require 'tomlrb/local_date'
+require 'tomlrb/local_time'
require 'tomlrb/string_utils'
require "tomlrb/scanner"
require "tomlrb/parser"
diff --git a/lib/tomlrb/generated_parser.rb b/lib/tomlrb/generated_parser.rb
index edbcbe0..f2e3fb5 100644
--- a/lib/tomlrb/generated_parser.rb
+++ b/lib/tomlrb/generated_parser.rb
@@ -1,7 +1,7 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16.pre.1
-# from Racc grammer file "".
+# This file is automatically generated by Racc 1.6.0
+# from Racc grammar file "".
#
require 'racc/parser.rb'
@@ -10,160 +10,185 @@ module Tomlrb
##### State transition tables begin ###
racc_action_table = [
- 2, 17, 11, 31, 12, 31, 13, 79, 14, 40,
- 41, 80, 15, 16, 8, 71, 72, 10, 27, 29,
- 32, 29, 59, 60, 61, 62, 58, 55, 52, 53,
- 54, 56, 57, 46, 33, 34, 10, 59, 60, 61,
- 62, 58, 55, 52, 53, 54, 56, 57, 46, 35,
- 36, 10, 59, 60, 61, 62, 58, 55, 52, 53,
- 54, 56, 57, 46, 37, 38, 10, 59, 60, 61,
- 62, 58, 55, 52, 53, 54, 56, 57, 46, 43,
- 68, 10, 59, 60, 61, 62, 58, 55, 52, 53,
- 54, 56, 57, 46, nil, nil, 10, 59, 60, 61,
- 62, 58, 55, 52, 53, 54, 56, 57, 46, nil,
- nil, 10, 59, 60, 61, 62, 58, 55, 52, 53,
- 54, 56, 57, 46, nil, nil, 10, 59, 60, 61,
- 62, 58, 55, 52, 53, 54, 56, 57, 46, 75,
- nil, 10, 59, 60, 61, 62, 58, 55, 52, 53,
- 54, 56, 57, 46, 75, 21, 10, 22, nil, 23,
- nil, 24, nil, nil, nil, 25, 26, 21, 19, 22,
- nil, 23, nil, 24, nil, nil, nil, 25, 26, nil,
- 19 ]
+ 2, 45, 16, 56, 17, 44, 18, 55, 23, 19,
+ 20, 14, 21, 22, 8, 4, 10, 36, 16, 12,
+ 17, 48, 18, 46, 47, 19, 20, 42, 21, 22,
+ 50, 51, 87, 86, 39, 54, 39, 72, 73, 74,
+ 75, 70, 71, 67, 68, 65, 66, 69, 78, nil,
+ 59, nil, nil, 12, 72, 73, 74, 75, 70, 71,
+ 67, 68, 65, 66, 69, nil, nil, 59, nil, nil,
+ 12, 72, 73, 74, 75, 70, 71, 67, 68, 65,
+ 66, 69, 91, nil, 59, 89, nil, 12, 72, 73,
+ 74, 75, 70, 71, 67, 68, 65, 66, 69, 91,
+ nil, 59, 89, nil, 12, 72, 73, 74, 75, 70,
+ 71, 67, 68, 65, 66, 69, 91, nil, 59, 89,
+ nil, 12, 72, 73, 74, 75, 70, 71, 67, 68,
+ 65, 66, 69, 91, nil, 59, 89, 29, 12, 30,
+ nil, 31, nil, nil, 32, 33, 27, 34, 35, 29,
+ nil, 30, 25, 31, nil, nil, 32, 33, 81, 34,
+ 35, 16, nil, 17, 25, 18, nil, nil, 19, 20,
+ 77, 21, 22, 16, nil, 17, nil, 18, nil, nil,
+ 19, 20, 42, 21, 22, 16, nil, 17, nil, 18,
+ nil, nil, 19, 20, 85, 21, 22, 95, nil, nil,
+ 93, nil, nil, nil, 94 ]
racc_action_check = [
- 1, 2, 1, 9, 1, 72, 1, 76, 1, 20,
- 20, 76, 1, 1, 1, 42, 42, 1, 8, 9,
- 11, 72, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 12, 13, 32, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 14,
- 15, 33, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 16, 19, 34, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 30,
- 40, 35, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, nil, nil, 36, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, nil,
- nil, 37, 43, 43, 43, 43, 43, 43, 43, 43,
- 43, 43, 43, 43, nil, nil, 43, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- nil, 45, 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 7, 80, 7, nil, 7,
- nil, 7, nil, nil, nil, 7, 7, 41, 7, 41,
- nil, 41, nil, 41, nil, nil, nil, 41, 41, nil,
- 41 ]
+ 1, 13, 1, 41, 1, 13, 1, 41, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 10, 11, 1,
+ 11, 25, 11, 24, 24, 11, 11, 11, 11, 11,
+ 26, 26, 57, 57, 38, 40, 11, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 50, nil,
+ 44, nil, nil, 44, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, nil, nil, 55, nil, nil,
+ 55, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, nil, 58, 58, nil, 58, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ nil, 91, 91, nil, 91, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, nil, 94, 94,
+ nil, 94, 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, nil, 95, 95, 9, 95, 9,
+ nil, 9, nil, nil, 9, 9, 9, 9, 9, 51,
+ nil, 51, 9, 51, nil, nil, 51, 51, 51, 51,
+ 51, 45, nil, 45, 51, 45, nil, nil, 45, 45,
+ 45, 45, 45, 54, nil, 54, nil, 54, nil, nil,
+ 54, 54, 54, 54, 54, 56, nil, 56, nil, 56,
+ nil, nil, 56, 56, 56, 56, 56, 90, nil, nil,
+ 90, nil, nil, nil, 90 ]
racc_action_pointer = [
- nil, 0, 1, nil, nil, nil, nil, 153, 4, 1,
- nil, 0, 14, 15, 29, 30, 44, nil, nil, 50,
- -6, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 59, nil, 19, 34, 49, 64, 79, 94, nil, nil,
- 65, 165, -3, 109, nil, 124, nil, nil, nil, nil,
+ nil, 0, 8, nil, nil, nil, nil, nil, nil, 135,
+ 1, 16, nil, -17, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, 9, 4, 13, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, 14, nil,
+ 14, -15, nil, nil, 34, 159, nil, nil, nil, nil,
+ 31, 147, nil, nil, 171, 51, 183, 18, 68, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 3, nil, nil, nil, -8, nil, nil, nil,
- 139, nil ]
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ 183, 85, nil, nil, 102, 119, nil, nil, nil ]
racc_action_default = [
- -1, -58, -58, -2, -3, -4, -5, -58, -8, -58,
- -22, -58, -58, -58, -58, -58, -58, 82, -6, -10,
- -58, -15, -16, -17, -18, -19, -20, -7, -21, -23,
- -58, -27, -46, -46, -46, -46, -46, -46, -9, -11,
- -13, -58, -58, -46, -29, -46, -40, -41, -42, -43,
- -44, -45, -47, -48, -49, -50, -51, -52, -53, -54,
- -55, -56, -57, -30, -31, -32, -33, -34, -12, -14,
- -24, -25, -58, -28, -35, -36, -58, -26, -37, -38,
- -46, -39 ]
+ -1, -79, -79, -2, -3, -4, -5, -6, -7, -79,
+ -11, -79, -31, -79, -45, -46, -47, -48, -49, -50,
+ -51, -52, -53, 99, -79, -13, -79, -20, -21, -22,
+ -23, -24, -25, -26, -27, -28, -10, -29, -79, -32,
+ -33, -79, -39, -40, -67, -79, -8, -9, -12, -14,
+ -16, -79, -30, -34, -79, -67, -79, -79, -67, -61,
+ -62, -63, -64, -65, -66, -68, -69, -70, -71, -72,
+ -73, -74, -75, -76, -77, -78, -43, -44, -15, -17,
+ -18, -19, -35, -36, -37, -38, -41, -42, -54, -55,
+ -79, -67, -56, -58, -67, -67, -57, -59, -60 ]
racc_goto_table = [
- 28, 74, 1, 18, 44, 63, 64, 65, 66, 67,
- 3, 4, 5, 6, 7, 73, 39, 42, 70, 78,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 81, 69, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ 15, 24, 38, 88, 28, 37, 57, 1, 3, 5,
+ 6, 7, 9, 49, 53, 13, 92, 83, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 77 ]
+ nil, nil, 52, nil, nil, nil, 96, nil, nil, 97,
+ 98, nil, nil, 79, 76, 82, 80, nil, nil, nil,
+ nil, nil, nil, nil, nil, 84 ]
racc_goto_check = [
- 11, 18, 1, 7, 15, 15, 15, 15, 15, 15,
- 2, 3, 4, 5, 6, 15, 9, 13, 14, 19,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 18, 7, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ 18, 7, 13, 22, 10, 12, 17, 1, 2, 3,
+ 4, 5, 6, 9, 15, 19, 23, 17, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 11 ]
+ nil, nil, 12, nil, nil, nil, 22, nil, nil, 22,
+ 22, nil, nil, 7, 18, 13, 10, nil, nil, nil,
+ nil, nil, nil, nil, nil, 18 ]
racc_goto_pointer = [
- nil, 2, 9, 10, 11, 12, 13, -4, nil, -4,
- nil, -9, nil, -13, -24, -28, nil, nil, -44, -57,
- nil, nil, nil ]
+ nil, 7, 7, 8, 9, 10, 11, -8, nil, -13,
+ -5, nil, -6, -9, nil, -26, nil, -38, -1, 14,
+ nil, nil, -55, -74, nil, nil, nil ]
racc_goto_default = [
- nil, nil, nil, nil, nil, 49, nil, nil, 20, nil,
- 9, nil, 30, nil, nil, 76, 48, 45, nil, nil,
- 47, 50, 51 ]
+ nil, nil, nil, nil, nil, 62, nil, nil, 26, nil,
+ nil, 11, nil, nil, 40, nil, 41, 90, 43, nil,
+ 61, 58, nil, nil, 60, 63, 64 ]
racc_reduce_table = [
0, 0, :racc_error,
- 0, 22, :_reduce_none,
- 2, 22, :_reduce_none,
- 1, 23, :_reduce_none,
- 1, 23, :_reduce_none,
- 1, 23, :_reduce_none,
+ 0, 24, :_reduce_none,
2, 24, :_reduce_none,
- 2, 27, :_reduce_7,
- 1, 27, :_reduce_8,
- 2, 28, :_reduce_9,
- 1, 28, :_reduce_10,
- 2, 28, :_reduce_none,
+ 2, 24, :_reduce_none,
+ 1, 25, :_reduce_none,
+ 1, 25, :_reduce_none,
+ 1, 25, :_reduce_none,
+ 1, 25, :_reduce_none,
+ 3, 26, :_reduce_none,
+ 3, 26, :_reduce_none,
+ 2, 29, :_reduce_10,
+ 1, 29, :_reduce_11,
2, 30, :_reduce_12,
1, 30, :_reduce_13,
2, 30, :_reduce_none,
- 1, 29, :_reduce_15,
- 1, 29, :_reduce_16,
- 1, 29, :_reduce_17,
- 1, 29, :_reduce_18,
- 1, 29, :_reduce_19,
- 1, 29, :_reduce_20,
- 2, 26, :_reduce_none,
- 1, 31, :_reduce_22,
- 1, 32, :_reduce_23,
- 3, 32, :_reduce_none,
- 1, 35, :_reduce_25,
- 2, 35, :_reduce_none,
- 1, 33, :_reduce_27,
- 2, 34, :_reduce_none,
- 3, 25, :_reduce_29,
- 3, 25, :_reduce_30,
- 3, 25, :_reduce_31,
- 3, 25, :_reduce_32,
- 3, 25, :_reduce_33,
- 3, 25, :_reduce_34,
- 2, 37, :_reduce_none,
- 1, 39, :_reduce_36,
- 2, 39, :_reduce_none,
- 1, 40, :_reduce_38,
- 2, 40, :_reduce_none,
- 1, 38, :_reduce_40,
- 1, 36, :_reduce_41,
- 1, 36, :_reduce_none,
+ 2, 32, :_reduce_15,
+ 1, 32, :_reduce_16,
+ 2, 32, :_reduce_none,
+ 3, 31, :_reduce_18,
+ 3, 31, :_reduce_19,
+ 1, 31, :_reduce_20,
+ 1, 31, :_reduce_21,
+ 1, 33, :_reduce_none,
+ 1, 33, :_reduce_23,
+ 1, 33, :_reduce_none,
+ 1, 33, :_reduce_none,
+ 1, 33, :_reduce_none,
+ 1, 33, :_reduce_none,
+ 1, 33, :_reduce_none,
+ 2, 28, :_reduce_none,
+ 3, 28, :_reduce_none,
+ 1, 34, :_reduce_31,
+ 1, 35, :_reduce_32,
1, 36, :_reduce_none,
+ 2, 36, :_reduce_none,
+ 2, 38, :_reduce_none,
+ 3, 37, :_reduce_36,
+ 3, 39, :_reduce_37,
+ 3, 39, :_reduce_38,
+ 1, 39, :_reduce_39,
+ 1, 39, :_reduce_40,
+ 4, 27, :_reduce_41,
+ 4, 27, :_reduce_42,
+ 3, 42, :_reduce_43,
+ 3, 42, :_reduce_44,
+ 1, 42, :_reduce_45,
+ 1, 42, :_reduce_46,
1, 41, :_reduce_none,
+ 1, 41, :_reduce_48,
1, 41, :_reduce_none,
- 0, 43, :_reduce_none,
- 1, 43, :_reduce_47,
- 1, 43, :_reduce_48,
- 1, 43, :_reduce_49,
- 1, 43, :_reduce_50,
- 1, 43, :_reduce_51,
- 1, 43, :_reduce_52,
- 1, 43, :_reduce_53,
- 1, 42, :_reduce_54,
- 1, 42, :_reduce_55,
- 1, 42, :_reduce_56,
- 1, 42, :_reduce_57 ]
-
-racc_reduce_n = 58
-
-racc_shift_n = 82
+ 1, 41, :_reduce_none,
+ 1, 41, :_reduce_none,
+ 1, 41, :_reduce_none,
+ 1, 41, :_reduce_none,
+ 2, 43, :_reduce_none,
+ 1, 45, :_reduce_55,
+ 2, 45, :_reduce_none,
+ 2, 45, :_reduce_none,
+ 1, 46, :_reduce_58,
+ 2, 46, :_reduce_none,
+ 2, 46, :_reduce_none,
+ 1, 44, :_reduce_61,
+ 1, 40, :_reduce_62,
+ 1, 40, :_reduce_none,
+ 1, 40, :_reduce_none,
+ 1, 47, :_reduce_none,
+ 1, 47, :_reduce_none,
+ 0, 49, :_reduce_none,
+ 1, 49, :_reduce_68,
+ 1, 49, :_reduce_69,
+ 1, 49, :_reduce_70,
+ 1, 49, :_reduce_71,
+ 1, 49, :_reduce_72,
+ 1, 49, :_reduce_73,
+ 1, 49, :_reduce_74,
+ 1, 48, :_reduce_75,
+ 1, 48, :_reduce_76,
+ 1, 48, :_reduce_77,
+ 1, 48, :_reduce_78 ]
+
+racc_reduce_n = 79
+
+racc_shift_n = 99
racc_token_table = {
false => 0,
@@ -174,21 +199,23 @@ racc_token_table = {
:STRING_LITERAL_MULTI => 5,
:STRING_LITERAL => 6,
:DATETIME => 7,
- :INTEGER => 8,
- :FLOAT => 9,
- :FLOAT_INF => 10,
- :FLOAT_NAN => 11,
- :TRUE => 12,
- :FALSE => 13,
- "[" => 14,
- "]" => 15,
- "." => 16,
- "{" => 17,
- "}" => 18,
- "," => 19,
- "=" => 20 }
-
-racc_nt_base = 21
+ :LOCAL_TIME => 8,
+ :INTEGER => 9,
+ :NON_DEC_INTEGER => 10,
+ :FLOAT => 11,
+ :FLOAT_KEYWORD => 12,
+ :BOOLEAN => 13,
+ :NEWLINE => 14,
+ :EOS => 15,
+ "[" => 16,
+ "]" => 17,
+ "." => 18,
+ "{" => 19,
+ "}" => 20,
+ "," => 21,
+ "=" => 22 }
+
+racc_nt_base = 23
racc_use_result_var = true
@@ -217,12 +244,14 @@ Racc_token_to_s_table = [
"STRING_LITERAL_MULTI",
"STRING_LITERAL",
"DATETIME",
+ "LOCAL_TIME",
"INTEGER",
+ "NON_DEC_INTEGER",
"FLOAT",
- "FLOAT_INF",
- "FLOAT_NAN",
- "TRUE",
- "FALSE",
+ "FLOAT_KEYWORD",
+ "BOOLEAN",
+ "NEWLINE",
+ "EOS",
"\"[\"",
"\"]\"",
"\".\"",
@@ -240,12 +269,16 @@ Racc_token_to_s_table = [
"table_continued",
"table_identifier",
"table_next",
+ "table_identifier_component",
"inline_table_start",
+ "inline_table_end",
"inline_continued",
- "inline_assignment_key",
- "inline_assignment_value",
+ "inline_assignment",
"inline_next",
+ "inline_assignment_key",
"value",
+ "assignment_key_component",
+ "assignment_key",
"array",
"start_array",
"array_continued",
@@ -272,291 +305,398 @@ Racc_debug_parser = false
# reduce 6 omitted
-module_eval(<<'.,.,', 'parser.y', 15)
- def _reduce_7(val, _values, result)
+# reduce 7 omitted
+
+# reduce 8 omitted
+
+# reduce 9 omitted
+
+module_eval(<<'.,.,', 'parser.y', 18)
+ def _reduce_10(val, _values, result)
@handler.start_(:array_of_tables)
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 16)
- def _reduce_8(val, _values, result)
+module_eval(<<'.,.,', 'parser.y', 19)
+ def _reduce_11(val, _values, result)
@handler.start_(:table)
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 19)
- def _reduce_9(val, _values, result)
+module_eval(<<'.,.,', 'parser.y', 22)
+ def _reduce_12(val, _values, result)
array = @handler.end_(:array_of_tables); @handler.set_context(array, is_array_of_tables: true)
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 20)
- def _reduce_10(val, _values, result)
+module_eval(<<'.,.,', 'parser.y', 23)
+ def _reduce_13(val, _values, result)
array = @handler.end_(:table); @handler.set_context(array)
result
end
.,.,
-# reduce 11 omitted
+# reduce 14 omitted
-module_eval(<<'.,.,', 'parser.y', 24)
- def _reduce_12(val, _values, result)
+module_eval(<<'.,.,', 'parser.y', 27)
+ def _reduce_15(val, _values, result)
array = @handler.end_(:array_of_tables); @handler.set_context(array, is_array_of_tables: true)
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 25)
- def _reduce_13(val, _values, result)
+module_eval(<<'.,.,', 'parser.y', 28)
+ def _reduce_16(val, _values, result)
array = @handler.end_(:table); @handler.set_context(array)
result
end
.,.,
-# reduce 14 omitted
+# reduce 17 omitted
-module_eval(<<'.,.,', 'parser.y', 29)
- def _reduce_15(val, _values, result)
- @handler.push(val[0])
+module_eval(<<'.,.,', 'parser.y', 32)
+ def _reduce_18(val, _values, result)
+ @handler.push(val[2])
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 30)
- def _reduce_16(val, _values, result)
- @handler.push(val[0])
+module_eval(<<'.,.,', 'parser.y', 33)
+ def _reduce_19(val, _values, result)
+ val[2].split('.').each { |k| @handler.push(k) }
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 31)
- def _reduce_17(val, _values, result)
- @handler.push(val[0])
+module_eval(<<'.,.,', 'parser.y', 35)
+ def _reduce_20(val, _values, result)
+ keys = val[0].split('.')
+ @handler.start_(:table)
+ keys.each { |key| @handler.push(key) }
+
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 32)
- def _reduce_18(val, _values, result)
+module_eval(<<'.,.,', 'parser.y', 39)
+ def _reduce_21(val, _values, result)
@handler.push(val[0])
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 33)
- def _reduce_19(val, _values, result)
- @handler.push(val[0])
+# reduce 22 omitted
+
+module_eval(<<'.,.,', 'parser.y', 43)
+ def _reduce_23(val, _values, result)
+ result = StringUtils.replace_escaped_chars(val[0])
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 34)
- def _reduce_20(val, _values, result)
- @handler.push(val[0])
+# reduce 24 omitted
+
+# reduce 25 omitted
+
+# reduce 26 omitted
+
+# reduce 27 omitted
+
+# reduce 28 omitted
+
+# reduce 29 omitted
+
+# reduce 30 omitted
+
+module_eval(<<'.,.,', 'parser.y', 55)
+ def _reduce_31(val, _values, result)
+ @handler.start_(:inline)
result
end
.,.,
-# reduce 21 omitted
+module_eval(<<'.,.,', 'parser.y', 59)
+ def _reduce_32(val, _values, result)
+ array = @handler.end_(:inline)
+ @handler.push_inline(array)
-module_eval(<<'.,.,', 'parser.y', 40)
- def _reduce_22(val, _values, result)
- @handler.start_(:inline)
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 43)
- def _reduce_23(val, _values, result)
- array = @handler.end_(:inline); @handler.push(Hash[*array])
+# reduce 33 omitted
+
+# reduce 34 omitted
+
+# reduce 35 omitted
+
+module_eval(<<'.,.,', 'parser.y', 72)
+ def _reduce_36(val, _values, result)
+ keys = @handler.end_(:inline_keys)
+ @handler.push(keys)
+
result
end
.,.,
-# reduce 24 omitted
+module_eval(<<'.,.,', 'parser.y', 78)
+ def _reduce_37(val, _values, result)
+ @handler.push(val[2])
-module_eval(<<'.,.,', 'parser.y', 48)
- def _reduce_25(val, _values, result)
- array = @handler.end_(:inline)
- array.map!.with_index{ |n,i| i.even? ? n.to_sym : n } if @handler.symbolize_keys
- @handler.push(Hash[*array])
+ result
+ end
+.,.,
+module_eval(<<'.,.,', 'parser.y', 80)
+ def _reduce_38(val, _values, result)
+ val[2].split('.').each { |k| @handler.push(k) }
result
end
.,.,
-# reduce 26 omitted
+module_eval(<<'.,.,', 'parser.y', 82)
+ def _reduce_39(val, _values, result)
+ keys = val[0].split('.')
+ @handler.start_(:inline_keys)
+ keys.each { |key| @handler.push(key) }
-module_eval(<<'.,.,', 'parser.y', 55)
- def _reduce_27(val, _values, result)
- @handler.push(val[0])
result
end
.,.,
-# reduce 28 omitted
+module_eval(<<'.,.,', 'parser.y', 87)
+ def _reduce_40(val, _values, result)
+ @handler.start_(:inline_keys)
+ @handler.push(val[0])
-module_eval(<<'.,.,', 'parser.y', 61)
- def _reduce_29(val, _values, result)
- @handler.assign(val[0])
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 62)
- def _reduce_30(val, _values, result)
- @handler.assign(val[0])
+module_eval(<<'.,.,', 'parser.y', 93)
+ def _reduce_41(val, _values, result)
+ keys = @handler.end_(:keys)
+ value = keys.pop
+ @handler.validate_value(value)
+ @handler.push(value)
+ @handler.assign(keys)
+
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 63)
- def _reduce_31(val, _values, result)
- @handler.assign(val[0])
+module_eval(<<'.,.,', 'parser.y', 100)
+ def _reduce_42(val, _values, result)
+ keys = @handler.end_(:keys)
+ value = keys.pop
+ @handler.validate_value(value)
+ @handler.push(value)
+ @handler.assign(keys)
+
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 64)
- def _reduce_32(val, _values, result)
- @handler.assign(val[0])
+module_eval(<<'.,.,', 'parser.y', 108)
+ def _reduce_43(val, _values, result)
+ @handler.push(val[2])
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 65)
- def _reduce_33(val, _values, result)
- @handler.assign(val[0])
+module_eval(<<'.,.,', 'parser.y', 109)
+ def _reduce_44(val, _values, result)
+ val[2].split('.').each { |k| @handler.push(k) }
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 66)
- def _reduce_34(val, _values, result)
- @handler.assign(val[0])
+module_eval(<<'.,.,', 'parser.y', 111)
+ def _reduce_45(val, _values, result)
+ keys = val[0].split('.')
+ @handler.start_(:keys)
+ keys.each { |key| @handler.push(key) }
+
result
end
.,.,
-# reduce 35 omitted
+module_eval(<<'.,.,', 'parser.y', 115)
+ def _reduce_46(val, _values, result)
+ @handler.start_(:keys); @handler.push(val[0])
+ result
+ end
+.,.,
-module_eval(<<'.,.,', 'parser.y', 72)
- def _reduce_36(val, _values, result)
- array = @handler.end_(:array); @handler.push(array)
+# reduce 47 omitted
+
+module_eval(<<'.,.,', 'parser.y', 119)
+ def _reduce_48(val, _values, result)
+ result = StringUtils.replace_escaped_chars(val[0])
result
end
.,.,
-# reduce 37 omitted
+# reduce 49 omitted
-module_eval(<<'.,.,', 'parser.y', 76)
- def _reduce_38(val, _values, result)
- array = @handler.end_(:array); @handler.push(array)
+# reduce 50 omitted
+
+# reduce 51 omitted
+
+# reduce 52 omitted
+
+# reduce 53 omitted
+
+# reduce 54 omitted
+
+module_eval(<<'.,.,', 'parser.y', 130)
+ def _reduce_55(val, _values, result)
+ array = @handler.end_(:array); @handler.push(array.compact)
result
end
.,.,
-# reduce 39 omitted
+# reduce 56 omitted
-module_eval(<<'.,.,', 'parser.y', 80)
- def _reduce_40(val, _values, result)
+# reduce 57 omitted
+
+module_eval(<<'.,.,', 'parser.y', 135)
+ def _reduce_58(val, _values, result)
+ array = @handler.end_(:array); @handler.push(array.compact)
+ result
+ end
+.,.,
+
+# reduce 59 omitted
+
+# reduce 60 omitted
+
+module_eval(<<'.,.,', 'parser.y', 140)
+ def _reduce_61(val, _values, result)
@handler.start_(:array)
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 83)
- def _reduce_41(val, _values, result)
+module_eval(<<'.,.,', 'parser.y', 143)
+ def _reduce_62(val, _values, result)
@handler.push(val[0])
result
end
.,.,
-# reduce 42 omitted
+# reduce 63 omitted
-# reduce 43 omitted
+# reduce 64 omitted
-# reduce 44 omitted
+# reduce 65 omitted
-# reduce 45 omitted
+# reduce 66 omitted
-# reduce 46 omitted
+# reduce 67 omitted
-module_eval(<<'.,.,', 'parser.y', 92)
- def _reduce_47(val, _values, result)
+module_eval(<<'.,.,', 'parser.y', 152)
+ def _reduce_68(val, _values, result)
result = val[0].to_f
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 93)
- def _reduce_48(val, _values, result)
- result = (val[0][0] == '-' ? -1 : 1) * Float::INFINITY
+module_eval(<<'.,.,', 'parser.y', 154)
+ def _reduce_69(val, _values, result)
+ v = val[0]
+ result = if v.end_with?('nan')
+ Float::NAN
+ else
+ (v[0] == '-' ? -1 : 1) * Float::INFINITY
+ end
+
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 94)
- def _reduce_49(val, _values, result)
- result = Float::NAN
+module_eval(<<'.,.,', 'parser.y', 161)
+ def _reduce_70(val, _values, result)
+ result = val[0].to_i
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 95)
- def _reduce_50(val, _values, result)
- result = val[0].to_i
+module_eval(<<'.,.,', 'parser.y', 163)
+ def _reduce_71(val, _values, result)
+ base = case val[0][1]
+ when "x" then 16
+ when "o" then 8
+ when "b" then 2
+ end
+ result = val[0].to_i(base)
+
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 96)
- def _reduce_51(val, _values, result)
- result = true
+module_eval(<<'.,.,', 'parser.y', 170)
+ def _reduce_72(val, _values, result)
+ result = val[0] == 'true' ? true : false
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 97)
- def _reduce_52(val, _values, result)
- result = false
+module_eval(<<'.,.,', 'parser.y', 172)
+ def _reduce_73(val, _values, result)
+ v = val[0]
+ result = if v[6].nil?
+ if v[4].nil?
+ LocalDate.new(v[0], v[1], v[2])
+ else
+ LocalDateTime.new(v[0], v[1], v[2], v[3] || 0, v[4] || 0, v[5].to_f)
+ end
+ else
+ # Patch for 24:00:00 which Ruby parses
+ if v[3].to_i == 24 && v[4].to_i == 0 && v[5].to_i == 0
+ v[3] = (v[3].to_i + 1).to_s
+ end
+
+ Time.new(v[0], v[1], v[2], v[3] || 0, v[4] || 0, v[5].to_f, v[6])
+ end
+
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 98)
- def _reduce_53(val, _values, result)
- result = Time.new(*val[0])
+module_eval(<<'.,.,', 'parser.y', 188)
+ def _reduce_74(val, _values, result)
+ result = LocalTime.new(*val[0])
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 101)
- def _reduce_54(val, _values, result)
+module_eval(<<'.,.,', 'parser.y', 191)
+ def _reduce_75(val, _values, result)
result = StringUtils.replace_escaped_chars(StringUtils.multiline_replacements(val[0]))
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 102)
- def _reduce_55(val, _values, result)
+module_eval(<<'.,.,', 'parser.y', 192)
+ def _reduce_76(val, _values, result)
result = StringUtils.replace_escaped_chars(val[0])
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 103)
- def _reduce_56(val, _values, result)
+module_eval(<<'.,.,', 'parser.y', 193)
+ def _reduce_77(val, _values, result)
result = StringUtils.strip_spaces(val[0])
result
end
.,.,
-module_eval(<<'.,.,', 'parser.y', 104)
- def _reduce_57(val, _values, result)
+module_eval(<<'.,.,', 'parser.y', 194)
+ def _reduce_78(val, _values, result)
result = val[0]
result
end
diff --git a/lib/tomlrb/handler.rb b/lib/tomlrb/handler.rb
index b9ba997..eb528d2 100644
--- a/lib/tomlrb/handler.rb
+++ b/lib/tomlrb/handler.rb
@@ -7,17 +7,24 @@ module Tomlrb
@current = @output
@stack = []
@array_names = []
+ @current_table = []
+ @keys = Keys.new
@symbolize_keys = options[:symbolize_keys]
end
def set_context(identifiers, is_array_of_tables: false)
+ if identifiers.empty?
+ raise ParseError, 'Array needs a name'
+ end
+
+ @current_table = identifiers.dup
+ @keys.add_table_key identifiers, is_array_of_tables
@current = @output
deal_with_array_of_tables(identifiers, is_array_of_tables) do |identifierz|
identifierz.each do |k|
k = k.to_sym if @symbolize_keys
if @current[k].is_a?(Array)
- @current[k] << {} if @current[k].empty?
@current = @current[k].last
else
@current[k] ||= {}
@@ -28,7 +35,6 @@ module Tomlrb
end
def deal_with_array_of_tables(identifiers, is_array_of_tables)
- identifiers.map!{|n| n.gsub("\"", '')}
stringified_identifier = identifiers.join('.')
if is_array_of_tables
@@ -43,20 +49,51 @@ module Tomlrb
if is_array_of_tables
last_identifier = last_identifier.to_sym if @symbolize_keys
@current[last_identifier] ||= []
+ raise ParseError, "Cannot use key #{last_identifier} for both table and array at once" unless @current[last_identifier].respond_to?(:<<)
@current[last_identifier] << {}
@current = @current[last_identifier].last
end
end
def assign(k)
- k = k.to_sym if @symbolize_keys
- @current[k] = @stack.pop
+ @keys.add_pair_key k, @current_table
+ current = @current
+ while key = k.shift
+ key = key.to_sym if @symbolize_keys
+ current = assign_key_path(current, key, k.empty?)
+ end
end
def push(o)
@stack << o
end
+ def push_inline(inline_arrays)
+ merged_inline = {}
+
+ inline_arrays.each do |inline_array|
+ current = merged_inline
+ value = inline_array.pop
+ inline_array.each_with_index do |inline_key, inline_index|
+ inline_key = inline_key.to_sym if @symbolize_keys
+ last_key = inline_index == inline_array.size - 1
+
+ if last_key
+ if current[inline_key].nil?
+ current[inline_key] = value
+ else
+ raise Key::KeyConflict, "Inline key #{inline_key} is already used"
+ end
+ else
+ current[inline_key] ||= {}
+ current = current[inline_key]
+ end
+ end
+ end
+
+ push(merged_inline)
+ end
+
def start_(type)
push([type])
end
@@ -64,10 +101,166 @@ module Tomlrb
def end_(type)
array = []
while (value = @stack.pop) != [type]
- raise ParseError, 'Unclosed table' if value.nil?
+ raise ParseError, 'Unclosed table' if @stack.empty?
array.unshift(value)
end
array
end
+
+ def validate_value(value)
+ if value.nil?
+ raise ParseError, 'Value must be present'
+ end
+ end
+
+ private
+
+ def assign_key_path(current, key, key_emptied)
+ if key_emptied
+
+ raise ParseError, "Cannot overwrite value with key #{key}" unless current.kind_of?(Hash)
+ current[key] = @stack.pop
+ return current
+ end
+ current[key] ||= {}
+ current = current[key]
+ current
+ end
+ end
+
+ class Keys
+ def initialize
+ @keys = {}
+ end
+
+ def add_table_key(keys, is_array_of_tables = false)
+ self << [keys, [], is_array_of_tables]
+ end
+
+ def add_pair_key(keys, context)
+ self << [context, keys, false]
+ end
+
+ def <<(keys)
+ table_keys, pair_keys, is_array_of_tables = keys
+ current = @keys
+ current = append_table_keys(current, table_keys, pair_keys.empty?, is_array_of_tables)
+ append_pair_keys(current, pair_keys, table_keys.empty?, is_array_of_tables)
+ end
+
+ private
+
+ def append_table_keys(current, table_keys, pair_keys_empty, is_array_of_tables)
+ table_keys.each_with_index do |key, index|
+ declared = (index == table_keys.length - 1) && pair_keys_empty
+ if index == 0
+ current = find_or_create_first_table_key(current, key, declared, is_array_of_tables)
+ else
+ current = current << [key, :table, declared, is_array_of_tables]
+ end
+ end
+
+ current.clear_children if is_array_of_tables
+ current
+ end
+
+ def find_or_create_first_table_key(current, key, declared, is_array_of_tables)
+ existed = current[key]
+ if existed && existed.type == :pair
+ raise Key::KeyConflict, "Key #{key} is already used as #{existed.type} key"
+ end
+ if existed && existed.declared? && declared && ! is_array_of_tables
+ raise Key::KeyConflict, "Key #{key} is already used"
+ end
+ k = existed || Key.new(key, :table, declared)
+ current[key] = k
+ k
+ end
+
+ def append_pair_keys(current, pair_keys, table_keys_empty, is_array_of_tables)
+ pair_keys.each_with_index do |key, index|
+ declared = index == pair_keys.length - 1
+ if index == 0 && table_keys_empty
+ current = find_or_create_first_pair_key(current, key, declared, table_keys_empty)
+ else
+ key = current << [key, :pair, declared, is_array_of_tables]
+ current = key
+ end
+ end
+ end
+
+ def find_or_create_first_pair_key(current, key, declared, table_keys_empty)
+ existed = current[key]
+ if existed && (existed.type == :pair) && declared && table_keys_empty
+ raise Key::KeyConflict, "Key #{key} is already used"
+ end
+ k = Key.new(key, :pair, declared)
+ current[key] = k
+ k
+ end
+ end
+
+ class Key
+ class KeyConflict < ParseError; end
+
+ attr_reader :key, :type
+
+ def initialize(key, type, declared = false)
+ @key = key
+ @type = type
+ @declared = declared
+ @children = {}
+ end
+
+ def declared?
+ @declared
+ end
+
+ def <<(key_type_declared)
+ key, type, declared, is_array_of_tables = key_type_declared
+ existed = @children[key]
+ validate_already_declared_as_different_key(type, declared, existed)
+ validate_already_declared_as_non_array_table(type, is_array_of_tables, declared, existed)
+ validate_path_already_created_as_different_type(type, declared, existed)
+ validate_path_already_declared_as_different_type(type, declared, existed)
+ validate_already_declared_as_same_key(declared, existed)
+ @children[key] = existed || self.class.new(key, type, declared)
+ end
+
+ def clear_children
+ @children.clear
+ end
+
+ private
+
+ def validate_already_declared_as_different_key(type, declared, existed)
+ if existed && existed.declared? && existed.type != type
+ raise KeyConflict, "Key #{existed.key} is already used as #{existed.type} key"
+ end
+ end
+
+ def validate_already_declared_as_non_array_table(type, is_array_of_tables, declared, existed)
+ if declared && type == :table && existed && existed.declared? && ! is_array_of_tables
+ raise KeyConflict, "Key #{existed.key} is already used"
+ end
+ end
+
+ def validate_path_already_created_as_different_type(type, declared, existed)
+ if declared && (type == :table) && existed && (existed.type == :pair) && (! existed.declared?)
+ raise KeyConflict, "Key #{existed.key} is already used as #{existed.type} key"
+ end
+ end
+
+ def validate_path_already_declared_as_different_type(type, declared, existed)
+ if ! declared && (type == :pair) && existed && (existed.type == :pair) && existed.declared?
+ raise KeyConflict, "Key #{key} is already used as #{type} key"
+ end
+ end
+
+ def validate_already_declared_as_same_key(declared, existed)
+ if existed && ! existed.declared? && declared
+ raise KeyConflict, "Key #{existed.key} is already used as #{existed.type} key"
+ end
+ end
end
end
diff --git a/lib/tomlrb/local_date.rb b/lib/tomlrb/local_date.rb
new file mode 100644
index 0000000..7d99209
--- /dev/null
+++ b/lib/tomlrb/local_date.rb
@@ -0,0 +1,33 @@
+require 'forwardable'
+
+module Tomlrb
+ class LocalDate
+ extend Forwardable
+
+ def_delegators :@time, :year, :month, :day
+
+ def initialize(year, month, day)
+ @time = Time.new(year, month, day, 0, 0, 0, '-00:00')
+ end
+
+ # @param offset see {LocalDateTime#to_time}
+ # @return [Time] 00:00:00 of the date
+ def to_time(offset='-00:00')
+ return @time if offset == '-00:00'
+ Time.new(year, month, day, 0, 0, 0, offset)
+ end
+
+ def to_s
+ @time.strftime('%F')
+ end
+
+ def ==(other)
+ other.kind_of?(self.class) &&
+ to_time == other.to_time
+ end
+
+ def inspect
+ "#<#{self.class}: #{to_s}>"
+ end
+ end
+end
diff --git a/lib/tomlrb/local_date_time.rb b/lib/tomlrb/local_date_time.rb
new file mode 100644
index 0000000..18bf28c
--- /dev/null
+++ b/lib/tomlrb/local_date_time.rb
@@ -0,0 +1,40 @@
+require 'forwardable'
+
+module Tomlrb
+ class LocalDateTime
+ extend Forwardable
+
+ def_delegators :@time, :year, :month, :day, :hour, :min, :sec, :usec, :nsec
+
+ def initialize(year, month, day, hour, min, sec) # rubocop:disable Metrics/ParameterLists
+ @time = Time.new(year, month, day, hour, min, sec, '-00:00')
+ @sec = sec
+ end
+
+ # @param offset [String, Symbol, Numeric, nil] time zone offset.
+ # * when +String+, must be '+HH:MM' format, '-HH:MM' format, 'UTC', 'A'..'I' or 'K'..'Z'. Arguments excluding '+-HH:MM' are supporeted at Ruby >= 2.7.0
+ # * when +Symbol+, must be +:dst+(for summar time for local) or +:std+(for standard time).
+ # * when +Numeric+, it is time zone offset in second.
+ # * when +nil+, local time zone offset is used.
+ # @return [Time]
+ def to_time(offset='-00:00')
+ return @time if offset == '-00:00'
+ Time.new(year, month, day, hour, min, @sec, offset)
+ end
+
+ def to_s
+ frac = (@sec - sec)
+ frac_str = frac == 0 ? '' : "#{frac.to_s[1..-1]}"
+ @time.strftime("%FT%T") << frac_str
+ end
+
+ def ==(other)
+ other.kind_of?(self.class) &&
+ to_time == other.to_time
+ end
+
+ def inspect
+ "#<#{self.class}: #{to_s}>"
+ end
+ end
+end
diff --git a/lib/tomlrb/local_time.rb b/lib/tomlrb/local_time.rb
new file mode 100644
index 0000000..833ab5a
--- /dev/null
+++ b/lib/tomlrb/local_time.rb
@@ -0,0 +1,38 @@
+require 'forwardable'
+
+module Tomlrb
+ class LocalTime
+ extend Forwardable
+
+ def_delegators :@time, :hour, :min, :sec, :usec, :nsec
+
+ def initialize(hour, min, sec)
+ @time = Time.new(0, 1, 1, hour, min, sec, '-00:00')
+ @sec = sec
+ end
+
+ # @param year [Integer]
+ # @param month [Integer]
+ # @param day [Integer]
+ # @param offset see {LocalDateTime#to_time}
+ # @return [Time] the time of the date specified by params
+ def to_time(year, month, day, offset='-00:00')
+ Time.new(year, month, day, hour, min, @sec, offset)
+ end
+
+ def to_s
+ frac = (@sec - sec)
+ frac_str = frac == 0 ? '' : "#{frac.to_s[1..-1]}"
+ @time.strftime("%T") << frac_str
+ end
+
+ def ==(other)
+ other.kind_of?(self.class) &&
+ @time == other.to_time(0, 1, 1)
+ end
+
+ def inspect
+ "#<#{self.class}: #{to_s}>"
+ end
+ end
+end
diff --git a/lib/tomlrb/parser.y b/lib/tomlrb/parser.y
index ab712e7..8160bb6 100644
--- a/lib/tomlrb/parser.y
+++ b/lib/tomlrb/parser.y
@@ -1,16 +1,19 @@
class Tomlrb::GeneratedParser
-token IDENTIFIER STRING_MULTI STRING_BASIC STRING_LITERAL_MULTI STRING_LITERAL DATETIME INTEGER FLOAT FLOAT_INF FLOAT_NAN TRUE FALSE
+token IDENTIFIER STRING_MULTI STRING_BASIC STRING_LITERAL_MULTI STRING_LITERAL DATETIME LOCAL_TIME INTEGER NON_DEC_INTEGER FLOAT FLOAT_KEYWORD BOOLEAN NEWLINE EOS
rule
expressions
| expressions expression
+ | expressions EOS
;
expression
: table
| assignment
| inline_table
+ | NEWLINE
;
table
- : table_start table_continued
+ : table_start table_continued NEWLINE
+ | table_start table_continued EOS
;
table_start
: '[' '[' { @handler.start_(:array_of_tables) }
@@ -27,55 +30,112 @@ rule
| '.' table_continued
;
table_identifier
- : IDENTIFIER { @handler.push(val[0]) }
- | STRING_BASIC { @handler.push(val[0]) }
- | STRING_LITERAL { @handler.push(val[0]) }
- | INTEGER { @handler.push(val[0]) }
- | TRUE { @handler.push(val[0]) }
- | FALSE { @handler.push(val[0]) }
+ : table_identifier '.' table_identifier_component { @handler.push(val[2]) }
+ | table_identifier '.' FLOAT { val[2].split('.').each { |k| @handler.push(k) } }
+ | FLOAT {
+ keys = val[0].split('.')
+ @handler.start_(:table)
+ keys.each { |key| @handler.push(key) }
+ }
+ | table_identifier_component { @handler.push(val[0]) }
+ ;
+ table_identifier_component
+ : IDENTIFIER
+ | STRING_BASIC { result = StringUtils.replace_escaped_chars(val[0]) }
+ | STRING_LITERAL
+ | INTEGER
+ | NON_DEC_INTEGER
+ | FLOAT_KEYWORD
+ | BOOLEAN
;
inline_table
- : inline_table_start inline_continued
+ : inline_table_start inline_table_end
+ | inline_table_start inline_continued inline_table_end
;
inline_table_start
: '{' { @handler.start_(:inline) }
;
+ inline_table_end
+ : '}' {
+ array = @handler.end_(:inline)
+ @handler.push_inline(array)
+ }
+ ;
inline_continued
- : '}' { array = @handler.end_(:inline); @handler.push(Hash[*array]) }
- | inline_assignment_key inline_assignment_value inline_next
+ : inline_assignment
+ | inline_assignment inline_next
;
inline_next
- : '}' {
- array = @handler.end_(:inline)
- array.map!.with_index{ |n,i| i.even? ? n.to_sym : n } if @handler.symbolize_keys
- @handler.push(Hash[*array])
+ : ',' inline_continued
+ ;
+ inline_assignment
+ : inline_assignment_key '=' value {
+ keys = @handler.end_(:inline_keys)
+ @handler.push(keys)
}
- | ',' inline_continued
;
inline_assignment_key
- : IDENTIFIER { @handler.push(val[0]) }
- ;
- inline_assignment_value
- : '=' value
+ : inline_assignment_key '.' assignment_key_component {
+ @handler.push(val[2])
+ }
+ | inline_assignment_key '.' FLOAT { val[2].split('.').each { |k| @handler.push(k) } }
+ | FLOAT {
+ keys = val[0].split('.')
+ @handler.start_(:inline_keys)
+ keys.each { |key| @handler.push(key) }
+ }
+ | assignment_key_component {
+ @handler.start_(:inline_keys)
+ @handler.push(val[0])
+ }
;
assignment
- : IDENTIFIER '=' value { @handler.assign(val[0]) }
- | STRING_BASIC '=' value { @handler.assign(val[0]) }
- | STRING_LITERAL '=' value { @handler.assign(val[0]) }
- | INTEGER '=' value { @handler.assign(val[0]) }
- | TRUE '=' value { @handler.assign(val[0]) }
- | FALSE '=' value { @handler.assign(val[0]) }
+ : assignment_key '=' value EOS {
+ keys = @handler.end_(:keys)
+ value = keys.pop
+ @handler.validate_value(value)
+ @handler.push(value)
+ @handler.assign(keys)
+ }
+ | assignment_key '=' value NEWLINE {
+ keys = @handler.end_(:keys)
+ value = keys.pop
+ @handler.validate_value(value)
+ @handler.push(value)
+ @handler.assign(keys)
+ }
+ ;
+ assignment_key
+ : assignment_key '.' assignment_key_component { @handler.push(val[2]) }
+ | assignment_key '.' FLOAT { val[2].split('.').each { |k| @handler.push(k) } }
+ | FLOAT {
+ keys = val[0].split('.')
+ @handler.start_(:keys)
+ keys.each { |key| @handler.push(key) }
+ }
+ | assignment_key_component { @handler.start_(:keys); @handler.push(val[0]) }
+ ;
+ assignment_key_component
+ : IDENTIFIER
+ | STRING_BASIC { result = StringUtils.replace_escaped_chars(val[0]) }
+ | STRING_LITERAL
+ | INTEGER
+ | NON_DEC_INTEGER
+ | FLOAT_KEYWORD
+ | BOOLEAN
;
array
: start_array array_continued
;
array_continued
- : ']' { array = @handler.end_(:array); @handler.push(array) }
+ : ']' { array = @handler.end_(:array); @handler.push(array.compact) }
| value array_next
+ | NEWLINE array_continued
;
array_next
- : ']' { array = @handler.end_(:array); @handler.push(array) }
+ : ']' { array = @handler.end_(:array); @handler.push(array.compact) }
| ',' array_continued
+ | NEWLINE array_continued
;
start_array
: '[' { @handler.start_(:array) }
@@ -91,12 +151,42 @@ rule
;
literal
| FLOAT { result = val[0].to_f }
- | FLOAT_INF { result = (val[0][0] == '-' ? -1 : 1) * Float::INFINITY }
- | FLOAT_NAN { result = Float::NAN }
+ | FLOAT_KEYWORD {
+ v = val[0]
+ result = if v.end_with?('nan')
+ Float::NAN
+ else
+ (v[0] == '-' ? -1 : 1) * Float::INFINITY
+ end
+ }
| INTEGER { result = val[0].to_i }
- | TRUE { result = true }
- | FALSE { result = false }
- | DATETIME { result = Time.new(*val[0])}
+ | NON_DEC_INTEGER {
+ base = case val[0][1]
+ when "x" then 16
+ when "o" then 8
+ when "b" then 2
+ end
+ result = val[0].to_i(base)
+ }
+ | BOOLEAN { result = val[0] == 'true' ? true : false }
+ | DATETIME {
+ v = val[0]
+ result = if v[6].nil?
+ if v[4].nil?
+ LocalDate.new(v[0], v[1], v[2])
+ else
+ LocalDateTime.new(v[0], v[1], v[2], v[3] || 0, v[4] || 0, v[5].to_f)
+ end
+ else
+ # Patch for 24:00:00 which Ruby parses
+ if v[3].to_i == 24 && v[4].to_i == 0 && v[5].to_i == 0
+ v[3] = (v[3].to_i + 1).to_s
+ end
+
+ Time.new(v[0], v[1], v[2], v[3] || 0, v[4] || 0, v[5].to_f, v[6])
+ end
+ }
+ | LOCAL_TIME { result = LocalTime.new(*val[0]) }
;
string
: STRING_MULTI { result = StringUtils.replace_escaped_chars(StringUtils.multiline_replacements(val[0])) }
diff --git a/lib/tomlrb/scanner.rb b/lib/tomlrb/scanner.rb
index 90f3fcb..f2c214b 100644
--- a/lib/tomlrb/scanner.rb
+++ b/lib/tomlrb/scanner.rb
@@ -2,57 +2,73 @@ require 'strscan'
module Tomlrb
class Scanner
- COMMENT = /#.*/
+ COMMENT = /#[^\u0000-\u0008\u000A-\u001F\u007F]*/
IDENTIFIER = /[A-Za-z0-9_-]+/
- SPACE = /[ \t\r\n]/
- STRING_BASIC = /(["])(?:\\?.)*?\1/
- STRING_MULTI = /"{3}([\s\S]*?"{3,4})/m
- STRING_LITERAL = /(['])(?:\\?.)*?\1/
- STRING_LITERAL_MULTI = /'{3}([\s\S]*?'{3})/m
+ SPACE = /[ \t]/
+ NEWLINE = /(?:[ \t]*(?:\r?\n)[ \t]*)+/
+ STRING_BASIC = /(["])(?:\\?[^\u0000-\u0008\u000A-\u001F\u007F])*?\1/
+ STRING_MULTI = /"{3}([^\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]*?(?<!\\)"{3,5})/m
+ STRING_LITERAL = /(['])(?:\\?[^\u0000-\u0008\u000A-\u001F\u007F])*?\1/
+ STRING_LITERAL_MULTI = /'{3}([^\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]*?'{3,5})/m
DATETIME = /(-?\d{4})-(\d{2})-(\d{2})(?:(?:t|\s)(\d{2}):(\d{2}):(\d{2}(?:\.\d+)?))?(z|[-+]\d{2}:\d{2})?/i
- FLOAT = /[+-]?(?:[0-9_]+\.[0-9_]*|\d+(?=[eE]))(?:[eE][+-]?[0-9_]+)?/
- FLOAT_INF = /[+-]?inf/
- FLOAT_NAN = /[+-]?nan/
+ LOCAL_TIME = /(\d{2}):(\d{2}):(\d{2}(?:\.\d+)?)/
+ FLOAT = /[+-]?(?:(?:\d|[1-9](?:_?\d)*)\.\d(?:_?\d)*|\d+(?=[eE]))(?:[eE][+-]?[0-9]+(_[0-9])*[0-9]*)?(?!\w)/
+ FLOAT_KEYWORD = /[+-]?(?:inf|nan)\b/
INTEGER = /[+-]?([1-9](_?\d)*|0)(?![A-Za-z0-9_-]+)/
- TRUE = /true/
- FALSE = /false/
+ 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]*)/
+ BOOLEAN = /true|false/
+ SPACED_ARRAY_OF_TABLES_START = /^\[[ \t]+\[(#{IDENTIFIER}|#{STRING_BASIC}|#{STRING_LITERAL}|#{INTEGER}|#{NON_DEC_INTEGER}|#{FLOAT_KEYWORD}|#{BOOLEAN})\]\]$/
+ SPACED_ARRAY_OF_TABLES_END = /^\[\[(#{IDENTIFIER}|#{STRING_BASIC}|#{STRING_LITERAL}|#{INTEGER}|#{NON_DEC_INTEGER}|#{FLOAT_KEYWORD}|#{BOOLEAN})\][ \t]+\]$/
+ SPACED_ARRAY_OF_TABLES_BOTH = /^\[[ \t]+\[(#{IDENTIFIER}|#{STRING_BASIC}|#{STRING_LITERAL}|#{INTEGER}|#{NON_DEC_INTEGER}|#{FLOAT_KEYWORD}|#{BOOLEAN})\][ \t]+\]$/
def initialize(io)
@ss = StringScanner.new(io.read)
+ @eos = false
end
def next_token
- return if @ss.eos?
-
case
+ when @ss.scan(NEWLINE) then [:NEWLINE, nil]
+ when @ss.scan(SPACED_ARRAY_OF_TABLES_START) then raise ParseError.new("Array of tables has spaces in starting brackets")
+ when @ss.scan(SPACED_ARRAY_OF_TABLES_END) then raise ParseError.new("Array of tables has spaces in ending brackets")
+ when @ss.scan(SPACED_ARRAY_OF_TABLES_BOTH) then raise ParseError.new("Array of tables has spaces in starting and ending brackets")
when @ss.scan(SPACE) then next_token
when @ss.scan(COMMENT) then next_token
when @ss.scan(DATETIME) then process_datetime
+ when @ss.scan(LOCAL_TIME) then process_local_time
when text = @ss.scan(STRING_MULTI) then [:STRING_MULTI, text[3..-4]]
when text = @ss.scan(STRING_BASIC) then [:STRING_BASIC, text[1..-2]]
when text = @ss.scan(STRING_LITERAL_MULTI) then [:STRING_LITERAL_MULTI, text[3..-4]]
when text = @ss.scan(STRING_LITERAL) then [:STRING_LITERAL, text[1..-2]]
when text = @ss.scan(FLOAT) then [:FLOAT, text]
- when text = @ss.scan(FLOAT_INF) then [:FLOAT_INF, text]
- when text = @ss.scan(FLOAT_NAN) then [:FLOAT_NAN, text]
+ when text = @ss.scan(FLOAT_KEYWORD) then [:FLOAT_KEYWORD, text]
when text = @ss.scan(INTEGER) then [:INTEGER, text]
- when text = @ss.scan(TRUE) then [:TRUE, text]
- when text = @ss.scan(FALSE) then [:FALSE, text]
+ when text = @ss.scan(NON_DEC_INTEGER) then [:NON_DEC_INTEGER, text]
+ when text = @ss.scan(BOOLEAN) then [:BOOLEAN, text]
when text = @ss.scan(IDENTIFIER) then [:IDENTIFIER, text]
- else
- x = @ss.getch
- [x, x]
+ when @ss.eos? then process_eos
+ else x = @ss.getch; [x, x]
end
end
def process_datetime
- if @ss[7].nil?
- offset = '+00:00'
- else
- offset = @ss[7].gsub('Z', '+00:00')
+ if @ss[7]
+ offset = @ss[7].gsub(/[zZ]/, '+00:00')
end
- args = [@ss[1], @ss[2], @ss[3], @ss[4] || 0, @ss[5] || 0, @ss[6].to_f, offset]
+ args = [@ss[1], @ss[2], @ss[3], @ss[4], @ss[5], @ss[6], offset]
[:DATETIME, args]
end
+
+ def process_local_time
+ args = [@ss[1], @ss[2], @ss[3].to_f]
+ [:LOCAL_TIME, args]
+ end
+
+ def process_eos
+ return if @eos
+
+ @eos = true
+ [:EOS, nil]
+ end
end
end
diff --git a/lib/tomlrb/string_utils.rb b/lib/tomlrb/string_utils.rb
index 53d27e4..139fb04 100644
--- a/lib/tomlrb/string_utils.rb
+++ b/lib/tomlrb/string_utils.rb
@@ -12,7 +12,13 @@ module Tomlrb
}.freeze
def self.multiline_replacements(str)
- strip_spaces(str).gsub(/\\\n\s+/, '')
+ strip_spaces(str).gsub(/\\+\s*\n\s*/) {|matched|
+ if matched.match(/\\+/)[0].length.odd?
+ matched.gsub(/\\\s*\n\s*/, '')
+ else
+ matched
+ end
+ }
end
def self.replace_escaped_chars(str)
diff --git a/lib/tomlrb/version.rb b/lib/tomlrb/version.rb
index f8e1a44..b61120a 100644
--- a/lib/tomlrb/version.rb
+++ b/lib/tomlrb/version.rb
@@ -1,3 +1,3 @@
module Tomlrb
- VERSION = '1.3.0'.freeze
+ VERSION = '2.0.3'.freeze
end
diff --git a/tomlrb.gemspec b/tomlrb.gemspec
index 18c476c..6d776c8 100644
--- a/tomlrb.gemspec
+++ b/tomlrb.gemspec
@@ -2,22 +2,32 @@
# This file has been automatically generated by gem2tgz #
#########################################################
# -*- encoding: utf-8 -*-
-# stub: tomlrb 1.3.0 ruby lib
+# stub: tomlrb 2.0.3 ruby lib
Gem::Specification.new do |s|
s.name = "tomlrb".freeze
- s.version = "1.3.0"
+ s.version = "2.0.3"
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
s.require_paths = ["lib".freeze]
s.authors = ["Francois Bernier".freeze]
- s.date = "2020-03-19"
+ s.date = "2022-05-28"
s.description = "A racc based toml parser".freeze
s.email = ["frankbernier@gmail.com".freeze]
- s.files = ["LICENSE.txt".freeze, "lib/tomlrb.rb".freeze, "lib/tomlrb/generated_parser.rb".freeze, "lib/tomlrb/handler.rb".freeze, "lib/tomlrb/parser.rb".freeze, "lib/tomlrb/parser.y".freeze, "lib/tomlrb/scanner.rb".freeze, "lib/tomlrb/string_utils.rb".freeze, "lib/tomlrb/version.rb".freeze]
+ s.files = ["LICENSE.txt".freeze, "lib/tomlrb.rb".freeze, "lib/tomlrb/generated_parser.rb".freeze, "lib/tomlrb/handler.rb".freeze, "lib/tomlrb/local_date.rb".freeze, "lib/tomlrb/local_date_time.rb".freeze, "lib/tomlrb/local_time.rb".freeze, "lib/tomlrb/parser.rb".freeze, "lib/tomlrb/parser.y".freeze, "lib/tomlrb/scanner.rb".freeze, "lib/tomlrb/string_utils.rb".freeze, "lib/tomlrb/version.rb".freeze]
s.homepage = "https://github.com/fbernier/tomlrb".freeze
s.licenses = ["MIT".freeze]
s.required_ruby_version = Gem::Requirement.new(">= 2.0".freeze)
- s.rubygems_version = "2.5.2.1".freeze
+ s.rubygems_version = "3.2.5".freeze
s.summary = "A racc based toml parser".freeze
+
+ if s.respond_to? :specification_version then
+ s.specification_version = 4
+ end
+
+ if s.respond_to? :add_runtime_dependency then
+ s.add_development_dependency(%q<psych>.freeze, ["~> 4"])
+ else
+ s.add_dependency(%q<psych>.freeze, ["~> 4"])
+ end
end
Debdiff
[The following lists of changes regard files as different if they have different names, permissions or owners.]
Files in second set of .debs but not in first
-rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-2.0.3/lib/tomlrb.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-2.0.3/lib/tomlrb/generated_parser.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-2.0.3/lib/tomlrb/handler.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-2.0.3/lib/tomlrb/local_date.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-2.0.3/lib/tomlrb/local_date_time.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-2.0.3/lib/tomlrb/local_time.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-2.0.3/lib/tomlrb/parser.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-2.0.3/lib/tomlrb/parser.y -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-2.0.3/lib/tomlrb/scanner.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-2.0.3/lib/tomlrb/string_utils.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-2.0.3/lib/tomlrb/version.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/specifications/tomlrb-2.0.3.gemspec
Files in first set of .debs but not in second
-rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-1.3.0/lib/tomlrb.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-1.3.0/lib/tomlrb/generated_parser.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-1.3.0/lib/tomlrb/handler.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-1.3.0/lib/tomlrb/parser.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-1.3.0/lib/tomlrb/parser.y -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-1.3.0/lib/tomlrb/scanner.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-1.3.0/lib/tomlrb/string_utils.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/tomlrb-1.3.0/lib/tomlrb/version.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/specifications/tomlrb-1.3.0.gemspec
Control files: lines which differ (wdiff format)
Ruby-Versions: all