mirror of
https://github.com/ToruNiina/toml11.git
synced 2024-11-15 00:51:04 +00:00
Merge pull request #36 from ToruNiina/refactor-format-underline
refactor: remove redundant function overload
This commit is contained in:
commit
4c7dc17b78
@ -28,6 +28,7 @@ set(TEST_NAMES
|
||||
test_serialize_file
|
||||
test_parse_unicode
|
||||
test_error_detection
|
||||
test_format_error
|
||||
)
|
||||
|
||||
CHECK_CXX_COMPILER_FLAG("-Wall" COMPILER_SUPPORTS_WALL)
|
||||
|
75
tests/test_format_error.cpp
Normal file
75
tests/test_format_error.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
#define BOOST_TEST_MODULE "test_value"
|
||||
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#else
|
||||
#define BOOST_TEST_NO_LIB
|
||||
#include <boost/test/included/unit_test.hpp>
|
||||
#endif
|
||||
#include <toml.hpp>
|
||||
|
||||
// to check it successfully compiles. it does not check the formatted string.
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_1_value)
|
||||
{
|
||||
toml::value val(42);
|
||||
|
||||
{
|
||||
const std::string pretty_error =
|
||||
toml::format_error("[error] test error", val, "this is a value");
|
||||
std::cout << pretty_error << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
const std::string pretty_error =
|
||||
toml::format_error("[error] test error", val, "this is a value",
|
||||
std::vector<std::string>{"this is a hint"});
|
||||
std::cout << pretty_error << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_2_values)
|
||||
{
|
||||
toml::value v1(42);
|
||||
toml::value v2(3.14);
|
||||
{
|
||||
const std::string pretty_error =
|
||||
toml::format_error("[error] test error with two values",
|
||||
v1, "this is the answer",
|
||||
v2, "this is the pi");
|
||||
std::cout << pretty_error << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
const std::string pretty_error =
|
||||
toml::format_error("[error] test error with two values",
|
||||
v1, "this is the answer",
|
||||
v2, "this is the pi",
|
||||
std::vector<std::string>{"hint"});
|
||||
std::cout << pretty_error << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_3_values)
|
||||
{
|
||||
toml::value v1(42);
|
||||
toml::value v2(3.14);
|
||||
toml::value v3("foo");
|
||||
{
|
||||
const std::string pretty_error =
|
||||
toml::format_error("[error] test error with two values",
|
||||
v1, "this is the answer",
|
||||
v2, "this is the pi",
|
||||
v3, "this is a meta-syntactic variable");
|
||||
std::cout << pretty_error << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
const std::string pretty_error =
|
||||
toml::format_error("[error] test error with two values",
|
||||
v1, "this is the answer",
|
||||
v2, "this is the pi",
|
||||
v3, "this is a meta-syntactic variable",
|
||||
std::vector<std::string>{"hint 1", "hint 2"});
|
||||
std::cout << pretty_error << std::endl;
|
||||
}
|
||||
}
|
28
toml/get.hpp
28
toml/get.hpp
@ -210,8 +210,9 @@ T get(const value& v)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[erorr] toml::get specified container size is ", container.size(),
|
||||
" but there are ", ar.size(), " elements in toml array."),
|
||||
detail::get_region(v), "here"));
|
||||
" but there are ", ar.size(), " elements in toml array."), {
|
||||
{std::addressof(detail::get_region(v)), "here"}
|
||||
}));
|
||||
}
|
||||
std::transform(ar.cbegin(), ar.cend(), container.begin(),
|
||||
[](const value& x){return ::toml::get<value_type>(x);});
|
||||
@ -233,7 +234,9 @@ T get(const value& v)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[erorr] toml::get specified std::pair but there are ", ar.size(),
|
||||
" elements in toml array."), detail::get_region(v), "here"));
|
||||
" elements in toml array."), {
|
||||
{std::addressof(detail::get_region(v)), "here"}
|
||||
}));
|
||||
}
|
||||
return std::make_pair(::toml::get<first_type >(ar.at(0)),
|
||||
::toml::get<second_type>(ar.at(1)));
|
||||
@ -264,7 +267,9 @@ T get(const value& v)
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[erorr] toml::get specified std::tuple with ",
|
||||
std::tuple_size<T>::value, "elements, but there are ", ar.size(),
|
||||
" elements in toml array."), detail::get_region(v), "here"));
|
||||
" elements in toml array."), {
|
||||
{std::addressof(detail::get_region(v)), "here"}
|
||||
}));
|
||||
}
|
||||
return detail::get_tuple_impl<T>(ar,
|
||||
detail::make_index_sequence<std::tuple_size<T>::value>{});
|
||||
@ -340,8 +345,9 @@ find(const toml::value& v, const toml::key& ky)
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), detail::get_region(v),
|
||||
"in this table"));
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return ::toml::get<T>(tab.at(ky));
|
||||
}
|
||||
@ -353,8 +359,9 @@ find(toml::value& v, const toml::key& ky)
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), detail::get_region(v),
|
||||
"in this table"));
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return ::toml::get<T>(tab.at(ky));
|
||||
}
|
||||
@ -366,8 +373,9 @@ find(toml::value&& v, const toml::key& ky)
|
||||
if(tab.count(ky) == 0)
|
||||
{
|
||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||
"[error] key \"", ky, "\" not found"), detail::get_region(v),
|
||||
"in this table"));
|
||||
"[error] key \"", ky, "\" not found"), {
|
||||
{std::addressof(detail::get_region(v)), "in this table"}
|
||||
}));
|
||||
}
|
||||
return ::toml::get<T>(std::move(tab[ky]));
|
||||
}
|
||||
|
352
toml/parser.hpp
352
toml/parser.hpp
@ -29,13 +29,13 @@ parse_boolean(location<Container>& loc)
|
||||
else // internal error.
|
||||
{
|
||||
throw toml::internal_error(format_underline(
|
||||
"[error] toml::parse_boolean: internal error", reg,
|
||||
"invalid token"));
|
||||
"[error] toml::parse_boolean: internal error",
|
||||
{{std::addressof(reg), "invalid token"}}));
|
||||
}
|
||||
}
|
||||
loc.iter() = first; //rollback
|
||||
return err(format_underline("[error] toml::parse_boolean: ", loc,
|
||||
"the next token is not a boolean"));
|
||||
return err(format_underline("[error] toml::parse_boolean: ",
|
||||
{{std::addressof(loc), "the next token is not a boolean"}}));
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
@ -57,14 +57,14 @@ parse_binary_integer(location<Container>& loc)
|
||||
{
|
||||
throw toml::internal_error(format_underline(
|
||||
"[error] toml::parse_integer: internal error",
|
||||
token.unwrap(), "invalid token"));
|
||||
{{std::addressof(token.unwrap()), "invalid token"}}));
|
||||
}
|
||||
}
|
||||
return ok(std::make_pair(retval, token.unwrap()));
|
||||
}
|
||||
loc.iter() = first;
|
||||
return err(format_underline("[error] toml::parse_binary_integer:", loc,
|
||||
"the next token is not an integer"));
|
||||
return err(format_underline("[error] toml::parse_binary_integer:",
|
||||
{{std::addressof(loc), "the next token is not an integer"}}));
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
@ -84,8 +84,8 @@ parse_octal_integer(location<Container>& loc)
|
||||
return ok(std::make_pair(retval, token.unwrap()));
|
||||
}
|
||||
loc.iter() = first;
|
||||
return err(format_underline("[error] toml::parse_octal_integer:", loc,
|
||||
"the next token is not an integer"));
|
||||
return err(format_underline("[error] toml::parse_octal_integer:",
|
||||
{{std::addressof(loc), "the next token is not an integer"}}));
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
@ -105,8 +105,8 @@ parse_hexadecimal_integer(location<Container>& loc)
|
||||
return ok(std::make_pair(retval, token.unwrap()));
|
||||
}
|
||||
loc.iter() = first;
|
||||
return err(format_underline("[error] toml::parse_hexadecimal_integer", loc,
|
||||
"the next token is not an integer"));
|
||||
return err(format_underline("[error] toml::parse_hexadecimal_integer",
|
||||
{{std::addressof(loc), "the next token is not an integer"}}));
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
@ -133,8 +133,8 @@ parse_integer(location<Container>& loc)
|
||||
return ok(std::make_pair(retval, token.unwrap()));
|
||||
}
|
||||
loc.iter() = first;
|
||||
return err(format_underline("[error] toml::parse_integer: ", loc,
|
||||
"the next token is not an integer"));
|
||||
return err(format_underline("[error] toml::parse_integer: ",
|
||||
{{std::addressof(loc), "the next token is not an integer"}}));
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
@ -222,8 +222,8 @@ parse_floating(location<Container>& loc)
|
||||
return ok(std::make_pair(v, token.unwrap()));
|
||||
}
|
||||
loc.iter() = first;
|
||||
return err(format_underline("[error] toml::parse_floating: ", loc,
|
||||
"the next token is not a float"));
|
||||
return err(format_underline("[error] toml::parse_floating: ",
|
||||
{{std::addressof(loc), "the next token is not a float"}}));
|
||||
}
|
||||
|
||||
template<typename Container, typename Container2>
|
||||
@ -252,8 +252,9 @@ std::string read_utf8_codepoint(const region<Container>& reg,
|
||||
{
|
||||
std::cerr << format_underline("[warning] "
|
||||
"toml::read_utf8_codepoint: codepoints in the range "
|
||||
"[0xD800, 0xDFFF] are not valid UTF-8.",
|
||||
loc, "not a valid UTF-8 codepoint") << std::endl;
|
||||
"[0xD800, 0xDFFF] are not valid UTF-8.", {{
|
||||
std::addressof(loc), "not a valid UTF-8 codepoint"
|
||||
}}) << std::endl;
|
||||
}
|
||||
assert(codepoint < 0xD800 || 0xDFFF < codepoint);
|
||||
// 1110yyyy 10yxxxxx 10xxxxxx
|
||||
@ -267,8 +268,8 @@ std::string read_utf8_codepoint(const region<Container>& reg,
|
||||
{
|
||||
std::cerr << format_underline("[error] "
|
||||
"toml::read_utf8_codepoint: input codepoint is too large to "
|
||||
"decode as a unicode character.", loc,
|
||||
"should be in [0x00..0x10FFFF]") << std::endl;
|
||||
"decode as a unicode character.", {{std::addressof(loc),
|
||||
"should be in [0x00..0x10FFFF]"}}) << std::endl;
|
||||
}
|
||||
// 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx
|
||||
character += static_cast<unsigned char>(0xF0| codepoint >> 18);
|
||||
@ -280,7 +281,7 @@ std::string read_utf8_codepoint(const region<Container>& reg,
|
||||
{
|
||||
throw std::range_error(format_underline(concat_to_string("[error] "
|
||||
"input codepoint (", str, ") is too large to encode as utf-8."),
|
||||
reg, "should be in [0x00..0x10FFFF]"));
|
||||
{{std::addressof(reg), "should be in [0x00..0x10FFFF]"}}));
|
||||
}
|
||||
return character;
|
||||
}
|
||||
@ -291,8 +292,8 @@ result<std::string, std::string> parse_escape_sequence(location<Container>& loc)
|
||||
const auto first = loc.iter();
|
||||
if(first == loc.end() || *first != '\\')
|
||||
{
|
||||
return err(format_underline("[error]: toml::parse_escape_sequence: ", loc,
|
||||
"the next token is not an escape sequence \"\\\""));
|
||||
return err(format_underline("[error]: toml::parse_escape_sequence: ", {{
|
||||
std::addressof(loc), "the next token is not a backslash \"\\\""}}));
|
||||
}
|
||||
++loc.iter();
|
||||
switch(*loc.iter())
|
||||
@ -314,7 +315,7 @@ result<std::string, std::string> parse_escape_sequence(location<Container>& loc)
|
||||
{
|
||||
return err(format_underline("[error] parse_escape_sequence: "
|
||||
"invalid token found in UTF-8 codepoint uXXXX.",
|
||||
loc, token.unwrap_err()));
|
||||
{{std::addressof(loc), token.unwrap_err()}}));
|
||||
}
|
||||
}
|
||||
case 'U':
|
||||
@ -327,16 +328,16 @@ result<std::string, std::string> parse_escape_sequence(location<Container>& loc)
|
||||
{
|
||||
return err(format_underline("[error] parse_escape_sequence: "
|
||||
"invalid token found in UTF-8 codepoint Uxxxxxxxx",
|
||||
loc, token.unwrap_err()));
|
||||
{{std::addressof(loc), token.unwrap_err()}}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto msg = format_underline("[error] parse_escape_sequence: "
|
||||
"unknown escape sequence appeared.", loc, "escape sequence is one of"
|
||||
" \\, \", b, t, n, f, r, uxxxx, Uxxxxxxxx", {"if you want to write "
|
||||
"backslash as just one backslash, use literal string like:",
|
||||
"regex = '<\\i\\c*\\s*>'"});
|
||||
"unknown escape sequence appeared.", {{std::addressof(loc),
|
||||
"escape sequence is one of \\, \", b, t, n, f, r, uxxxx, Uxxxxxxxx"}},
|
||||
/* Hints = */{"if you want to write backslash as just one backslash, "
|
||||
"use literal string like: regex = '<\\i\\c*\\s*>'"});
|
||||
loc.iter() = first;
|
||||
return err(msg);
|
||||
}
|
||||
@ -359,7 +360,7 @@ parse_ml_basic_string(location<Container>& loc)
|
||||
{
|
||||
throw internal_error(format_underline("[error] "
|
||||
"parse_ml_basic_string: invalid token",
|
||||
inner_loc, "should be \"\"\""));
|
||||
{{std::addressof(inner_loc), "should be \"\"\""}}));
|
||||
}
|
||||
// immediate newline is ignored (if exists)
|
||||
/* discard return value */ lex_newline::invoke(inner_loc);
|
||||
@ -385,7 +386,7 @@ parse_ml_basic_string(location<Container>& loc)
|
||||
{
|
||||
throw internal_error(format_underline("[error] "
|
||||
"parse_ml_basic_string: unexpected end of region",
|
||||
inner_loc, "not sufficient token"));
|
||||
{{std::addressof(inner_loc), "not sufficient token"}}));
|
||||
}
|
||||
delim = lex_ml_basic_string_delim::invoke(inner_loc);
|
||||
}
|
||||
@ -412,7 +413,7 @@ parse_basic_string(location<Container>& loc)
|
||||
if(!quot)
|
||||
{
|
||||
throw internal_error(format_underline("[error] parse_basic_string: "
|
||||
"invalid token", inner_loc, "should be \""));
|
||||
"invalid token", {{std::addressof(inner_loc), "should be \""}}));
|
||||
}
|
||||
|
||||
std::string retval;
|
||||
@ -434,7 +435,7 @@ parse_basic_string(location<Container>& loc)
|
||||
{
|
||||
throw internal_error(format_underline("[error] "
|
||||
"parse_ml_basic_string: unexpected end of region",
|
||||
inner_loc, "not sufficient token"));
|
||||
{{std::addressof(inner_loc), "not sufficient token"}}));
|
||||
}
|
||||
quot = lex_quotation_mark::invoke(inner_loc);
|
||||
}
|
||||
@ -461,7 +462,7 @@ parse_ml_literal_string(location<Container>& loc)
|
||||
{
|
||||
throw internal_error(format_underline("[error] "
|
||||
"parse_ml_literal_string: invalid token",
|
||||
inner_loc, "should be '''"));
|
||||
{{std::addressof(inner_loc), "should be '''"}}));
|
||||
}
|
||||
// immediate newline is ignored (if exists)
|
||||
/* discard return value */ lex_newline::invoke(inner_loc);
|
||||
@ -473,7 +474,7 @@ parse_ml_literal_string(location<Container>& loc)
|
||||
{
|
||||
throw internal_error(format_underline("[error] "
|
||||
"parse_ml_literal_string: invalid token",
|
||||
inner_loc, "should be '''"));
|
||||
{{std::addressof(inner_loc), "should be '''"}}));
|
||||
}
|
||||
return ok(std::make_pair(
|
||||
toml::string(body.unwrap().str(), toml::string_t::literal),
|
||||
@ -500,7 +501,7 @@ parse_literal_string(location<Container>& loc)
|
||||
{
|
||||
throw internal_error(format_underline("[error] "
|
||||
"parse_literal_string: invalid token",
|
||||
inner_loc, "should be '"));
|
||||
{{std::addressof(inner_loc), "should be '"}}));
|
||||
}
|
||||
|
||||
const auto body = repeat<lex_literal_char, unlimited>::invoke(inner_loc);
|
||||
@ -510,7 +511,7 @@ parse_literal_string(location<Container>& loc)
|
||||
{
|
||||
throw internal_error(format_underline("[error] "
|
||||
"parse_literal_string: invalid token",
|
||||
inner_loc, "should be '"));
|
||||
{{std::addressof(inner_loc), "should be '"}}));
|
||||
}
|
||||
return ok(std::make_pair(
|
||||
toml::string(body.unwrap().str(), toml::string_t::literal),
|
||||
@ -531,8 +532,8 @@ parse_string(location<Container>& loc)
|
||||
if(const auto rslt = parse_ml_literal_string(loc)) {return rslt;}
|
||||
if(const auto rslt = parse_basic_string(loc)) {return rslt;}
|
||||
if(const auto rslt = parse_literal_string(loc)) {return rslt;}
|
||||
return err(format_underline("[error] toml::parse_string: ", loc,
|
||||
"the next token is not a string"));
|
||||
return err(format_underline("[error] toml::parse_string: ",
|
||||
{{std::addressof(loc), "the next token is not a string"}}));
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
@ -547,21 +548,23 @@ parse_local_date(location<Container>& loc)
|
||||
const auto y = lex_date_fullyear::invoke(inner_loc);
|
||||
if(!y || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != '-')
|
||||
{
|
||||
const std::string msg = y.map_err_or_else(
|
||||
[](const std::string& msg) {return msg;}, "should be `-`");
|
||||
|
||||
throw internal_error(format_underline("[error]: "
|
||||
"toml::parse_inner_local_date: invalid year format",
|
||||
inner_loc, y.map_err_or_else([](const std::string& msg) {
|
||||
return msg;
|
||||
}, "should be `-`")));
|
||||
{{std::addressof(inner_loc), msg}}));
|
||||
}
|
||||
++inner_loc.iter();
|
||||
const auto m = lex_date_month::invoke(inner_loc);
|
||||
if(!m || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != '-')
|
||||
{
|
||||
const std::string msg = m.map_err_or_else(
|
||||
[](const std::string& msg) {return msg;}, "should be `-`");
|
||||
|
||||
throw internal_error(format_underline("[error]: "
|
||||
"toml::parse_local_date: invalid month format",
|
||||
inner_loc, m.map_err_or_else([](const std::string& msg) {
|
||||
return msg;
|
||||
}, "should be `-`")));
|
||||
{{std::addressof(inner_loc), msg}}));
|
||||
}
|
||||
++inner_loc.iter();
|
||||
const auto d = lex_date_mday::invoke(inner_loc);
|
||||
@ -569,7 +572,7 @@ parse_local_date(location<Container>& loc)
|
||||
{
|
||||
throw internal_error(format_underline("[error]: "
|
||||
"toml::parse_local_date: invalid day format",
|
||||
inner_loc, d.unwrap_err()));
|
||||
{{std::addressof(inner_loc), d.unwrap_err()}}));
|
||||
}
|
||||
return ok(std::make_pair(local_date(
|
||||
static_cast<std::int16_t>(from_string<int>(y.unwrap().str(), 0)),
|
||||
@ -581,8 +584,8 @@ parse_local_date(location<Container>& loc)
|
||||
else
|
||||
{
|
||||
loc.iter() = first;
|
||||
return err(format_underline("[error]: toml::parse_local_date: ", loc,
|
||||
"the next token is not a local_date"));
|
||||
return err(format_underline("[error]: toml::parse_local_date: ",
|
||||
{{std::addressof(loc), "the next token is not a local_date"}}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -598,21 +601,23 @@ parse_local_time(location<Container>& loc)
|
||||
const auto h = lex_time_hour::invoke(inner_loc);
|
||||
if(!h || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != ':')
|
||||
{
|
||||
const std::string msg = h.map_err_or_else(
|
||||
[](const std::string& msg) {return msg;}, "should be `:`");
|
||||
|
||||
throw internal_error(format_underline("[error]: "
|
||||
"toml::parse_local_time: invalid year format",
|
||||
inner_loc, h.map_err_or_else([](const std::string& msg) {
|
||||
return msg;
|
||||
}, "should be `:`")));
|
||||
{{std::addressof(inner_loc), msg}}));
|
||||
}
|
||||
++inner_loc.iter();
|
||||
const auto m = lex_time_minute::invoke(inner_loc);
|
||||
if(!m || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != ':')
|
||||
{
|
||||
const std::string msg = m.map_err_or_else(
|
||||
[](const std::string& msg) {return msg;}, "should be `:`");
|
||||
|
||||
throw internal_error(format_underline("[error]: "
|
||||
"toml::parse_local_time: invalid month format",
|
||||
inner_loc, m.map_err_or_else([](const std::string& msg) {
|
||||
return msg;
|
||||
}, "should be `:`")));
|
||||
{{std::addressof(inner_loc), msg}}));
|
||||
}
|
||||
++inner_loc.iter();
|
||||
const auto s = lex_time_second::invoke(inner_loc);
|
||||
@ -620,7 +625,7 @@ parse_local_time(location<Container>& loc)
|
||||
{
|
||||
throw internal_error(format_underline("[error]: "
|
||||
"toml::parse_local_time: invalid second format",
|
||||
inner_loc, s.unwrap_err()));
|
||||
{{std::addressof(inner_loc), s.unwrap_err()}}));
|
||||
}
|
||||
local_time time(
|
||||
static_cast<std::int8_t>(from_string<int>(h.unwrap().str(), 0)),
|
||||
@ -656,7 +661,7 @@ parse_local_time(location<Container>& loc)
|
||||
{
|
||||
throw internal_error(format_underline("[error]: "
|
||||
"toml::parse_local_time: invalid subsecond format",
|
||||
inner_loc, secfrac.unwrap_err()));
|
||||
{{std::addressof(inner_loc), secfrac.unwrap_err()}}));
|
||||
}
|
||||
}
|
||||
return ok(std::make_pair(time, token.unwrap()));
|
||||
@ -664,8 +669,8 @@ parse_local_time(location<Container>& loc)
|
||||
else
|
||||
{
|
||||
loc.iter() = first;
|
||||
return err(format_underline("[error]: toml::parse_local_time: ", loc,
|
||||
"the next token is not a local_time"));
|
||||
return err(format_underline("[error]: toml::parse_local_time: ",
|
||||
{{std::addressof(loc), "the next token is not a local_time"}}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -680,25 +685,26 @@ parse_local_datetime(location<Container>& loc)
|
||||
const auto date = parse_local_date(inner_loc);
|
||||
if(!date || inner_loc.iter() == inner_loc.end())
|
||||
{
|
||||
const std::string msg = date.map_err_or_else(
|
||||
[](const std::string& msg) {return msg;}, "date, not datetime");
|
||||
|
||||
throw internal_error(format_underline("[error]: "
|
||||
"toml::parse_local_datetime: invalid datetime format",
|
||||
inner_loc, date.map_err_or_else([](const std::string& msg){
|
||||
return msg;
|
||||
}, "date, not datetime")));
|
||||
{{std::addressof(inner_loc), msg}}));
|
||||
}
|
||||
const char delim = *(inner_loc.iter()++);
|
||||
if(delim != 'T' && delim != 't' && delim != ' ')
|
||||
{
|
||||
throw internal_error(format_underline("[error]: "
|
||||
"toml::parse_local_datetime: invalid datetime format",
|
||||
inner_loc, "should be `T` or ` ` (space)"));
|
||||
{{std::addressof(inner_loc), "should be `T` or ` ` (space)"}}));
|
||||
}
|
||||
const auto time = parse_local_time(inner_loc);
|
||||
if(!time)
|
||||
{
|
||||
throw internal_error(format_underline("[error]: "
|
||||
"toml::parse_local_datetime: invalid datetime format",
|
||||
inner_loc, "invalid time fomrat"));
|
||||
{{std::addressof(inner_loc), "invalid time fomrat"}}));
|
||||
}
|
||||
return ok(std::make_pair(
|
||||
local_datetime(date.unwrap().first, time.unwrap().first),
|
||||
@ -707,8 +713,8 @@ parse_local_datetime(location<Container>& loc)
|
||||
else
|
||||
{
|
||||
loc.iter() = first;
|
||||
return err(format_underline("[error]: toml::parse_local_datetime: ", loc,
|
||||
"the next token is not a local_datetime"));
|
||||
return err(format_underline("[error]: toml::parse_local_datetime: ",
|
||||
{{std::addressof(loc), "the next token is not a local_datetime"}}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -723,11 +729,12 @@ parse_offset_datetime(location<Container>& loc)
|
||||
const auto datetime = parse_local_datetime(inner_loc);
|
||||
if(!datetime || inner_loc.iter() == inner_loc.end())
|
||||
{
|
||||
const std::string msg = datetime.map_err_or_else(
|
||||
[](const std::string& msg){return msg;}, "date, not datetime");
|
||||
|
||||
throw internal_error(format_underline("[error]: "
|
||||
"toml::parse_offset_datetime: invalid datetime format",
|
||||
inner_loc, datetime.map_err_or_else([](const std::string& msg){
|
||||
return msg;
|
||||
}, "date, not datetime")));
|
||||
{{std::addressof(inner_loc), msg}}));
|
||||
}
|
||||
time_offset offset(0, 0);
|
||||
if(const auto ofs = lex_time_numoffset::invoke(inner_loc))
|
||||
@ -748,7 +755,7 @@ parse_offset_datetime(location<Container>& loc)
|
||||
{
|
||||
throw internal_error(format_underline("[error]: "
|
||||
"toml::parse_offset_datetime: invalid datetime format",
|
||||
inner_loc, "should be `Z` or `+HH:MM`"));
|
||||
{{std::addressof(inner_loc), "should be `Z` or `+HH:MM`"}}));
|
||||
}
|
||||
return ok(std::make_pair(offset_datetime(datetime.unwrap().first, offset),
|
||||
token.unwrap()));
|
||||
@ -756,8 +763,8 @@ parse_offset_datetime(location<Container>& loc)
|
||||
else
|
||||
{
|
||||
loc.iter() = first;
|
||||
return err(format_underline("[error]: toml::parse_offset_datetime: ", loc,
|
||||
"the next token is not a local_datetime"));
|
||||
return err(format_underline("[error]: toml::parse_offset_datetime: ",
|
||||
{{std::addressof(loc), "the next token is not a local_datetime"}}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -778,8 +785,8 @@ parse_simple_key(location<Container>& loc)
|
||||
const auto reg = bare.unwrap();
|
||||
return ok(std::make_pair(reg.str(), reg));
|
||||
}
|
||||
return err(format_underline("[error] toml::parse_simple_key: ", loc,
|
||||
"the next token is not a simple key"));
|
||||
return err(format_underline("[error] toml::parse_simple_key: ",
|
||||
{{std::addressof(loc), "the next token is not a simple key"}}));
|
||||
}
|
||||
|
||||
// dotted key become vector of keys
|
||||
@ -806,7 +813,7 @@ parse_key(location<Container>& loc)
|
||||
{
|
||||
throw internal_error(format_underline("[error] "
|
||||
"toml::detail::parse_key: dotted key contains invalid key",
|
||||
inner_loc, k.unwrap_err()));
|
||||
{{std::addressof(inner_loc), k.unwrap_err()}}));
|
||||
}
|
||||
|
||||
lex_ws::invoke(inner_loc);
|
||||
@ -821,8 +828,8 @@ parse_key(location<Container>& loc)
|
||||
else
|
||||
{
|
||||
throw internal_error(format_underline("[error] toml::parse_key: "
|
||||
"dotted key contains invalid key ", inner_loc,
|
||||
"should be `.`"));
|
||||
"dotted key contains invalid key ",
|
||||
{{std::addressof(inner_loc), "should be `.`"}}));
|
||||
}
|
||||
}
|
||||
return ok(std::make_pair(keys, reg));
|
||||
@ -835,7 +842,8 @@ parse_key(location<Container>& loc)
|
||||
return ok(std::make_pair(std::vector<key>(1, smpl.unwrap().first),
|
||||
smpl.unwrap().second));
|
||||
}
|
||||
return err(format_underline("[error] toml::parse_key: ", loc, "is not a valid key"));
|
||||
return err(format_underline("[error] toml::parse_key: ",
|
||||
{{std::addressof(loc), "is not a valid key"}}));
|
||||
}
|
||||
|
||||
// forward-decl to implement parse_array and parse_table
|
||||
@ -880,22 +888,16 @@ parse_array(location<Container>& loc)
|
||||
array_start_loc.iter() = first;
|
||||
|
||||
throw syntax_error(format_underline("[error] toml::parse_array: "
|
||||
"type of elements should be the same each other.",
|
||||
std::vector<std::pair<region_base const*, std::string>>{
|
||||
std::make_pair(
|
||||
std::addressof(array_start_loc),
|
||||
std::string("array starts here")
|
||||
),
|
||||
std::make_pair(
|
||||
"type of elements should be the same each other.", {
|
||||
{std::addressof(array_start_loc), "array starts here"},
|
||||
{
|
||||
std::addressof(get_region(retval.front())),
|
||||
std::string("value has type ") +
|
||||
stringize(retval.front().type())
|
||||
),
|
||||
std::make_pair(
|
||||
"value has type " + stringize(retval.front().type())
|
||||
},
|
||||
{
|
||||
std::addressof(get_region(val.unwrap())),
|
||||
std::string("value has different type, ") +
|
||||
stringize(val.unwrap().type())
|
||||
)
|
||||
"value has different type, " + stringize(val.unwrap().type())
|
||||
}
|
||||
}));
|
||||
}
|
||||
retval.push_back(std::move(val.unwrap()));
|
||||
@ -906,9 +908,10 @@ parse_array(location<Container>& loc)
|
||||
array_start_loc.iter() = first;
|
||||
|
||||
throw syntax_error(format_underline("[error] toml::parse_array: "
|
||||
"value having invalid format appeared in an array",
|
||||
array_start_loc, "array starts here",
|
||||
loc, "it is not a valid value."));
|
||||
"value having invalid format appeared in an array", {
|
||||
{std::addressof(array_start_loc), "array starts here"},
|
||||
{std::addressof(loc), "it is not a valid value."}
|
||||
}));
|
||||
}
|
||||
|
||||
using lex_array_separator = sequence<maybe<lex_ws>, character<','>>;
|
||||
@ -928,14 +931,17 @@ parse_array(location<Container>& loc)
|
||||
array_start_loc.iter() = first;
|
||||
|
||||
throw syntax_error(format_underline("[error] toml::parse_array:"
|
||||
" missing array separator `,` after a value",
|
||||
array_start_loc, "array starts here", loc, "should be `,`"));
|
||||
" missing array separator `,` after a value", {
|
||||
{std::addressof(array_start_loc), "array starts here"},
|
||||
{std::addressof(loc), "should be `,`"}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
loc.iter() = first;
|
||||
throw syntax_error(format_underline("[error] toml::parse_array: "
|
||||
"array did not closed by `]`", loc, "should be closed"));
|
||||
"array did not closed by `]`",
|
||||
{{std::addressof(loc), "should be closed"}}));
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
@ -953,7 +959,8 @@ parse_key_value_pair(location<Container>& loc)
|
||||
{
|
||||
loc.iter() = first;
|
||||
msg = format_underline("[error] toml::parse_key_value_pair: "
|
||||
"empty key is not allowed.", loc, "key expected before '='");
|
||||
"empty key is not allowed.",
|
||||
{{std::addressof(loc), "key expected before '='"}});
|
||||
}
|
||||
return err(std::move(msg));
|
||||
}
|
||||
@ -968,14 +975,16 @@ parse_key_value_pair(location<Container>& loc)
|
||||
if(std::find(loc.iter(), line_end, '=') != line_end)
|
||||
{
|
||||
msg = format_underline("[error] toml::parse_key_value_pair: "
|
||||
"invalid format for key", loc, "invalid character in key", {
|
||||
"Did you forget '.' to separate dotted-key?",
|
||||
"invalid format for key",
|
||||
{{std::addressof(loc), "invalid character in key"}},
|
||||
{"Did you forget '.' to separate dotted-key?",
|
||||
"Allowed characters for bare key are [0-9a-zA-Z_-]."});
|
||||
}
|
||||
else // if not, the error is lack of key-value separator.
|
||||
{
|
||||
msg = format_underline("[error] toml::parse_key_value_pair: "
|
||||
"missing key-value separator `=`", loc, "should be `=`");
|
||||
"missing key-value separator `=`",
|
||||
{{std::addressof(loc), "should be `=`"}});
|
||||
}
|
||||
loc.iter() = first;
|
||||
return err(std::move(msg));
|
||||
@ -992,8 +1001,8 @@ parse_key_value_pair(location<Container>& loc)
|
||||
{
|
||||
loc.iter() = after_kvsp;
|
||||
msg = format_underline("[error] toml::parse_key_value_pair: "
|
||||
"missing value after key-value separator '='", loc,
|
||||
"expected value, but got nothing");
|
||||
"missing value after key-value separator '='",
|
||||
{{std::addressof(loc), "expected value, but got nothing"}});
|
||||
}
|
||||
else // there is something not a comment/whitespace, so invalid format.
|
||||
{
|
||||
@ -1122,19 +1131,26 @@ insert_nested_key(table& root, const toml::value& v,
|
||||
// show special err msg for conflicting table
|
||||
throw syntax_error(format_underline(concat_to_string(
|
||||
"[error] toml::insert_value: array of table (\"",
|
||||
format_dotted_keys(first, last), "\") cannot insert"
|
||||
"ed"), get_region(tab->at(k)), "table already defined",
|
||||
get_region(v), "this conflicts with the previous table"));
|
||||
format_dotted_keys(first, last),
|
||||
"\") cannot be defined"), {
|
||||
{std::addressof(get_region(tab->at(k))),
|
||||
"table already defined"},
|
||||
{std::addressof(get_region(v)),
|
||||
"this conflicts with the previous table"}
|
||||
}));
|
||||
}
|
||||
else if(!(tab->at(k).is(value_t::Array)))
|
||||
{
|
||||
throw syntax_error(format_underline(concat_to_string(
|
||||
"[error] toml::insert_value: array of table (\"",
|
||||
format_dotted_keys(first, last), "\") collides with"
|
||||
" existing value"), get_region(tab->at(k)),
|
||||
concat_to_string("this ", tab->at(k).type(),
|
||||
" value already exists"), get_region(v),
|
||||
"while inserting this array-of-tables"));
|
||||
" existing value"), {
|
||||
{std::addressof(get_region(tab->at(k))),
|
||||
concat_to_string("this ", tab->at(k).type(),
|
||||
" value already exists")},
|
||||
{std::addressof(get_region(v)),
|
||||
"while inserting this array-of-tables"}
|
||||
}));
|
||||
}
|
||||
array& a = tab->at(k).template cast<toml::value_t::Array>();
|
||||
if(!(a.front().is(value_t::Table)))
|
||||
@ -1142,10 +1158,13 @@ insert_nested_key(table& root, const toml::value& v,
|
||||
throw syntax_error(format_underline(concat_to_string(
|
||||
"[error] toml::insert_value: array of table (\"",
|
||||
format_dotted_keys(first, last), "\") collides with"
|
||||
" existing value"), get_region(tab->at(k)),
|
||||
concat_to_string("this ", tab->at(k).type(),
|
||||
" value already exists"), get_region(v),
|
||||
"while inserting this array-of-tables"));
|
||||
" existing value"), {
|
||||
{std::addressof(get_region(tab->at(k))),
|
||||
concat_to_string("this ", tab->at(k).type(),
|
||||
" value already exists")},
|
||||
{std::addressof(get_region(v)),
|
||||
"while inserting this array-of-tables"}
|
||||
}));
|
||||
}
|
||||
// avoid conflicting array of table like the following.
|
||||
// ```toml
|
||||
@ -1167,10 +1186,13 @@ insert_nested_key(table& root, const toml::value& v,
|
||||
throw syntax_error(format_underline(concat_to_string(
|
||||
"[error] toml::insert_value: array of table (\"",
|
||||
format_dotted_keys(first, last), "\") collides with"
|
||||
" existing array-of-tables"), get_region(tab->at(k)),
|
||||
concat_to_string("this ", tab->at(k).type(),
|
||||
" value has static size"), get_region(v),
|
||||
"appending this to the statically sized array"));
|
||||
" existing array-of-tables"), {
|
||||
{std::addressof(get_region(tab->at(k))),
|
||||
concat_to_string("this ", tab->at(k).type(),
|
||||
" value has static size")},
|
||||
{std::addressof(get_region(v)),
|
||||
"appending it to the statically sized array"}
|
||||
}));
|
||||
}
|
||||
a.push_back(v);
|
||||
return ok(true);
|
||||
@ -1191,11 +1213,14 @@ insert_nested_key(table& root, const toml::value& v,
|
||||
tab->at(k), first, iter, last))
|
||||
{
|
||||
throw syntax_error(format_underline(concat_to_string(
|
||||
"[error] toml::insert_value: table (\"",
|
||||
format_dotted_keys(first, last),
|
||||
"\") already exists."),
|
||||
get_region(tab->at(k)), "table already exists here",
|
||||
get_region(v), "table defined twice"));
|
||||
"[error] toml::insert_value: table (\"",
|
||||
format_dotted_keys(first, last),
|
||||
"\") already exists."), {
|
||||
{std::addressof(get_region(tab->at(k))),
|
||||
"table already exists here"},
|
||||
{std::addressof(get_region(v)),
|
||||
"table defined twice"}
|
||||
}));
|
||||
}
|
||||
// to allow the following toml file.
|
||||
// [a.b.c]
|
||||
@ -1217,18 +1242,23 @@ insert_nested_key(table& root, const toml::value& v,
|
||||
{
|
||||
throw syntax_error(format_underline(concat_to_string(
|
||||
"[error] toml::insert_value: array of tables (\"",
|
||||
format_dotted_keys(first, last), "\") already exists."),
|
||||
get_region(tab->at(k)), "array of tables defined here",
|
||||
get_region(v), "table conflicts with the previous array"
|
||||
" of table"));
|
||||
format_dotted_keys(first, last), "\") already exists."), {
|
||||
{std::addressof(get_region(tab->at(k))),
|
||||
"array of tables defined here"},
|
||||
{std::addressof(get_region(v)),
|
||||
"table conflicts with the previous array of table"}
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw syntax_error(format_underline(concat_to_string(
|
||||
"[error] toml::insert_value: value (\"",
|
||||
format_dotted_keys(first, last), "\") already exists."),
|
||||
get_region(tab->at(k)), "value already exists here",
|
||||
get_region(v), "value defined twice"));
|
||||
format_dotted_keys(first, last), "\") already exists."), {
|
||||
{std::addressof(get_region(tab->at(k))),
|
||||
"value already exists here"},
|
||||
{std::addressof(get_region(v)),
|
||||
"value defined twice"}
|
||||
}));
|
||||
}
|
||||
}
|
||||
tab->insert(std::make_pair(k, v));
|
||||
@ -1260,9 +1290,11 @@ insert_nested_key(table& root, const toml::value& v,
|
||||
throw syntax_error(format_underline(concat_to_string(
|
||||
"[error] toml::insert_value: target (",
|
||||
format_dotted_keys(first, std::next(iter)),
|
||||
") is neither table nor an array of tables"),
|
||||
get_region(a.back()), concat_to_string("actual type is ",
|
||||
a.back().type()), get_region(v), "inserting this"));
|
||||
") is neither table nor an array of tables"), {
|
||||
{std::addressof(get_region(a.back())),
|
||||
concat_to_string("actual type is ", a.back().type())},
|
||||
{std::addressof(get_region(v)), "inserting this"}
|
||||
}));
|
||||
}
|
||||
tab = std::addressof(a.back().template cast<value_t::Table>());
|
||||
}
|
||||
@ -1271,9 +1303,11 @@ insert_nested_key(table& root, const toml::value& v,
|
||||
throw syntax_error(format_underline(concat_to_string(
|
||||
"[error] toml::insert_value: target (",
|
||||
format_dotted_keys(first, std::next(iter)),
|
||||
") is neither table nor an array of tables"),
|
||||
get_region(tab->at(k)), concat_to_string("actual type is ",
|
||||
tab->at(k).type()), get_region(v), "inserting this"));
|
||||
") is neither table nor an array of tables"), {
|
||||
{std::addressof(get_region(tab->at(k))),
|
||||
concat_to_string("actual type is ", tab->at(k).type())},
|
||||
{std::addressof(get_region(v)), "inserting this"}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1288,8 +1322,8 @@ parse_inline_table(location<Container>& loc)
|
||||
table retval;
|
||||
if(!(loc.iter() != loc.end() && *loc.iter() == '{'))
|
||||
{
|
||||
return err(format_underline("[error] toml::parse_inline_table: ", loc,
|
||||
"the next token is not an inline table"));
|
||||
return err(format_underline("[error] toml::parse_inline_table: ",
|
||||
{{std::addressof(loc), "the next token is not an inline table"}}));
|
||||
}
|
||||
++loc.iter();
|
||||
// it starts from "{". it should be formatted as inline-table
|
||||
@ -1335,13 +1369,14 @@ parse_inline_table(location<Container>& loc)
|
||||
{
|
||||
throw syntax_error(format_underline("[error] "
|
||||
"toml:::parse_inline_table: missing table separator `,` ",
|
||||
loc, "should be `,`"));
|
||||
{{std::addressof(loc), "should be `,`"}}));
|
||||
}
|
||||
}
|
||||
}
|
||||
loc.iter() = first;
|
||||
throw syntax_error(format_underline("[error] toml::parse_inline_table: "
|
||||
"inline table did not closed by `}`", loc, "should be closed"));
|
||||
"inline table did not closed by `}`",
|
||||
{{std::addressof(loc), "should be closed"}}));
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
@ -1350,7 +1385,8 @@ result<value, std::string> parse_value(location<Container>& loc)
|
||||
const auto first = loc.iter();
|
||||
if(first == loc.end())
|
||||
{
|
||||
return err(format_underline("[error] toml::parse_value: input is empty", loc, ""));
|
||||
return err(format_underline("[error] toml::parse_value: input is empty",
|
||||
{{std::addressof(loc), ""}}));
|
||||
}
|
||||
if(auto r = parse_string (loc))
|
||||
{return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));}
|
||||
@ -1374,7 +1410,7 @@ result<value, std::string> parse_value(location<Container>& loc)
|
||||
{return ok(value(std::move(r.unwrap().first), std::move(r.unwrap().second)));}
|
||||
|
||||
const auto msg = format_underline("[error] toml::parse_value: "
|
||||
"unknown token appeared", loc, "unknown");
|
||||
"unknown token appeared", {{std::addressof(loc), "unknown"}});
|
||||
loc.iter() = first;
|
||||
return err(msg);
|
||||
}
|
||||
@ -1391,7 +1427,8 @@ parse_table_key(location<Container>& loc)
|
||||
if(!open || inner_loc.iter() == inner_loc.end())
|
||||
{
|
||||
throw internal_error(format_underline("[error] "
|
||||
"toml::parse_table_key: no `[`", inner_loc, "should be `[`"));
|
||||
"toml::parse_table_key: no `[`",
|
||||
{{std::addressof(inner_loc), "should be `[`"}}));
|
||||
}
|
||||
// to skip [ a . b . c ]
|
||||
// ^----------- this whitespace
|
||||
@ -1400,7 +1437,8 @@ parse_table_key(location<Container>& loc)
|
||||
if(!keys)
|
||||
{
|
||||
throw internal_error(format_underline("[error] "
|
||||
"toml::parse_table_key: invalid key", inner_loc, "not key"));
|
||||
"toml::parse_table_key: invalid key",
|
||||
{{std::addressof(inner_loc), "not key"}}));
|
||||
}
|
||||
// to skip [ a . b . c ]
|
||||
// ^-- this whitespace
|
||||
@ -1409,7 +1447,8 @@ parse_table_key(location<Container>& loc)
|
||||
if(!close)
|
||||
{
|
||||
throw internal_error(format_underline("[error] "
|
||||
"toml::parse_table_key: no `]`", inner_loc, "should be `]`"));
|
||||
"toml::parse_table_key: no `]`",
|
||||
{{std::addressof(inner_loc), "should be `]`"}}));
|
||||
}
|
||||
|
||||
// after [table.key], newline or EOF(empty table) requried.
|
||||
@ -1422,7 +1461,7 @@ parse_table_key(location<Container>& loc)
|
||||
{
|
||||
throw syntax_error(format_underline("[error] "
|
||||
"toml::parse_table_key: newline required after [table.key]",
|
||||
loc, "expected newline"));
|
||||
{{std::addressof(loc), "expected newline"}}));
|
||||
}
|
||||
}
|
||||
return ok(std::make_pair(keys.unwrap().first, token.unwrap()));
|
||||
@ -1445,23 +1484,24 @@ parse_array_table_key(location<Container>& loc)
|
||||
if(!open || inner_loc.iter() == inner_loc.end())
|
||||
{
|
||||
throw internal_error(format_underline("[error] "
|
||||
"toml::parse_array_table_key: no `[[`", inner_loc,
|
||||
"should be `[[`"));
|
||||
"toml::parse_array_table_key: no `[[`",
|
||||
{{std::addressof(inner_loc), "should be `[[`"}}));
|
||||
}
|
||||
lex_ws::invoke(inner_loc);
|
||||
const auto keys = parse_key(inner_loc);
|
||||
if(!keys)
|
||||
{
|
||||
throw internal_error(format_underline("[error] "
|
||||
"toml::parse_array_table_key: invalid key", inner_loc,
|
||||
"not key"));
|
||||
"toml::parse_array_table_key: invalid key",
|
||||
{{std::addressof(inner_loc), "not a key"}}));
|
||||
}
|
||||
lex_ws::invoke(inner_loc);
|
||||
const auto close = lex_array_table_close::invoke(inner_loc);
|
||||
if(!close)
|
||||
{
|
||||
throw internal_error(format_underline("[error] "
|
||||
"toml::parse_table_key: no `]]`", inner_loc, "should be `]]`"));
|
||||
"toml::parse_table_key: no `]]`",
|
||||
{{std::addressof(inner_loc), "should be `]]`"}}));
|
||||
}
|
||||
|
||||
// after [[table.key]], newline or EOF(empty table) requried.
|
||||
@ -1472,9 +1512,9 @@ parse_array_table_key(location<Container>& loc)
|
||||
const auto nl = lex_newline_after_table_key::invoke(loc);
|
||||
if(!nl)
|
||||
{
|
||||
throw syntax_error(format_underline("[error] "
|
||||
"toml::parse_array_table_key: newline required after "
|
||||
"[[table.key]]", loc, "expected newline"));
|
||||
throw syntax_error(format_underline("[error] toml::"
|
||||
"parse_array_table_key: newline required after [[table.key]]",
|
||||
{{std::addressof(loc), "expected newline"}}));
|
||||
}
|
||||
}
|
||||
return ok(std::make_pair(keys.unwrap().first, token.unwrap()));
|
||||
@ -1550,8 +1590,8 @@ result<table, std::string> parse_ml_table(location<Container>& loc)
|
||||
const auto before = loc.iter();
|
||||
lex_ws::invoke(loc); // skip whitespace
|
||||
const auto msg = format_underline("[error] toml::parse_table: "
|
||||
"invalid line format", loc, concat_to_string(
|
||||
"expected newline, but got '", show_char(*loc.iter()), "'."));
|
||||
"invalid line format", {{std::addressof(loc), concat_to_string(
|
||||
"expected newline, but got '", show_char(*loc.iter()), "'.")}});
|
||||
loc.iter() = before;
|
||||
return err(msg);
|
||||
}
|
||||
@ -1621,7 +1661,7 @@ result<table, std::string> parse_toml_file(location<Container>& loc)
|
||||
continue;
|
||||
}
|
||||
return err(format_underline("[error]: toml::parse_toml_file: "
|
||||
"unknown line appeared", loc, "unknown format"));
|
||||
"unknown line appeared", {{std::addressof(loc), "unknown format"}}));
|
||||
}
|
||||
return ok(data);
|
||||
}
|
||||
|
149
toml/region.hpp
149
toml/region.hpp
@ -237,149 +237,6 @@ struct region final : public region_base
|
||||
const_iterator first_, last_;
|
||||
};
|
||||
|
||||
// to show a better error message.
|
||||
inline std::string format_underline(const std::string& message,
|
||||
const region_base& reg, const std::string& comment_for_underline,
|
||||
std::vector<std::string> helps = {})
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const auto newline = "\r\n";
|
||||
#else
|
||||
const char newline = '\n';
|
||||
#endif
|
||||
const auto line = reg.line();
|
||||
const auto line_number = reg.line_num();
|
||||
|
||||
std::string retval;
|
||||
retval += message;
|
||||
retval += newline;
|
||||
retval += " --> ";
|
||||
retval += reg.name();
|
||||
retval += newline;
|
||||
retval += ' ';
|
||||
retval += line_number;
|
||||
retval += " | ";
|
||||
retval += line;
|
||||
retval += newline;
|
||||
retval += make_string(line_number.size() + 1, ' ');
|
||||
retval += " | ";
|
||||
retval += make_string(reg.before(), ' ');
|
||||
if(reg.size() == 1)
|
||||
{
|
||||
// invalid
|
||||
// ^------
|
||||
retval += '^';
|
||||
retval += make_string(reg.after(), '-');
|
||||
}
|
||||
else
|
||||
{
|
||||
// invalid
|
||||
// ~~~~~~~
|
||||
retval += make_string(reg.size(), '~');
|
||||
}
|
||||
retval += ' ';
|
||||
retval += comment_for_underline;
|
||||
if(helps.size() != 0)
|
||||
{
|
||||
retval += newline;
|
||||
retval += make_string(line_number.size() + 1, ' ');
|
||||
retval += " | ";
|
||||
for(const auto help : helps)
|
||||
{
|
||||
retval += newline;
|
||||
retval += "Hint: ";
|
||||
retval += help;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
// to show a better error message.
|
||||
inline std::string format_underline(const std::string& message,
|
||||
const region_base& reg1, const std::string& comment_for_underline1,
|
||||
const region_base& reg2, const std::string& comment_for_underline2,
|
||||
std::vector<std::string> helps = {})
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const auto newline = "\r\n";
|
||||
#else
|
||||
const char newline = '\n';
|
||||
#endif
|
||||
const auto line1 = reg1.line();
|
||||
const auto line_number1 = reg1.line_num();
|
||||
const auto line2 = reg2.line();
|
||||
const auto line_number2 = reg2.line_num();
|
||||
const auto line_num_width =
|
||||
std::max(line_number1.size(), line_number2.size());
|
||||
|
||||
std::ostringstream retval;
|
||||
retval << message << newline;
|
||||
retval << " --> " << reg1.name() << newline;
|
||||
// ---------------------------------------
|
||||
retval << ' ' << std::setw(line_num_width) << line_number1;
|
||||
retval << " | " << line1 << newline;
|
||||
retval << make_string(line_num_width + 1, ' ');
|
||||
retval << " | ";
|
||||
retval << make_string(reg1.before(), ' ');
|
||||
if(reg1.size() == 1)
|
||||
{
|
||||
// invalid
|
||||
// ^------
|
||||
retval << '^';
|
||||
retval << make_string(reg1.after(), '-');
|
||||
}
|
||||
else
|
||||
{
|
||||
// invalid
|
||||
// ~~~~~~~
|
||||
retval << make_string(reg1.size(), '~');
|
||||
}
|
||||
retval << ' ';
|
||||
retval << comment_for_underline1 << newline;
|
||||
// ---------------------------------------
|
||||
if(reg2.name() != reg1.name())
|
||||
{
|
||||
retval << " --> " << reg2.name() << newline;
|
||||
}
|
||||
else
|
||||
{
|
||||
retval << " ..." << newline;
|
||||
}
|
||||
retval << ' ' << std::setw(line_num_width) << line_number2;
|
||||
retval << " | " << line2 << newline;
|
||||
retval << make_string(line_num_width + 1, ' ');
|
||||
retval << " | ";
|
||||
retval << make_string(reg2.before(), ' ');
|
||||
if(reg2.size() == 1)
|
||||
{
|
||||
// invalid
|
||||
// ^------
|
||||
retval << '^';
|
||||
retval << make_string(reg2.after(), '-');
|
||||
}
|
||||
else
|
||||
{
|
||||
// invalid
|
||||
// ~~~~~~~
|
||||
retval << make_string(reg2.size(), '~');
|
||||
}
|
||||
retval << ' ';
|
||||
retval << comment_for_underline2;
|
||||
if(helps.size() != 0)
|
||||
{
|
||||
retval << newline;
|
||||
retval << make_string(line_num_width + 1, ' ');
|
||||
retval << " | ";
|
||||
for(const auto help : helps)
|
||||
{
|
||||
retval << newline;
|
||||
retval << "Hint: ";
|
||||
retval << help;
|
||||
}
|
||||
}
|
||||
return retval.str();
|
||||
}
|
||||
|
||||
// to show a better error message.
|
||||
inline std::string format_underline(const std::string& message,
|
||||
std::vector<std::pair<region_base const*, std::string>> reg_com,
|
||||
@ -408,10 +265,11 @@ inline std::string format_underline(const std::string& message,
|
||||
{
|
||||
if(i!=0 && reg_com.at(i-1).first->name() == reg_com.at(i).first->name())
|
||||
{
|
||||
retval << " ..." << newline;
|
||||
retval << newline << " ..." << newline;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i != 0) {retval << newline;}
|
||||
retval << " --> " << reg_com.at(i).first->name() << newline;
|
||||
}
|
||||
|
||||
@ -439,7 +297,7 @@ inline std::string format_underline(const std::string& message,
|
||||
}
|
||||
|
||||
retval << ' ';
|
||||
retval << comment << newline;
|
||||
retval << comment;
|
||||
}
|
||||
|
||||
if(helps.size() != 0)
|
||||
@ -457,7 +315,6 @@ inline std::string format_underline(const std::string& message,
|
||||
return retval.str();
|
||||
}
|
||||
|
||||
|
||||
} // detail
|
||||
} // toml
|
||||
#endif// TOML11_REGION_H
|
||||
|
@ -681,9 +681,11 @@ typename detail::toml_default_type<T>::type& value::cast() &
|
||||
{
|
||||
if(T != this->type_)
|
||||
{
|
||||
throw type_error(format_underline(concat_to_string(
|
||||
"[error] toml::value bad_cast to ", T), *region_info_,
|
||||
concat_to_string("the actual type is ", this->type_)));
|
||||
throw type_error(detail::format_underline(concat_to_string(
|
||||
"[error] toml::value bad_cast to ", T), {
|
||||
{this->region_info_.get(),
|
||||
concat_to_string("the actual type is ", this->type_)}
|
||||
}));
|
||||
}
|
||||
return switch_cast<T>::invoke(*this);
|
||||
}
|
||||
@ -692,9 +694,11 @@ typename detail::toml_default_type<T>::type const& value::cast() const&
|
||||
{
|
||||
if(T != this->type_)
|
||||
{
|
||||
throw type_error(format_underline(concat_to_string(
|
||||
"[error] toml::value bad_cast to ", T), *region_info_,
|
||||
concat_to_string("the actual type is ", this->type_)));
|
||||
throw type_error(detail::format_underline(concat_to_string(
|
||||
"[error] toml::value bad_cast to ", T), {
|
||||
{this->region_info_.get(),
|
||||
concat_to_string("the actual type is ", this->type_)}
|
||||
}));
|
||||
}
|
||||
return switch_cast<T>::invoke(*this);
|
||||
}
|
||||
@ -703,9 +707,11 @@ typename detail::toml_default_type<T>::type&& value::cast() &&
|
||||
{
|
||||
if(T != this->type_)
|
||||
{
|
||||
throw type_error(format_underline(concat_to_string(
|
||||
"[error] toml::value bad_cast to ", T), *region_info_,
|
||||
concat_to_string("the actual type is ", this->type_)));
|
||||
throw type_error(detail::format_underline(concat_to_string(
|
||||
"[error] toml::value bad_cast to ", T), {
|
||||
{this->region_info_.get(),
|
||||
concat_to_string("the actual type is ", this->type_)}
|
||||
}));
|
||||
}
|
||||
return switch_cast<T>::invoke(std::move(*this));
|
||||
}
|
||||
@ -788,22 +794,38 @@ inline bool operator>=(const toml::value& lhs, const toml::value& rhs)
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
inline std::string format_error(const std::string& err_msg,
|
||||
const toml::value& v, const std::string& comment,
|
||||
std::vector<std::string> hints = {})
|
||||
namespace detail
|
||||
{
|
||||
return detail::format_underline(err_msg, detail::get_region(v), comment,
|
||||
std::move(hints));
|
||||
inline std::string format_error_impl(const std::string& err_msg,
|
||||
std::vector<std::pair<region_base const*, std::string>> val,
|
||||
std::vector<std::string> hints)
|
||||
{
|
||||
return format_underline(err_msg, std::move(val), std::move(hints));
|
||||
}
|
||||
inline std::string format_error_impl(const std::string& err_msg,
|
||||
std::vector<std::pair<region_base const*, std::string>> val)
|
||||
{
|
||||
return format_underline(err_msg, std::move(val));
|
||||
}
|
||||
|
||||
inline std::string format_error(const std::string& err_msg,
|
||||
const toml::value& v1, const std::string& comment1,
|
||||
const toml::value& v2, const std::string& comment2,
|
||||
std::vector<std::string> hints = {})
|
||||
template<typename ... Ts>
|
||||
std::string format_error_impl(const std::string& err_msg,
|
||||
std::vector<std::pair<region_base const*, std::string>> val,
|
||||
const toml::value& v, const std::string& comment,
|
||||
Ts&& ... args)
|
||||
{
|
||||
return detail::format_underline(err_msg, detail::get_region(v1), comment1,
|
||||
detail::get_region(v2), comment2,
|
||||
std::move(hints));
|
||||
val.push_back(std::make_pair(std::addressof(get_region(v)), comment));
|
||||
return format_error_impl(err_msg, std::move(val), std::forward<Ts>(args)...);
|
||||
}
|
||||
} // detail
|
||||
|
||||
template<typename ... Ts>
|
||||
std::string format_error(const std::string& err_msg, Ts&& ... args)
|
||||
{
|
||||
std::vector<std::pair<detail::region_base const*, std::string>> val;
|
||||
val.reserve(sizeof...(args) / 2);
|
||||
return detail::format_error_impl(err_msg, std::move(val),
|
||||
std::forward<Ts>(args)...);
|
||||
}
|
||||
|
||||
template<typename Visitor>
|
||||
|
Loading…
Reference in New Issue
Block a user