From 6ab05a85947b6faba10b10755d9a302813ea3c2d Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Thu, 11 May 2017 15:09:11 +0900 Subject: [PATCH] change impl of parser of values --- tests/test_parser.cpp | 556 +++++++++++++++-------------- toml/parser.hpp | 797 +++++++++++++++++++++--------------------- 2 files changed, 711 insertions(+), 642 deletions(-) diff --git a/tests/test_parser.cpp b/tests/test_parser.cpp index ff8b243..430aeed 100644 --- a/tests/test_parser.cpp +++ b/tests/test_parser.cpp @@ -1,4 +1,4 @@ -#define BOOST_TEST_MODULE "test_barekey" +#define BOOST_TEST_MODULE "test_parser" #ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST #include #else @@ -317,7 +317,7 @@ BOOST_AUTO_TEST_CASE(test_parse_boolean) BOOST_CHECK(result.second == acceptor::invoke(source.begin())); } { - const std::string source("T"); + const std::string source("dummy"); const auto result = parser::invoke(source.cbegin()); BOOST_CHECK(!result.first.ok()); BOOST_CHECK(result.second == source.begin()); @@ -326,257 +326,307 @@ BOOST_AUTO_TEST_CASE(test_parse_boolean) -// BOOST_AUTO_TEST_CASE(test_parse_local_time) -// { -// typedef toml::parse_local_time parser; -// typedef toml::is_local_time acceptor; -// { -// const std::string source("12:34:56"); -// const toml::Datetime expected(12, 34, 56, 0, 0); -// const toml::Datetime result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// BOOST_CHECK_EQUAL(result, expected); -// } -// { -// const std::string source("12:34:56.7"); -// const toml::Datetime expected(12, 34, 56, 700, 0); -// const toml::Datetime result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// BOOST_CHECK_EQUAL(result, expected); -// } -// { -// const std::string source("12:34:56.7891"); -// const toml::Datetime expected(12, 34, 56, 789, 100); -// const toml::Datetime result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// BOOST_CHECK_EQUAL(result, expected); -// } -// } -// -// BOOST_AUTO_TEST_CASE(test_parse_local_date) -// { -// typedef toml::parse_local_date parser; -// typedef toml::is_local_date acceptor; -// { -// const std::string source("1979-09-27"); -// const toml::Datetime expected(1979, 9, 27); -// const toml::Datetime result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// BOOST_CHECK_EQUAL(result, expected); -// } -// } -// -// BOOST_AUTO_TEST_CASE(test_parse_local_date_time) -// { -// typedef toml::parse_local_date_time parser; -// typedef toml::is_local_date_time acceptor; -// { -// const std::string source("1979-09-27T12:34:56"); -// const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0); -// const toml::Datetime result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// BOOST_CHECK_EQUAL(result, expected); -// } -// { -// const std::string source("1979-09-27T12:34:56.789000"); -// const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 789, 0); -// const toml::Datetime result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// BOOST_CHECK_EQUAL(result, expected); -// } -// } -// -// BOOST_AUTO_TEST_CASE(test_parse_offset_date_time) -// { -// typedef toml::parse_offset_date_time parser; -// typedef toml::is_offset_date_time acceptor; -// { -// const std::string source("1979-09-27T12:34:56Z"); -// const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0, 0, 0); -// const toml::Datetime result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// BOOST_CHECK_EQUAL(result, expected); -// } -// { -// const std::string source("1979-09-27T12:34:56.789000Z"); -// const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 789, 0, 0, 0); -// const toml::Datetime result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// BOOST_CHECK_EQUAL(result, expected); -// } -// -// { -// const std::string source("1979-09-27T12:34:56+07:30"); -// const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0, 7, 30); -// const toml::Datetime result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// BOOST_CHECK_EQUAL(result, expected); -// } -// { -// const std::string source("1979-09-27T12:34:56.789000+07:30"); -// const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 789, 0, 7, 30); -// const toml::Datetime result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// BOOST_CHECK_EQUAL(result, expected); -// } -// -// { -// const std::string source("1979-09-27T12:34:56-07:30"); -// const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0, -7, -30); -// const toml::Datetime result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// BOOST_CHECK_EQUAL(result, expected); -// } -// { -// const std::string source("1979-09-27T12:34:56.789000-07:30"); -// const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 789, 0, -7, -30); -// const toml::Datetime result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// BOOST_CHECK_EQUAL(result, expected); -// } -// } -// -// BOOST_AUTO_TEST_CASE(test_parse_array) -// { -// typedef toml::parse_array parser; -// typedef toml::is_array acceptor; -// { -// const std::string source("[1,2,3]"); -// const toml::Array expected{1, 2, 3}; -// const toml::Array result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("[1, 2, 3]"); -// const toml::Array expected{1, 2, 3}; -// const toml::Array result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("[ 1,2,3 ]"); -// const toml::Array expected{1, 2, 3}; -// const toml::Array result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("[ 1 , 2 , 3 ]"); -// const toml::Array expected{1, 2, 3}; -// const toml::Array result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("[ 1 \n,#comment\n 2 ,\n 3\n ]"); -// const toml::Array expected{1, 2, 3}; -// const toml::Array result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("[ # empty array\n ]"); -// const toml::Array expected{}; -// const toml::Array result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("[ \"] \", ' # ', \n']', # ] \n]"); -// const toml::Array expected{"] ", " # ", "]"}; -// const toml::Array result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// -// { -// const std::string source("[ \"Test #11 ]proved that\", 'Experiment #9 was a success' ]"); -// const toml::Array expected{"Test #11 ]proved that", "Experiment #9 was a success"}; -// const toml::Array result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// -// { -// const std::string source("[ \"Test #11 ]proved that\", 'Experiment #9 was a success' ]"); -// const toml::Array expected{"Test #11 ]proved that", "Experiment #9 was a success"}; -// const toml::Array result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// -// { -// const std::string source("[ [1,2,3] , ['a', 'b', 'c'] ]"); -// const toml::Array expected{{1,2,3}, {"a", "b", "c"}}; -// const toml::Array result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// -// { -// const std::string source("[ {foo=1}, {foo=1, bar=2.0}, {foo=1, bar=2.0, baz='str'} ]"); -// const toml::Array expected{{{"foo", 1}}, {{"foo", 1}, {"bar", 2.0}}, {{"foo", 1}, {"bar", 2.0}, {"baz", "str"}}}; -// const toml::Array result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// } -// -// -// BOOST_AUTO_TEST_CASE(test_parse_inline_table) -// { -// typedef toml::parse_inline_table parser; -// typedef toml::is_inline_table acceptor; -// { -// const std::string source("{foo=1,bar=2.0,baz='str'}"); -// const toml::Table expected{{"foo", 1}, {"bar", 2.0}, {"baz", "str"}}; -// const toml::Table result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("{ foo=1, bar=2.0, baz='str' }"); -// const toml::Table expected{{"foo", 1}, {"bar", 2.0}, {"baz", "str"}}; -// const toml::Table result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("{ foo = 1, bar = 2.0, baz = 'str' }"); -// const toml::Table expected{{"foo", 1}, {"bar", 2.0}, {"baz", "str"}}; -// const toml::Table result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// -// { -// const std::string source("{b=true, i=1, f=2.0, d=1907-03-02T07:32:00, s='str', a=[1,2,3], t={foo=1}}"); -// const toml::Table expected{{"b", true}, {"i", 1}, {"f", 2.0}, -// {"d", toml::Datetime(1907,3,2,7,32,0,0,0)}, -// {"s", "str"}, {"a", {1, 2, 3}}, -// {"t", {{"foo", 1}}}}; -// const toml::Table result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// } +BOOST_AUTO_TEST_CASE(test_parse_local_time) +{ + typedef toml::parse_local_time parser; + typedef toml::is_local_time acceptor; + { + const std::string source("12:34:56"); + const toml::Datetime expected(12, 34, 56, 0, 0); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("12:34:56.7"); + const toml::Datetime expected(12, 34, 56, 700, 0); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("12:34:56.7891"); + const toml::Datetime expected(12, 34, 56, 789, 100); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } +} + +BOOST_AUTO_TEST_CASE(test_parse_local_date) +{ + typedef toml::parse_local_date parser; + typedef toml::is_local_date acceptor; + { + const std::string source("1979-09-27"); + const toml::Datetime expected(1979, 9, 27); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } +} + +BOOST_AUTO_TEST_CASE(test_parse_local_date_time) +{ + typedef toml::parse_local_date_time parser; + typedef toml::is_local_date_time acceptor; + { + const std::string source("1979-09-27T12:34:56"); + const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("1979-09-27T12:34:56.789000"); + const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 789, 0); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } +} + +BOOST_AUTO_TEST_CASE(test_parse_offset_date_time) +{ + typedef toml::parse_offset_date_time parser; + typedef toml::is_offset_date_time acceptor; + { + const std::string source("1979-09-27T12:34:56Z"); + const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0, 0, 0); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("1979-09-27T12:34:56.789000Z"); + const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 789, 0, 0, 0); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + + { + const std::string source("1979-09-27T12:34:56+07:30"); + const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0, 7, 30); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("1979-09-27T12:34:56.789000+07:30"); + const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 789, 0, 7, 30); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + + { + const std::string source("1979-09-27T12:34:56-07:30"); + const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0, -7, -30); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("1979-09-27T12:34:56.789000-07:30"); + const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 789, 0, -7, -30); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } +} + +BOOST_AUTO_TEST_CASE(test_parse_datetime) +{ + typedef toml::parse_datetime parser; + typedef toml::is_datetime acceptor; + { + const std::string source("1979-09-27T12:34:56Z"); + const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0, 0, 0); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("1979-09-27T12:34:56"); + const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("1979-09-27"); + const toml::Datetime expected(1979, 9, 27); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("12:34:56"); + const toml::Datetime expected(12, 34, 56, 0, 0); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } +} + + +BOOST_AUTO_TEST_CASE(test_parse_array) +{ + typedef toml::parse_array parser; + typedef toml::is_array acceptor; + { + const std::string source("[1,2,3]"); + const toml::Array expected{1, 2, 3}; + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("[1, 2, 3]"); + const toml::Array expected{1, 2, 3}; + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("[ 1,2,3 ]"); + const toml::Array expected{1, 2, 3}; + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("[ 1 , 2 , 3 ]"); + const toml::Array expected{1, 2, 3}; + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("[ 1 \n,#comment\n 2 ,\n 3\n ]"); + const toml::Array expected{1, 2, 3}; + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("[ # empty array\n ]"); + const toml::Array expected{}; + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("[ \"] \", ' # ', \n']', # ] \n]"); + const toml::Array expected{"] ", " # ", "]"}; + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + + { + const std::string source("[ \"Test #11 ]proved that\", 'Experiment #9 was a success' ]"); + const toml::Array expected{"Test #11 ]proved that", "Experiment #9 was a success"}; + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + + { + const std::string source("[ \"Test #11 ]proved that\", 'Experiment #9 was a success' ]"); + const toml::Array expected{"Test #11 ]proved that", "Experiment #9 was a success"}; + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + + { + const std::string source("[ [1,2,3] , ['a', 'b', 'c'] ]"); + const toml::Array expected{{1,2,3}, {"a", "b", "c"}}; + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + + { + const std::string source("[ {foo=1}, {foo=1, bar=2.0}, {foo=1, bar=2.0, baz='str'} ]"); + const toml::Array expected{{{"foo", 1}}, {{"foo", 1}, {"bar", 2.0}}, {{"foo", 1}, {"bar", 2.0}, {"baz", "str"}}}; + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } +} + + +BOOST_AUTO_TEST_CASE(test_parse_inline_table) +{ + typedef toml::parse_inline_table parser; + typedef toml::is_inline_table acceptor; + { + const std::string source("{foo=1,bar=2.0,baz='str'}"); + const toml::Table expected{{"foo", 1}, {"bar", 2.0}, {"baz", "str"}}; + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("{ foo=1, bar=2.0, baz='str' }"); + const toml::Table expected{{"foo", 1}, {"bar", 2.0}, {"baz", "str"}}; + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + { + const std::string source("{ foo = 1, bar = 2.0, baz = 'str' }"); + const toml::Table expected{{"foo", 1}, {"bar", 2.0}, {"baz", "str"}}; + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } + + { + const std::string source("{b=true, i=1, f=2.0, d=1907-03-02T07:32:00, s='str', a=[1,2,3], t={foo=1}}"); + const toml::Table expected{{"b", true}, {"i", 1}, {"f", 2.0}, + {"d", toml::Datetime(1907,3,2,7,32,0,0,0)}, + {"s", "str"}, {"a", {1, 2, 3}}, + {"t", {{"foo", 1}}}}; + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(result.first.ok()); + BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.second == acceptor::invoke(source.begin())); + } +} // // // BOOST_AUTO_TEST_CASE(test_parse_barekey) // // { diff --git a/toml/parser.hpp b/toml/parser.hpp index c521479..226181e 100644 --- a/toml/parser.hpp +++ b/toml/parser.hpp @@ -349,395 +349,414 @@ struct parse_boolean } }; -// template -// struct parse_local_time -// { -// typedef charT value_type; -// typedef std::basic_string string_type; -// typedef toml::Datetime result_type; -// typedef typename result_type::number_type number_type; -// typedef is_repeat_of, 2> nums; -// typedef is_charactor delim; -// typedef is_charactor fract; -// -// template::value_type, -// value_type>::value>::type> -// static result_type invoke(Iterator iter, Iterator end) -// { -// result_type result; -// result.hour = std::stoi(string_type(iter, nums::invoke(iter))); -// iter = delim::invoke(nums::invoke(iter)); -// result.minute = std::stoi(string_type(iter, nums::invoke(iter))); -// iter = delim::invoke(nums::invoke(iter)); -// result.second = std::stoi(string_type(iter, nums::invoke(iter))); -// iter = fract::invoke(nums::invoke(iter)); -// if(iter == end) -// { -// result.millisecond = 0.0; -// result.microsecond = 0.0; -// } -// else if(std::distance(iter, end) <= 3) -// { -// result.millisecond = parse_number(iter, end); -// result.microsecond = 0.0; -// } -// else -// { -// result.millisecond = parse_number(iter, iter + 3); -// result.microsecond = parse_number(iter + 3, end); -// } -// result.offset_hour = result_type::nooffset; -// result.offset_minute = result_type::nooffset; -// result.year = result_type::undef; -// result.month = result_type::undef; -// result.day = result_type::undef; -// return result; -// } -// -// template::value_type, -// value_type>::value>::type> -// static number_type parse_number(Iterator iter, Iterator end) -// { -// if(std::distance(iter, end) > 3) end = iter + 3; -// string_type str(iter, end); -// while(str.size() < 3){str += '0';} -// return std::stoi(str); -// } -// }; -// -// template -// struct parse_local_date -// { -// typedef charT value_type; -// typedef std::basic_string string_type; -// typedef toml::Datetime result_type; -// template -// using nums = is_repeat_of, N>; -// typedef is_charactor delim; -// -// template::value_type, -// value_type>::value>::type> -// static result_type invoke(Iterator iter, Iterator end) -// { -// result_type result; -// result.year = std::stoi(string_type(iter, nums<4>::invoke(iter))); -// iter = delim::invoke(nums<4>::invoke(iter)); -// result.month = std::stoi(string_type(iter, nums<2>::invoke(iter))); -// iter = delim::invoke(nums<2>::invoke(iter)); -// result.day = std::stoi(string_type(iter, nums<2>::invoke(iter))); -// -// result.offset_hour = result_type::nooffset; -// result.offset_minute = result_type::nooffset; -// result.hour = result_type::undef; -// result.minute = result_type::undef; -// result.second = result_type::undef; -// result.millisecond = result_type::undef; -// result.microsecond = result_type::undef; -// return result; -// } -// }; -// -// template -// struct parse_local_date_time -// { -// typedef charT value_type; -// typedef std::basic_string string_type; -// typedef toml::Datetime result_type; -// template -// using nums = is_repeat_of, N>; -// typedef is_charactor delim; -// -// template::value_type, -// value_type>::value>::type> -// static result_type invoke(Iterator iter, Iterator end) -// { -// const Iterator date = is_local_date::invoke(iter); -// result_type result = parse_local_date::invoke(iter, date); -// iter = delim::invoke(date);// 'T' -// const result_type time = parse_local_time::invoke(iter, end); -// result.hour = time.hour; -// result.minute = time.minute; -// result.second = time.second; -// result.millisecond = time.millisecond; -// result.microsecond = time.microsecond; -// result.offset_hour = result_type::nooffset; -// result.offset_minute = result_type::nooffset; -// return result; -// } -// }; -// -// template -// struct parse_offset_date_time -// { -// typedef charT value_type; -// typedef std::basic_string string_type; -// typedef toml::Datetime result_type; -// template -// using nums = is_repeat_of, N>; -// typedef is_charactor delim; -// -// template::value_type, -// value_type>::value>::type> -// static result_type invoke(Iterator iter, Iterator end) -// { -// const Iterator datetime = is_local_date_time::invoke(iter); -// result_type result = parse_local_date_time::invoke(iter, datetime); -// iter = datetime; -// if(*iter == 'Z') -// { -// result.offset_hour = 0; -// result.offset_minute = 0; -// } -// else -// { -// if(*iter != '+' && *iter != '-') -// throw syntax_error("invalid offset-datetime"); -// const int sign = (*iter == '-') ? -1 : 1; -// ++iter; -// result.offset_hour = sign * -// std::stoi(string_type(iter, nums<2>::invoke(iter))); -// iter = delim::invoke(nums<2>::invoke(iter)); -// result.offset_minute = sign * -// std::stoi(string_type(iter, nums<2>::invoke(iter))); -// } -// return result; -// } -// }; -// -// template -// struct parse_datetime -// { -// typedef charT value_type; -// typedef toml::Datetime result_type; -// -// template::value_type, -// value_type>::value>::type> -// static result_type invoke(Iterator iter, Iterator end) -// { -// Iterator tmp = is_offset_date_time::invoke(iter); -// if(tmp != iter) return parse_offset_date_time::invoke(iter, tmp); -// tmp = is_local_date_time::invoke(iter); -// if(tmp != iter) return parse_local_date_time::invoke(iter, tmp); -// tmp = is_local_date::invoke(iter); -// if(tmp != iter) return parse_local_date::invoke(iter, tmp); -// tmp = is_local_time::invoke(iter); -// if(tmp != iter) return parse_local_time::invoke(iter, tmp); -// throw internal_error("no datetime here"); -// } -// }; -// -// template -// struct parse_fixed_type_array -// { -// typedef charT value_type; -// typedef toml::Array result_type; -// typedef acceptorT acceptor_type; -// typedef parserT parser_type; -// typedef is_skippable_in_array skippable; -// -// template::value_type, -// value_type>::value>::type> -// static result_type invoke(Iterator iter, Iterator end) -// { -// result_type result; -// --end; -// assert(*iter == '[' && *end == ']'); -// ++iter; -// iter = skippable::invoke(iter); -// while(iter != end) -// { -// const Iterator tmp = acceptor_type::invoke(iter); -// result.emplace_back(parser_type::invoke(iter, tmp)); -// iter = tmp; -// iter = skippable::invoke(iter); -// iter = is_charactor::invoke(iter); -// iter = skippable::invoke(iter); -// } -// return result; -// } -// }; -// -// template -// struct parse_inline_table; -// -// template -// struct parse_array -// { -// typedef charT value_type; -// typedef toml::Array result_type; -// typedef is_skippable_in_array skippable; -// -// template::value_type, -// value_type>::value>::type> -// static result_type invoke(Iterator iter, Iterator end) -// { -// const Iterator init = skippable::invoke(std::next(iter)); -// if(is_boolean::invoke(init) != init) -// return parse_fixed_type_array, -// parse_boolean>::invoke(iter, end); -// -// if(is_integer::invoke(init) != init) -// return parse_fixed_type_array, -// parse_integer>::invoke(iter, end); -// -// if(is_float::invoke(init) != init) -// return parse_fixed_type_array, -// parse_float>::invoke(iter, end); -// -// if(is_string::invoke(init) != init) -// return parse_fixed_type_array, -// parse_string>::invoke(iter, end); -// -// if(is_datetime::invoke(init) != init) -// return parse_fixed_type_array, -// parse_datetime>::invoke(iter, end); -// -// if(is_array::invoke(init) != init) -// return parse_fixed_type_array, -// parse_array>::invoke(iter, end); -// -// if(is_inline_table::invoke(init) != init) -// return parse_fixed_type_array, -// parse_inline_table>::invoke(iter, end); -// -// if(is_skippable_in_array::invoke(init) == std::prev(end)) -// return result_type{}; // empty -// -// throw internal_error("no valid array here"); -// } -// }; -// -// template -// struct parse_value -// { -// typedef charT value_type; -// typedef toml::value result_type; -// -// template::value_type, -// value_type>::value>::type> -// static result_type invoke(Iterator iter, Iterator end) -// { -// if(iter != is_string::invoke(iter)) -// return result_type(parse_string::invoke(iter, end)); -// else if(iter != is_datetime::invoke(iter)) -// return result_type(parse_datetime::invoke(iter, end)); -// else if(iter != is_float::invoke(iter)) -// return result_type(parse_float::invoke(iter, end)); -// else if(iter != is_integer::invoke(iter)) -// return result_type(parse_integer::invoke(iter, end)); -// else if(iter != is_boolean::invoke(iter)) -// return result_type(parse_boolean::invoke(iter, end)); -// else if(iter != is_array::invoke(iter)) -// return result_type(parse_array::invoke(iter, end)); -// else if(iter != is_inline_table::invoke(iter)) -// return result_type(parse_inline_table::invoke(iter, end)); -// -// throw internal_error("no valid value here"); -// } -// }; -// -// template -// struct parse_barekey -// { -// typedef charT value_type; -// typedef toml::key result_type; -// static_assert(std::is_same::value, "char type is different from default key type"); -// -// template::value_type, -// value_type>::value>::type> -// static result_type invoke(Iterator iter, Iterator end) -// { -// return result_type(iter, end); -// } -// }; -// -// template -// struct parse_key -// { -// typedef charT value_type; -// typedef toml::key result_type; -// static_assert(std::is_same::value, "char type is different from default key type"); -// -// template::value_type, -// value_type>::value>::type> -// static result_type invoke(Iterator iter, Iterator end) -// { -// if(iter != is_barekey::invoke(iter)) -// return parse_barekey::invoke(iter, end); -// else if(iter != is_string::invoke(iter)) -// return parse_string::invoke(iter, end); -// throw internal_error("no valid key here"); -// } -// }; -// -// template -// struct parse_key_value_pair -// { -// typedef charT value_type; -// typedef std::pair result_type; -// -// template::value_type, -// value_type>::value>::type> -// static result_type invoke(Iterator iter, Iterator end) -// { -// Iterator tmp = is_key::invoke(iter); -// const toml::key k = parse_key::invoke(iter, tmp); -// iter = tmp; -// iter = is_any_num_of_ws::invoke(iter); -// assert(*iter == '='); ++iter; -// iter = is_any_num_of_ws::invoke(iter); -// tmp = is_value::invoke(iter); -// const toml::value v = parse_value::invoke(iter, tmp); -// return std::make_pair(k, v); -// } -// }; -// -// template -// struct parse_inline_table -// { -// typedef charT value_type; -// typedef toml::Table result_type; -// -// template::value_type, -// value_type>::value>::type> -// static result_type invoke(Iterator iter, Iterator end) -// { -// --end; -// assert(*iter == '{' && *end == '}'); -// ++iter; -// iter = is_any_num_of_ws::invoke(iter); -// -// result_type result; -// -// while(iter != end) -// { -// Iterator tmp = is_key_value_pair::invoke(iter); -// result.emplace(parse_key_value_pair::invoke(iter, tmp)); -// iter = tmp; -// -// iter = is_any_num_of_ws::invoke(iter); -// iter = is_charactor::invoke(iter); -// iter = is_any_num_of_ws::invoke(iter); -// } -// return result; -// } -// }; -// +struct parse_local_time +{ + typedef toml::charactor value_type; + typedef std::basic_string string_type; + typedef detail::result result_type; + typedef typename toml::Datetime::number_type number_type; + template + using nums = is_repeat_of, N>; + typedef is_charactor delim; + typedef is_charactor fract; + + template::value_type, + value_type>::value>::type> + static std::pair invoke(Iterator iter) + { + const Iterator end = is_local_time::invoke(iter); + if(iter == end) return std::make_pair(result_type{}, iter); + + toml::Datetime result; + result.hour = std::stoi(string_type(iter, nums<2>::invoke(iter))); + iter = delim::invoke(nums<2>::invoke(iter)); + result.minute = std::stoi(string_type(iter, nums<2>::invoke(iter))); + iter = delim::invoke(nums<2>::invoke(iter)); + result.second = std::stoi(string_type(iter, nums<2>::invoke(iter))); + iter = fract::invoke(nums<2>::invoke(iter)); + if(iter == end) + { + result.millisecond = 0.0; + result.microsecond = 0.0; + } + else if(std::distance(iter, end) <= 3) + { + result.millisecond = parse_number(iter, end); + result.microsecond = 0.0; + } + else + { + result.millisecond = parse_number(iter, iter + 3); + result.microsecond = parse_number(iter + 3, end); + } + result.offset_hour = toml::Datetime::nooffset; + result.offset_minute = toml::Datetime::nooffset; + result.year = toml::Datetime::undef; + result.month = toml::Datetime::undef; + result.day = toml::Datetime::undef; + return std::make_pair(result, end); + } + + template::value_type, + value_type>::value>::type> + static number_type parse_number(Iterator iter, Iterator end) + { + if(std::distance(iter, end) > 3) end = iter + 3; + string_type str(iter, end); + while(str.size() < 3){str += '0';} + return std::stoi(str); + } +}; + +struct parse_local_date +{ + typedef toml::charactor value_type; + typedef std::basic_string string_type; + typedef detail::result result_type; + template + using nums = is_repeat_of, N>; + typedef is_charactor delim; + + template::value_type, + value_type>::value>::type> + static std::pair invoke(Iterator iter) + { + const Iterator end = is_local_date::invoke(iter); + if(iter == end) return std::make_pair(result_type{}, iter); + + toml::Datetime result; + result.year = std::stoi(string_type(iter, nums<4>::invoke(iter))); + iter = delim::invoke(nums<4>::invoke(iter)); + result.month = std::stoi(string_type(iter, nums<2>::invoke(iter))); + iter = delim::invoke(nums<2>::invoke(iter)); + result.day = std::stoi(string_type(iter, nums<2>::invoke(iter))); + + result.offset_hour = toml::Datetime::nooffset; + result.offset_minute = toml::Datetime::nooffset; + result.hour = toml::Datetime::undef; + result.minute = toml::Datetime::undef; + result.second = toml::Datetime::undef; + result.millisecond = toml::Datetime::undef; + result.microsecond = toml::Datetime::undef; + return std::make_pair(result, end); + } +}; + +struct parse_local_date_time +{ + typedef toml::charactor value_type; + typedef std::basic_string string_type; + typedef detail::result result_type; + template + using nums = is_repeat_of, N>; + typedef is_charactor delim; + + template::value_type, + value_type>::value>::type> + static std::pair invoke(Iterator iter) + { + const Iterator end = is_local_date_time::invoke(iter); + if(iter == end) return std::make_pair(result_type{}, iter); + + auto ld = parse_local_date::invoke(iter); + if(!ld.first.ok()) throw syntax_error("invalid local datetime"); + toml::Datetime result(ld.first.move()); + iter = delim::invoke(ld.second);// 'T' + + const auto time = parse_local_time::invoke(iter); + result.hour = time.first.get().hour; + result.minute = time.first.get().minute; + result.second = time.first.get().second; + result.millisecond = time.first.get().millisecond; + result.microsecond = time.first.get().microsecond; + result.offset_hour = toml::Datetime::nooffset; + result.offset_minute = toml::Datetime::nooffset; + return std::make_pair(result, end); + } +}; + +struct parse_offset_date_time +{ + typedef toml::charactor value_type; + typedef std::basic_string string_type; + typedef detail::result result_type; + template + using nums = is_repeat_of, N>; + typedef is_charactor delim; + + template::value_type, + value_type>::value>::type> + static std::pair invoke(Iterator iter) + { + const Iterator end = is_offset_date_time::invoke(iter); + if(iter == end) return std::make_pair(result_type{}, iter); + + auto ldt = parse_local_date_time::invoke(iter); + if(!ldt.first.ok()) throw syntax_error("invalid offset datetime"); + toml::Datetime result(ldt.first.move()); + iter = ldt.second; + if(*iter == 'Z') + { + result.offset_hour = 0; + result.offset_minute = 0; + } + else + { + if(*iter != '+' && *iter != '-') + throw syntax_error("invalid offset-datetime"); + const int sign = (*iter == '-') ? -1 : 1; + ++iter; + result.offset_hour = sign * + std::stoi(string_type(iter, nums<2>::invoke(iter))); + iter = delim::invoke(nums<2>::invoke(iter)); + result.offset_minute = sign * + std::stoi(string_type(iter, nums<2>::invoke(iter))); + } + return std::make_pair(result, end); + } +}; + +struct parse_datetime +{ + typedef toml::charactor value_type; + typedef detail::result result_type; + + template::value_type, + value_type>::value>::type> + static std::pair invoke(Iterator iter) + { + std::pair result; + if((result = parse_offset_date_time::invoke(iter)).first.ok()) + return result; + else if((result = parse_local_date_time::invoke(iter)).first.ok()) + return result; + else if((result = parse_local_date::invoke(iter)).first.ok()) + return result; + else if((result = parse_local_time::invoke(iter)).first.ok()) + return result; + else + return std::make_pair(result_type{}, iter); + } +}; + +template +struct parse_fixed_type_array +{ + typedef toml::charactor value_type; + typedef detail::result result_type; + typedef acceptorT acceptor_type; + typedef parserT parser_type; + typedef is_skippable_in_array skippable; + + template::value_type, + value_type>::value>::type> + static std::pair invoke(Iterator iter) + { + const Iterator end = is_fixed_type_array::invoke(iter); + if(iter == end) return std::make_pair(result_type{}, iter); + + toml::Array result; + const Iterator last = std::prev(end); + iter = skippable::invoke(std::next(iter)); + while(iter != last) + { + const Iterator tmp = acceptor_type::invoke(iter); + if(tmp == iter) throw syntax_error("parse_array"); + auto next = parser_type::invoke(iter); + if(!next.first.ok()) throw syntax_error("parse_array"); + result.emplace_back(next.first.move()); + iter = tmp; + iter = skippable::invoke(iter); + iter = is_charactor::invoke(iter); + iter = skippable::invoke(iter); + } + return std::make_pair(result, end); + } +}; + +template +struct parse_inline_table; + +template +struct parse_array +{ + typedef charT value_type; + static_assert(std::is_same::value, ""); + typedef detail::result result_type; + typedef is_skippable_in_array skippable; + + template::value_type, + value_type>::value>::type> + static std::pair invoke(Iterator iter) + { + if(iter == is_array::invoke(iter)) + return std::make_pair(result_type{}, iter); + + std::pair result; + if((result = parse_fixed_type_array, + parse_boolean>::invoke(iter)).first.ok()) return result; + else if((result = parse_fixed_type_array, + parse_string>::invoke(iter)).first.ok()) return result; + else if((result = parse_fixed_type_array, + parse_datetime>::invoke(iter)).first.ok()) return result; + else if((result = parse_fixed_type_array, + parse_float>::invoke(iter)).first.ok()) return result; + else if((result = parse_fixed_type_array, + parse_integer>::invoke(iter)).first.ok()) return result; + else if((result = parse_fixed_type_array, + parse_array>::invoke(iter)).first.ok()) return result; + else if((result = parse_fixed_type_array, + parse_inline_table>::invoke(iter)).first.ok()) + return result; + else if(skippable::invoke(std::next(iter)) == // empty + std::prev(is_array::invoke(iter)) + ) return std::make_pair( + toml::Array{}, is_array::invoke(iter)); + else throw syntax_error("no valid array here"); + } +}; + +template +struct parse_value +{ + typedef charT value_type; + static_assert(std::is_same::value, ""); + typedef detail::result result_type; + + template::value_type, + value_type>::value>::type> + static std::pair invoke(Iterator iter) + { + std::pair result; + if((result = parse_boolean::invoke(iter)).first.ok()) + return result; + else if((result = parse_string::invoke(iter)).first.ok()) + return result; + else if((result = parse_datetime::invoke(iter)).first.ok()) + return result; + else if((result = parse_float::invoke(iter)).first.ok()) + return result; + else if((result = parse_integer::invoke(iter)).first.ok()) + return result; + else if((result = parse_array::invoke(iter)).first.ok()) + return result; + else if((result = parse_inline_table::invoke(iter)).first.ok()) + return result; + else + return std::make_pair(result_type{}, iter); + } +}; + +struct parse_barekey +{ + typedef toml::charactor value_type; + typedef detail::result result_type; + + template::value_type, + value_type>::value>::type> + static std::pair invoke(Iterator iter) + { + const Iterator end = is_barekey::invoke(iter); + if(iter == end) return std::make_pair(result_type{}, iter); + return std::make_pair(toml::key(iter, end), end); + } +}; + +struct parse_key +{ + typedef toml::charactor value_type; + typedef detail::result result_type; + + template::value_type, + value_type>::value>::type> + static std::pair invoke(Iterator iter) + { + std::pair result; + if((result = parse_barekey::invoke(iter)).first.ok()) + return result; + else if((result = parse_string::invoke(iter)).first.ok()) + return result; + else return std::make_pair(result_type{}, iter); + } +}; + +template +struct parse_key_value_pair +{ + typedef charT value_type; + static_assert(std::is_same::value, ""); + typedef detail::result> result_type; + + template::value_type, + value_type>::value>::type> + static std::pair invoke(Iterator iter) + { + auto tmp_key = parse_key::invoke(iter); + if(!tmp_key.first.ok()) + return std::make_pair(result_type{}, iter); + iter = is_any_num_of_ws::invoke(tmp_key.second); + if(*iter != '=') throw syntax_error("invalid key value pair"); + iter = is_any_num_of_ws::invoke(std::next(iter)); + + auto tmp_value = parse_value::invoke(iter); + if(!tmp_value.first.ok()) + throw syntax_error("invalid key value pair"); + + iter = tmp_value.second; + + return std::make_pair(std::make_pair( + tmp_key.first.move(), tmp_value.first.move()), + is_any_num_of_ws::invoke(tmp_value.second)); + } +}; + +template +struct parse_inline_table +{ + typedef charT value_type; + static_assert(std::is_same::value, ""); + typedef detail::result result_type; + + template::value_type, + value_type>::value>::type> + static std::pair invoke(Iterator iter) + { + const Iterator end = is_inline_table::invoke(iter); + if(iter == end) return std::make_pair(result_type{}, iter); + + iter = is_any_num_of_ws::invoke(std::next(iter)); + + const Iterator last = std::prev(end); + toml::Table result; + while(iter != last) + { + auto tmp = parse_key_value_pair::invoke(iter); + if(!tmp.first.ok()) throw syntax_error("parse_inline_table"); + + result.emplace(tmp.first.move()); + iter = tmp.second; + + iter = is_any_num_of_ws::invoke(iter); + iter = is_charactor::invoke(iter); + iter = is_any_num_of_ws::invoke(iter); + } + return std::make_pair(result, end); + } +}; + // template // struct parse_table_contents // {