diff --git a/tests/test_parser.cpp b/tests/test_parser.cpp index 430aeed..0f2f0aa 100644 --- a/tests/test_parser.cpp +++ b/tests/test_parser.cpp @@ -294,6 +294,12 @@ BOOST_AUTO_TEST_CASE(test_float) BOOST_CHECK(!result.first.ok()); BOOST_CHECK(result.second == source.begin()); } + { + const std::string source("42"); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(result.second == source.begin()); + } } BOOST_AUTO_TEST_CASE(test_parse_boolean) @@ -354,6 +360,12 @@ BOOST_AUTO_TEST_CASE(test_parse_local_time) BOOST_CHECK_EQUAL(result.first.get(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin())); } + { + const std::string source("10"); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(result.second == source.begin()); + } } BOOST_AUTO_TEST_CASE(test_parse_local_date) @@ -368,6 +380,12 @@ BOOST_AUTO_TEST_CASE(test_parse_local_date) BOOST_CHECK_EQUAL(result.first.get(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin())); } + { + const std::string source("10"); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(result.second == source.begin()); + } } BOOST_AUTO_TEST_CASE(test_parse_local_date_time) @@ -390,6 +408,12 @@ BOOST_AUTO_TEST_CASE(test_parse_local_date_time) BOOST_CHECK_EQUAL(result.first.get(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin())); } + { + const std::string source("1000-11-11"); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(result.second == source.begin()); + } } BOOST_AUTO_TEST_CASE(test_parse_offset_date_time) @@ -446,6 +470,12 @@ BOOST_AUTO_TEST_CASE(test_parse_offset_date_time) BOOST_CHECK_EQUAL(result.first.get(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin())); } + { + const std::string source("1000-11-11"); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(result.second == source.begin()); + } } BOOST_AUTO_TEST_CASE(test_parse_datetime) @@ -484,6 +514,12 @@ BOOST_AUTO_TEST_CASE(test_parse_datetime) BOOST_CHECK_EQUAL(result.first.get(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin())); } + { + const std::string source("12"); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(result.second == source.begin()); + } } @@ -583,6 +619,12 @@ BOOST_AUTO_TEST_CASE(test_parse_array) BOOST_CHECK(result.first.get() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin())); } + { + const std::string source("[dummy]"); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(result.second == source.begin()); + } } @@ -626,207 +668,268 @@ BOOST_AUTO_TEST_CASE(test_parse_inline_table) BOOST_CHECK(result.first.get() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin())); } + { + const std::string source("{dummy}"); + const auto result = parser::invoke(source.cbegin()); + BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(result.second == source.begin()); + } } -// -// // BOOST_AUTO_TEST_CASE(test_parse_barekey) -// // { -// // { -// // const std::string source("hoge"); -// // const std::string result = toml::parse_barekey::invoke( -// // source.cbegin(), toml::is_barekey::invoke(source.cbegin())); -// // BOOST_CHECK_EQUAL(source, result); -// // } -// // { -// // const std::string source("bare-key"); -// // const std::string result = toml::parse_barekey::invoke( -// // source.cbegin(), toml::is_barekey::invoke(source.cbegin())); -// // BOOST_CHECK_EQUAL(source, result); -// // } -// // { -// // const std::string source("bare_key"); -// // const std::string result = toml::parse_barekey::invoke( -// // source.cbegin(), toml::is_barekey::invoke(source.cbegin())); -// // BOOST_CHECK_EQUAL(source, result); -// // } -// // { -// // const std::string source("42"); -// // const std::string result = toml::parse_barekey::invoke( -// // source.cbegin(), toml::is_barekey::invoke(source.cbegin())); -// // BOOST_CHECK_EQUAL(source, result); -// // } -// // } -// -// -// -// BOOST_AUTO_TEST_CASE(test_key_value_pair) -// { -// typedef toml::parse_key_value_pair parser; -// typedef toml::is_key_value_pair acceptor; -// { -// const std::string source("key=1"); -// const std::pair expected{"key", 1}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("key =\t1"); -// const std::pair expected{"key", 1}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("key = true"); -// const std::pair expected{"key", true}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("key = -42"); -// const std::pair expected{"key", -42}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("key = -42.0"); -// const std::pair expected{"key", -42.}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("key = \"string\""); -// const std::pair expected{"key", "string"}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("key = 1901-01-01T00:00:00"); -// const std::pair expected{"key", toml::Datetime(1901, 1,1,0,0,0,0,0)}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("key = [1,2,3]"); -// const std::pair expected{"key", {1,2,3}}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("key = {foo=1,bar=2.0,baz='3'}"); -// const std::pair expected{"key", -// {{"foo", 1}, {"bar", 2.0}, {"baz", "3"}}}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// } -// -// BOOST_AUTO_TEST_CASE(test_table_definition) -// { -// typedef toml::parse_standard_table_definition parser; -// typedef toml::is_table_definition acceptor; -// { -// const std::string source("[foo]"); -// const std::vector expected{"foo"}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("[foo.bar.baz]"); -// const std::vector expected{"foo", "bar", "baz"}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("[foo . bar. baz]"); -// const std::vector expected{"foo", "bar", "baz"}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("[foo . \"bar\" . baz]"); -// const std::vector expected{"foo", "bar", "baz"}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("[foo . \"b\\tar\" . baz]"); -// const std::vector expected{"foo", "b\tar", "baz"}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// } -// -// BOOST_AUTO_TEST_CASE(test_array_of_table_definition) -// { -// typedef toml::parse_array_of_table_definition parser; -// typedef toml::is_array_of_table_definition acceptor; -// { -// const std::string source("[[foo]]"); -// const std::vector expected{"foo"}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("[[foo.bar.baz]]"); -// const std::vector expected{"foo", "bar", "baz"}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("[[foo . bar. baz]]"); -// const std::vector expected{"foo", "bar", "baz"}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("[[foo . \"bar\" . baz]]"); -// const std::vector expected{"foo", "bar", "baz"}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// { -// const std::string source("[[foo . \"b\\tar\" . baz]]"); -// const std::vector expected{"foo", "b\tar", "baz"}; -// const auto result = parser::invoke( -// source.cbegin(), acceptor::invoke(source.cbegin())); -// const bool check = result == expected; -// BOOST_CHECK(check); -// } -// } -// +BOOST_AUTO_TEST_CASE(test_parse_barekey) +{ + typedef toml::parse_barekey parser; + typedef toml::is_barekey acceptor; + { + const std::string source("hoge"); + const toml::key expected("hoge"); + 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("bare-key"); + const toml::key expected("bare-key"); + 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("bare_key"); + const toml::key expected("bare_key"); + 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("42"); + const toml::key expected("42"); + 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_key_value_pair) +{ + typedef toml::parse_key_value_pair parser; + typedef toml::is_key_value_pair acceptor; + { + const std::string source("key=1"); + const std::pair expected{"key", 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())); + } + { + const std::string source("key =\t1"); + const std::pair expected{"key", 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())); + } + { + const std::string source("key = true"); + const std::pair expected{"key", true}; + 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("key = -42"); + const std::pair expected{"key", -42}; + 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("key = -42.0"); + const std::pair expected{"key", -42.}; + 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("key = \"string\""); + const std::pair expected{"key", "string"}; + 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("key = 1901-01-01T00:00:00"); + const std::pair expected{"key", toml::Datetime(1901, 1,1,0,0,0,0,0)}; + 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("key = [1,2,3]"); + const std::pair expected{"key", {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("key = {foo=1,bar=2.0,baz='3'}"); + const std::pair expected{"key", + {{"foo", 1}, {"bar", 2.0}, {"baz", "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())); + } +} + +BOOST_AUTO_TEST_CASE(test_table_definition) +{ + typedef toml::parse_table_definition parser; + typedef toml::is_table_definition acceptor; + { + const std::string source("[foo]"); + const std::vector expected{"foo"}; + 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.bar.baz]"); + const std::vector expected{"foo", "bar", "baz"}; + 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 . bar. baz]"); + const std::vector expected{"foo", "bar", "baz"}; + 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 . \"bar\" . baz]"); + const std::vector expected{"foo", "bar", "baz"}; + 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 . \"b\\tar\" . baz]"); + const std::vector expected{"foo", "b\tar", "baz"}; + 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_array_of_table_definition) +{ + typedef toml::parse_array_of_table_definition parser; + typedef toml::is_array_of_table_definition acceptor; + { + const std::string source("[[foo]]"); + const std::vector expected{"foo"}; + 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.bar.baz]]"); + const std::vector expected{"foo", "bar", "baz"}; + 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 . bar. baz]]"); + const std::vector expected{"foo", "bar", "baz"}; + 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 . \"bar\" . baz]]"); + const std::vector expected{"foo", "bar", "baz"}; + 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 . \"b\\tar\" . baz]]"); + const std::vector expected{"foo", "b\tar", "baz"}; + 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_data) +{ + typedef toml::parse_data parser; + { + const std::string source("#hogehoge"); + const toml::Table expected{}; + const auto result = parser::invoke(source.cbegin(), source.cend()); + BOOST_CHECK(result == expected); + } + { + const std::string source("key = 'value'"); + const toml::Table expected{{"key", "value"}}; + const auto result = parser::invoke(source.cbegin(), source.cend()); + BOOST_CHECK(result == expected); + } + { + const std::string source("key = 'value' #hoge"); + const toml::Table expected{{"key", "value"}}; + const auto result = parser::invoke(source.cbegin(), source.cend()); + BOOST_CHECK(result == expected); + } + { + const std::string source("[table]\nkey = 'value' #hoge"); + const toml::Table expected{{"table", {{"key", "value"}} }}; + const auto result = parser::invoke(source.cbegin(), source.cend()); + BOOST_CHECK(result == expected); + } + { + const std::string source("[table]\n\tkey = 'value'\n\t#hoge"); + const toml::Table expected{{"table", {{"key", "value"}} }}; + const auto result = parser::invoke(source.cbegin(), source.cend()); + BOOST_CHECK(result == expected); + } + { + const std::string source("[table]\n\tkey = 'value'\n\t#hoge"); + const toml::Table expected{{"table", {{"key", "value"}} }}; + const auto result = parser::invoke(source.cbegin(), source.cend()); + BOOST_CHECK(result == expected); + } + { + const std::string source("[nested.table]\n\tkey = 'value'\n\t#hoge"); + const toml::Table expected{{"nested", {{"table", {{"key", "value"}}}}}}; + const auto result = parser::invoke(source.cbegin(), source.cend()); + BOOST_CHECK(result == expected); + } +} diff --git a/toml/parser.hpp b/toml/parser.hpp index 226181e..cb0e919 100644 --- a/toml/parser.hpp +++ b/toml/parser.hpp @@ -757,197 +757,220 @@ struct parse_inline_table } }; -// template -// struct parse_table_contents -// { -// typedef charT value_type; -// typedef toml::Table result_type; -// -// template::value_type, -// value_type>::value>::type> -// static result_type invoke(Iterator iter, Iterator end) -// { -// result_type result; -// while(iter != end) -// { -// iter = is_empty_lines::invoke(iter); -// -// Iterator tmp = is_key_value_pair::invoke(iter); -// result.emplace(parse_key_value_pair::invoke(iter, tmp)); -// iter = is_one_of, is_newline>::invoke(tmp); -// -// iter = is_empty_lines::invoke(iter); -// } -// return result; -// } -// }; -// -// template -// struct parse_standard_table_definition -// { -// typedef charT value_type; -// typedef std::vector result_type; -// -// template::value_type, -// value_type>::value>::type> -// static result_type invoke(Iterator iter, Iterator end) -// { -// result_type result; -// iter = is_any_num_of_ws::invoke(iter); -// --end; -// assert(*iter == '[' && *end == ']'); -// ++iter; -// iter = is_any_num_of_ws::invoke(iter); -// -// Iterator tmp = is_key::invoke(iter); -// result.emplace_back(parse_key::invoke(iter, tmp)); -// iter = is_any_num_of_ws::invoke(tmp); -// -// while(iter != end) -// { -// iter = is_charactor::invoke(iter); -// iter = is_any_num_of_ws::invoke(iter); -// -// tmp = is_key::invoke(iter); -// result.emplace_back(parse_key::invoke(iter, tmp)); -// iter = is_any_num_of_ws::invoke(tmp); -// } -// return result; -// } -// }; -// -// template -// struct parse_array_of_table_definition -// { -// typedef charT value_type; -// typedef std::vector result_type; -// -// template::value_type, -// value_type>::value>::type> -// static result_type invoke(Iterator iter, Iterator end) -// { -// result_type result; -// iter = is_any_num_of_ws::invoke(iter); -// --end; -// assert(*iter == '[' && *std::next(iter) == '[' && -// *end == ']' && *std::prev(end) == ']'); -// ++iter; ++iter; --end; -// -// iter = is_any_num_of_ws::invoke(iter); -// -// Iterator tmp = is_key::invoke(iter); -// result.emplace_back(parse_key::invoke(iter, tmp)); -// iter = is_any_num_of_ws::invoke(tmp); -// -// while(iter != end) -// { -// iter = is_charactor::invoke(iter); -// iter = is_any_num_of_ws::invoke(iter); -// -// tmp = is_key::invoke(iter); -// result.emplace_back(parse_key::invoke(iter, tmp)); -// iter = is_any_num_of_ws::invoke(tmp); -// } -// return result; -// } -// }; -// -// template -// struct parse_data -// { -// typedef charT value_type; -// typedef toml::Table result_type; -// -// template::value_type, -// value_type>::value>::type> -// static result_type invoke(Iterator iter, Iterator end) -// { -// result_type result; -// -// Iterator tmp = is_table_contents::invoke(iter); -// if(tmp != iter) -// { -// result = parse_table_contents::invoke(iter, tmp); -// } -// -// while(iter != end) -// { -// if(iter != (tmp = is_table_definition::invoke(iter))) -// { -// auto k = parse_standard_table_definition::invoke(iter, tmp); -// iter = tmp; -// tmp = is_table_contents::invoke(iter); -// auto tab = parse_table_contents::invoke(iter, tmp); -// push_table(result, std::move(tab), std::begin(k), std::end(k)); -// } -// else if(iter != (tmp=is_array_of_table_definition::invoke(iter))) -// { -// auto k = parse_array_of_table_definition::invoke(iter, tmp); -// iter = tmp; -// tmp = is_table_contents::invoke(iter); -// auto tab = parse_table_contents::invoke(iter, tmp); -// push_array_of_table(result, std::move(tab), -// std::begin(k), std::end(k)); -// } -// else -// throw internal_error("no array "); -// } -// return result; -// } -// -// template::value_type, -// toml::key>::value>::type> -// static void -// push_table(toml::Table& data, toml::Table&& v, Iterator iter, Iterator end) -// { -// if(iter == std::prev(end)) -// { -// if(data.count(*iter) == 1) -// throw syntax_error("duplicate key"); -// data.emplace(*iter, std::move(v)); -// } -// -// if(data.count(*iter) == 0) -// data.emplace(*iter, toml::Table()); -// else if(data[*iter].type() != value_t::Table) -// throw syntax_error("duplicate key"); -// -// return push_table(data[*iter].template cast(), -// std::move(v), std::next(iter), end); -// } -// -// template::value_type, -// toml::key>::value>::type> -// static void -// push_array_of_table(toml::Table& data, toml::Table&& v, -// Iterator iter, Iterator end) -// { -// if(iter == std::prev(end)) -// { -// if(data.count(*iter) == 0) -// data.emplace(*iter, toml::Array()); -// else if(data.at(*iter).type() != value_t::Array) -// throw syntax_error("duplicate key"); -// -// data[*iter].template cast().emplace_back(std::move(v)); -// } -// -// if(data.count(*iter) == 0) -// data.emplace(*iter, toml::Table()); -// else if(data[*iter].type() != value_t::Table) -// throw syntax_error("duplicate key"); -// -// return push_array_of_table(data[*iter].template cast(), -// std::move(v), std::next(iter), end); -// } -// -// }; +struct parse_table_definition +{ + 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_table_definition::invoke(iter); + if(iter == end) return std::make_pair(result_type{}, iter); + + std::vector result; + result.reserve(std::count(iter, end, '.')+1); + + const Iterator last = std::prev(end); + iter = is_any_num_of_ws::invoke(iter); + iter = is_any_num_of_ws::invoke(std::next(iter)); + + auto tmp = parse_key::invoke(iter); + if(!tmp.first.ok()) throw syntax_error("table definition"); + result.emplace_back(tmp.first.move()); + iter = is_any_num_of_ws::invoke(tmp.second); + + while(iter != last) + { + iter = is_charactor::invoke(iter); + iter = is_any_num_of_ws::invoke(iter); + + tmp = parse_key::invoke(iter); + if(!tmp.first.ok()) throw syntax_error("table definition"); + result.emplace_back(tmp.first.move()); + iter = is_any_num_of_ws::invoke(tmp.second); + } + return std::make_pair(result, end); + } +}; + +struct parse_array_of_table_definition +{ + 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_array_of_table_definition::invoke(iter); + if(iter == end) return std::make_pair(result_type{}, iter); + + std::vector result; + result.reserve(std::count(iter, end, '.')+1); + + const Iterator last = end - 2; + iter = is_any_num_of_ws::invoke(iter) + 2; + iter = is_any_num_of_ws::invoke(iter); + + auto tmp = parse_key::invoke(iter); + if(!tmp.first.ok()) throw syntax_error("array of table definition"); + result.emplace_back(tmp.first.move()); + iter = is_any_num_of_ws::invoke(tmp.second); + + while(iter != last) + { + iter = is_charactor::invoke(iter); + iter = is_any_num_of_ws::invoke(iter); + + tmp = parse_key::invoke(iter); + if(!tmp.first.ok()) throw syntax_error("array of table definition"); + result.emplace_back(tmp.first.move()); + iter = is_any_num_of_ws::invoke(tmp.second); + } + return std::make_pair(result, end); + } +}; + +struct parse_data +{ + typedef toml::charactor value_type; + typedef toml::Table result_type; + + template::value_type, + value_type>::value>::type> + static result_type invoke(Iterator iter, const Iterator end) + { + toml::Table result; + auto noname = parse_table_contents(iter, end); + result = std::move(noname.first); + iter = skip_empty(noname.second, end); + + while(iter != end) + { + iter = skip_empty(iter, end); + std::pair>, Iterator> tabname; + if((tabname = parse_table_definition::invoke(iter)).first.ok()) + { + auto contents = parse_table_contents(tabname.second, end); + push_table(result, std::move(contents.first), + tabname.first.get().begin(), tabname.first.get().end()); + iter = contents.second; + } + else if((tabname = parse_array_of_table_definition::invoke(iter)).first.ok()) + { + auto contents = parse_table_contents(tabname.second, end); + push_array_of_table(result, std::move(contents.first), + tabname.first.get().begin(), tabname.first.get().end()); + iter = contents.second; + } + else + throw syntax_error("parse_data: unknown line"); + } + return result; + } + + template::value_type, + value_type>::value>::type> + static Iterator + skip_empty(Iterator iter, Iterator end) + { + while(iter != end) + { + if(*iter == '#') + { + while(iter != end && + iter == is_newline::invoke(iter)){++iter;} + } + else if(iter == is_newline::invoke(iter) && + iter == is_whitespace::invoke(iter)) + { + return iter; + } + else + { + ++iter; + } + } + return iter; + } + + template::value_type, + value_type>::value>::type> + static std::pair + parse_table_contents(Iterator iter, Iterator end) + { + toml::Table table; + iter = skip_empty(iter, end); + while(iter != end) + { + auto kv = parse_key_value_pair::invoke(iter); + if(!kv.first.ok()) return std::make_pair(table, iter); + + table.emplace(kv.first.move()); + iter = kv.second; + iter = skip_empty(iter, end); + } + return std::make_pair(table, iter); + } + + template::value_type, + toml::key>::value>::type> + static void + push_table(toml::Table& data, toml::Table&& v, Iterator iter, Iterator end) + { + if(iter == std::prev(end)) + { + if(data.count(*iter) == 1) + throw syntax_error("duplicate key"); + data.emplace(*iter, std::move(v)); + return; + } + + if(data.count(*iter) == 0) + data.emplace(*iter, toml::Table()); + else if(data[*iter].type() != value_t::Table) + throw syntax_error("duplicate key"); + + return push_table(data[*iter].template cast(), + std::move(v), std::next(iter), end); + } + + template::value_type, + toml::key>::value>::type> + static void + push_array_of_table(toml::Table& data, toml::Table&& v, + Iterator iter, Iterator end) + { + if(iter == std::prev(end)) + { + if(data.count(*iter) == 0) + data.emplace(*iter, toml::Array()); + else if(data.at(*iter).type() != value_t::Array) + throw syntax_error("duplicate key"); + + data[*iter].template cast().emplace_back(std::move(v)); + return; + } + + if(data.count(*iter) == 0) + data.emplace(*iter, toml::Table()); + else if(data[*iter].type() != value_t::Table) + throw syntax_error("duplicate key"); + + return push_array_of_table(data[*iter].template cast(), + std::move(v), std::next(iter), end); + } + +}; }// toml #endif// TOML11_PARSER