From 88e2c3fe482e99e7d06f6b69e282d3ee15f23016 Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Wed, 10 May 2017 23:56:09 +0900 Subject: [PATCH] change impl of parser: optional based --- tests/test_parser.cpp | 1005 ++++++++++++++------------- toml/parser.hpp | 1494 +++++++++++++++++++++-------------------- 2 files changed, 1316 insertions(+), 1183 deletions(-) diff --git a/tests/test_parser.cpp b/tests/test_parser.cpp index fb4181b..8669af8 100644 --- a/tests/test_parser.cpp +++ b/tests/test_parser.cpp @@ -10,504 +10,609 @@ #include #include -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_parse_basic_inline_string) { - typedef toml::parse_basic_inline_string parser; - typedef toml::is_basic_inline_string acceptor; + typedef toml::parse_basic_inline_string parser; + typedef toml::is_basic_inline_string acceptor; { const std::string source("\"simple\""); const std::string expected("simple"); - const std::string result = parser::invoke( - source.cbegin(), acceptor::invoke(source.cbegin())); - BOOST_CHECK_EQUAL(result, expected); + 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("\"I'm a string. \\\"You can quote me\\\". Name\\tJos\\u00E9\\nLocation\\tSF.\""); const std::string expected("I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF."); - const std::string result = parser::invoke( - source.cbegin(), acceptor::invoke(source.cbegin())); - BOOST_CHECK_EQUAL(result, expected); + 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_basic_multiline_string) { - typedef toml::parse_basic_multiline_string parser; - typedef toml::is_basic_multiline_string acceptor; + typedef toml::parse_basic_multiline_string parser; + typedef toml::is_basic_multiline_string acceptor; { - const std::string source("\"\"\"\nRoses are red\nViolets are blue\"\"\""); //XXX ifdef windows platform + const std::string source("\"\"\"\nRoses are red\nViolets are blue\"\"\""); const std::string expected("Roses are red\nViolets are blue"); - const std::string result = parser::invoke( - source.cbegin(), acceptor::invoke(source.cbegin())); - BOOST_CHECK_EQUAL(result, expected); + 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("\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\""); const std::string expected("The quick brown fox jumps over the lazy dog."); - const std::string result = parser::invoke( - source.cbegin(), acceptor::invoke(source.cbegin())); - BOOST_CHECK_EQUAL(result, expected); + 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("\"\"\"\nThe quick brown \\\n fox jumps over \\\n the lazy dog.\\\n \"\"\""); const std::string expected("The quick brown fox jumps over the lazy dog."); - const std::string result = parser::invoke( - source.cbegin(), acceptor::invoke(source.cbegin())); - BOOST_CHECK_EQUAL(result, expected); + 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_time) +BOOST_AUTO_TEST_CASE(test_parse_literal_inline_string) { - typedef toml::parse_local_time parser; - typedef toml::is_local_time acceptor; + typedef toml::parse_literal_inline_string parser; + typedef toml::is_literal_inline_string 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("'C:\\Users\\nodejs\\templates'"); + const std::string expected("C:\\Users\\nodejs\\templates"); + 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 toml::Datetime result = parser::invoke( - source.cbegin(), acceptor::invoke(source.cbegin())); - BOOST_CHECK_EQUAL(result, expected); + const std::string source("'\\\\ServerX\\admin$\\system32\\'"); + const std::string expected("\\\\ServerX\\admin$\\system32\\"); + 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 toml::Datetime result = parser::invoke( - source.cbegin(), acceptor::invoke(source.cbegin())); - BOOST_CHECK_EQUAL(result, expected); + const std::string source("'Tom \"Dubs\" Preston-Werner'"); + const std::string expected("Tom \"Dubs\" Preston-Werner"); + 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("'<\\i\\c*\\s*>'"); + const std::string expected("<\\i\\c*\\s*>"); + 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) +BOOST_AUTO_TEST_CASE(test_parse_literal_multiline_string) { - typedef toml::parse_local_date parser; - typedef toml::is_local_date acceptor; + typedef toml::parse_literal_multiline_string parser; + typedef toml::is_literal_multiline_string 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); + const std::string source("'''I [dw]on't need \\d{2} apples'''"); + const std::string expected("I [dw]on't need \\d{2} apples"); + 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("'''\nThe first newline is \ntrimmed in raw strings.\n All other whitespace\n is preserved.'''"); + const std::string expected("The first newline is \ntrimmed in raw strings.\n All other whitespace\n is preserved."); + 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) +BOOST_AUTO_TEST_CASE(test_parse_string) { - typedef toml::parse_local_date_time parser; - typedef toml::is_local_date_time acceptor; + typedef toml::parse_string parser; + typedef toml::is_string 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("\"string\""); + const std::string expected("string"); + 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 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_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); + const std::string source("\"\"\"string\"\"\""); + const std::string expected("string"); + 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("'string'"); + const std::string expected("string"); + 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("'''string'''"); + const std::string expected("string"); + 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_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_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); +// } +// } +// diff --git a/toml/parser.hpp b/toml/parser.hpp index 39c6aeb..d9e7c5c 100644 --- a/toml/parser.hpp +++ b/toml/parser.hpp @@ -8,44 +8,69 @@ namespace toml { -template +namespace detail +{ + +// it is just an inferior vertion of boost/std::optional +template +struct result +{ + result() : ok_(false){} + ~result() = default; + result(const result& rhs) = default; + result(result&& rhs) = default; + result& operator=(const result& rhs) = default; + result& operator=(result&& rhs) = default; + + result(const T& v) : ok_(true), value_(v){} + result(T&& v) : ok_(true), value_(std::move(v)){} + result& operator=(const T& rhs){ok_ = true; value_ = rhs; return *this;} + result& operator=(T&& rhs) {ok_ = true; value_ = rhs; return *this;} + + bool ok() const {return ok_;} + operator bool() const {return ok_;} + + T& get() {if(!ok_) throw std::logic_error("result"); return value_;} + T const& get() const {if(!ok_) throw std::logic_error("result"); return value_;} + T&& move() + {if(!ok_) throw std::logic_error("result"); ok_ = false; return std::move(value_);} + + private: + bool ok_; + T value_; +}; + + +}//detail + struct parse_escape_sequence { - typedef charT value_type; - typedef toml::String string_type; - typedef string_type result_type; - static_assert(std::is_same::value, "char type is different from default String type"); + typedef toml::charactor value_type; + typedef toml::String string_type; + typedef detail::result result_type; - //XXX this changes iterator position! template::value_type, value_type>::value>::type> - static result_type invoke(Iterator& iter) + static std::pair invoke(Iterator iter) { - assert(*iter == '\\'); + if(*iter != '\\') return std::make_pair(result_type{}, iter); ++iter; switch(*iter) { - case '\\': ++iter; return "\\"; - case '"' : ++iter; return "\""; - case 'b' : ++iter; return "\b"; - case 't' : ++iter; return "\t"; - case 'n' : ++iter; return "\n"; - case 'f' : ++iter; return "\f"; - case 'r' : ++iter; return "\r"; + case '\\': return std::make_pair(string_type("\\"), std::next(iter)); + case '"' : return std::make_pair(string_type("\""), std::next(iter)); + case 'b' : return std::make_pair(string_type("\b"), std::next(iter)); + case 't' : return std::make_pair(string_type("\t"), std::next(iter)); + case 'n' : return std::make_pair(string_type("\n"), std::next(iter)); + case 'f' : return std::make_pair(string_type("\f"), std::next(iter)); + case 'r' : return std::make_pair(string_type("\r"), std::next(iter)); case 'u' : - { - string_type tmp(iter+1, iter+5); - std::advance(iter, 5); - return utf8_to_char(make_codepoint(tmp)); - } + return std::make_pair(utf8_to_char(make_codepoint( + string_type(iter+1, iter+5))), iter+5); case 'U': - { - string_type tmp(iter+1, iter+9); - std::advance(iter, 9); - return utf8_to_char(make_codepoint(tmp)); - } + return std::make_pair(utf8_to_char(make_codepoint( + string_type(iter+1, iter+9))), iter+9); default: throw syntax_error("unkwnon escape sequence"); } } @@ -53,14 +78,14 @@ struct parse_escape_sequence static unsigned int make_codepoint(string_type str) { unsigned int codepoint; - std::basic_istringstream iss(str); + std::basic_istringstream iss(str); iss >> std::hex >> codepoint; return codepoint; } - static result_type utf8_to_char(const unsigned int codepoint) + static string_type utf8_to_char(const unsigned int codepoint) { - result_type charactor; + string_type charactor; if(codepoint < 0x80) { charactor += static_cast(codepoint); @@ -87,64 +112,69 @@ struct parse_escape_sequence } }; -template struct parse_basic_inline_string { - typedef charT value_type; - typedef toml::String result_type; - static_assert(std::is_same::value, "char type is different from default String type"); + typedef toml::charactor value_type; + typedef detail::result result_type; template::value_type, value_type>::value>::type> - static result_type invoke(Iterator iter, Iterator end) + static std::pair invoke(Iterator iter) { + const Iterator end = is_basic_inline_string::invoke(iter); + if(iter == end) return std::make_pair(result_type{}, iter); if(std::distance(iter, end) < 2) - throw internal_error("no basic inline string here"); - result_type result; result.reserve(std::distance(iter, end)-2); - ++iter; --end; // ignore '"' - while(iter != end) + throw internal_error("is_basic_inline_string"); + + toml::String result; result.reserve(std::distance(iter, end)-2); + ++iter; + const Iterator last = std::prev(end); // ignore '"' + while(iter != last) { if(*iter == '\\') { - result += parse_escape_sequence::invoke(iter); + auto r = parse_escape_sequence::invoke(iter); + if(!r.first.ok()) throw internal_error("parse_basic_inline_string"); + result += r.first.move(); + iter = r.second; } else { - result.push_back(*iter); + result += *iter; ++iter; } } - return result; + return std::make_pair(result, end); } }; -template struct parse_basic_multiline_string { - typedef charT value_type; - typedef toml::String result_type; - static_assert(std::is_same::value, "char type is different from default String type"); + typedef toml::charactor value_type; + typedef toml::String string_type; + typedef detail::result result_type; - typedef is_chain_of, is_newline> + typedef is_chain_of, is_newline> is_line_ending_backslash; - typedef is_repeat_of, is_newline>, + typedef is_repeat_of, is_newline>, repeat_infinite()> ws_nl_after_backslash_remover; template::value_type, value_type>::value>::type> - static result_type invoke(Iterator iter, Iterator end) + static std::pair invoke(Iterator iter) { + const Iterator end = is_basic_multiline_string::invoke(iter); + if(iter == end) return std::make_pair(result_type{}, iter); if(std::distance(iter, end) < 6) - throw internal_error("no basic multiline string here"); - result_type result; result.reserve(std::distance(iter, end)-6); + throw internal_error("is_basic_inline_string"); + + toml::String result; result.reserve(std::distance(iter, end)-6); std::advance(iter, 3); - std::advance(end, -3); - iter = is_newline::invoke(iter); // the first newline will be trimmed - while(iter != end) + const Iterator last = end - 3; + iter = is_newline::invoke(iter); // trim first newline if exists + while(iter != last) { if(*iter == '\\') { @@ -154,7 +184,10 @@ struct parse_basic_multiline_string } else { - result += parse_escape_sequence::invoke(iter); + auto r = parse_escape_sequence::invoke(iter); + if(!r.first.ok()) throw internal_error("parse_basic_inline_string"); + result += r.first.move(); + iter = r.second; } } else @@ -163,731 +196,726 @@ struct parse_basic_multiline_string ++iter; } } - return result; + return std::make_pair(result, end); } }; -template struct parse_literal_inline_string { - typedef charT value_type; - typedef toml::String result_type; - static_assert(std::is_same::value, "char type is different from default String type"); + typedef toml::charactor value_type; + typedef detail::result result_type; template::value_type, value_type>::value>::type> - static result_type invoke(Iterator iter, Iterator end) + static std::pair invoke(Iterator iter) { + const Iterator end = is_literal_inline_string::invoke(iter); + if(iter == end) return std::make_pair(result_type{}, iter); if(std::distance(iter, end) < 2) - throw internal_error("no literal multiline string here"); - result_type result; result.reserve(std::distance(iter, end)-2); - std::advance(iter, 1); - std::advance(end, -1); - while(iter != end) + throw internal_error("is_literal_inline_string"); + + toml::String result; result.reserve(std::distance(iter, end)-2); + ++iter; + const Iterator last = end - 1; + while(iter != last) { result.push_back(*iter); ++iter; } - return result; + return std::make_pair(result, end); } }; -template struct parse_literal_multiline_string { - typedef charT value_type; - typedef toml::String result_type; - static_assert(std::is_same::value, "char type is different from default String type"); + typedef toml::charactor value_type; + typedef detail::result result_type; - typedef is_chain_of, is_newline> + typedef is_chain_of, is_newline> is_line_ending_backslash; - typedef is_repeat_of, is_newline>, + typedef is_repeat_of, is_newline>, repeat_infinite()> ws_nl_after_backslash_remover; template::value_type, value_type>::value>::type> - static result_type invoke(Iterator iter, Iterator end) + static std::pair invoke(Iterator iter) { + const Iterator end = is_literal_multiline_string::invoke(iter); + if(iter == end) return std::make_pair(result_type{}, iter); if(std::distance(iter, end) < 6) - throw internal_error("no literal multiline string here"); - result_type result; result.reserve(std::distance(iter, end)-6); + throw internal_error("is_literal_multiline_string"); + + toml::String result; result.reserve(std::distance(iter, end)-6); std::advance(iter, 3); - std::advance(end, -3); - iter = is_newline::invoke(iter); // the first newline will be trimmed - while(iter != end) + const Iterator last = end - 3; + iter = is_newline::invoke(iter); // trim first newline if exist + while(iter != last) { result.push_back(*iter); ++iter; } - return result; + return std::make_pair(result, end); } }; -template struct parse_string { - typedef charT value_type; - typedef toml::String result_type; - static_assert(std::is_same::value, "char type is different from default String type"); + typedef toml::charactor value_type; + typedef detail::result result_type; template::value_type, value_type>::value>::type> - static result_type invoke(Iterator iter, Iterator end) + static std::pair invoke(Iterator iter) { - Iterator tmp = is_basic_inline_string::invoke(iter); - if(iter != tmp) - return parse_basic_inline_string::invoke(iter, tmp); - tmp = is_basic_multiline_string::invoke(iter); - if(iter != tmp) - return parse_basic_multiline_string::invoke(iter, tmp); - tmp = is_literal_inline_string::invoke(iter); - if(iter != tmp) - return parse_literal_inline_string::invoke(iter, tmp); - tmp = is_literal_multiline_string::invoke(iter); - if(iter != tmp) - return parse_literal_multiline_string::invoke(iter, tmp); - throw internal_error("no string here"); - } -}; - - -template -struct parse_integer -{ - typedef charT value_type; - typedef std::basic_string string_type; - typedef toml::Integer result_type; - - template::value_type, - value_type>::value>::type> - static result_type invoke(Iterator iter, Iterator end) - { - string_type result; result.resize(std::distance(iter, end)); - std::copy_if(iter, end, result.begin(), [](charT c){return c != '_';}); - return std::stoi(result); - } -}; - -template -struct parse_float -{ - typedef charT value_type; - typedef std::basic_string string_type; - typedef toml::Float result_type; - - template::value_type, - value_type>::value>::type> - static result_type invoke(Iterator iter, Iterator end) - { - string_type result; result.resize(std::distance(iter, end)); - std::copy_if(iter, end, result.begin(), [](charT c){return c != '_';}); - return std::stod(result); - } -}; - -template -struct parse_boolean -{ - typedef charT value_type; - typedef toml::Boolean result_type; - - template::value_type, - value_type>::value>::type> - static result_type invoke(Iterator iter, Iterator end) - { - return (std::distance(iter, end) == 4); - } -}; - -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; - } + std::pair result; + if((result = parse_basic_inline_string::invoke(iter)).first.ok()) + return result; + else if((result = parse_basic_multiline_string::invoke(iter)).first.ok()) + return result; + else if((result = parse_literal_inline_string::invoke(iter)).first.ok()) + return result; + else if((result = parse_literal_multiline_string::invoke(iter)).first.ok()) + return result; 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); + return std::make_pair(result_type{}, iter); } }; -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; - } -}; - -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); - } - -}; +// +// template +// struct parse_integer +// { +// typedef charT value_type; +// typedef std::basic_string string_type; +// typedef toml::Integer result_type; +// +// template::value_type, +// value_type>::value>::type> +// static result_type invoke(Iterator iter, Iterator end) +// { +// string_type result; result.resize(std::distance(iter, end)); +// std::copy_if(iter, end, result.begin(), [](charT c){return c != '_';}); +// return std::stoi(result); +// } +// }; +// +// template +// struct parse_float +// { +// typedef charT value_type; +// typedef std::basic_string string_type; +// typedef toml::Float result_type; +// +// template::value_type, +// value_type>::value>::type> +// static result_type invoke(Iterator iter, Iterator end) +// { +// string_type result; result.resize(std::distance(iter, end)); +// std::copy_if(iter, end, result.begin(), [](charT c){return c != '_';}); +// return std::stod(result); +// } +// }; +// +// template +// struct parse_boolean +// { +// typedef charT value_type; +// typedef toml::Boolean result_type; +// +// template::value_type, +// value_type>::value>::type> +// static result_type invoke(Iterator iter, Iterator end) +// { +// return (std::distance(iter, end) == 4); +// } +// }; +// +// 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; +// } +// }; +// +// 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); +// } +// +// }; }// toml #endif// TOML11_PARSER