mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-09-18 02:08:09 +08:00
perf: do not use concat_string if it is not needed
At the earlier stage of the development, I thought that it is useful if lexer-combinators generate error messages, because by doing this, parser would not need to generate an error message. But now it turned out that to show an appropriate error message, parser need to generate according to the context. And almost all the messages from lexer are discarded. So I added another parameter to lexer-combinator to suppress error message generation. In the future, we may want to remove messages completely from lexers, but currently I will keep it. Removing those unused message generation makes the parsing process faster.
This commit is contained in:
@@ -56,7 +56,8 @@ struct character
|
|||||||
static constexpr char target = C;
|
static constexpr char target = C;
|
||||||
|
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
@@ -67,8 +68,12 @@ struct character
|
|||||||
const char c = *(loc.iter());
|
const char c = *(loc.iter());
|
||||||
if(c != target)
|
if(c != target)
|
||||||
{
|
{
|
||||||
return err(concat_to_string("expected '", show_char(target),
|
if(msg)
|
||||||
"' but got '", show_char(c), "'."));
|
{
|
||||||
|
return err(concat_to_string("expected '", show_char(target),
|
||||||
|
"' but got '", show_char(c), "'."));
|
||||||
|
}
|
||||||
|
return err("");
|
||||||
}
|
}
|
||||||
loc.advance(); // update location
|
loc.advance(); // update location
|
||||||
|
|
||||||
@@ -91,7 +96,8 @@ struct in_range
|
|||||||
static constexpr char lower = Low;
|
static constexpr char lower = Low;
|
||||||
|
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
@@ -102,9 +108,13 @@ struct in_range
|
|||||||
const char c = *(loc.iter());
|
const char c = *(loc.iter());
|
||||||
if(c < lower || upper < c)
|
if(c < lower || upper < c)
|
||||||
{
|
{
|
||||||
return err(concat_to_string("expected character in range "
|
if(msg)
|
||||||
"[", show_char(lower), ", ", show_char(upper), "] but got ",
|
{
|
||||||
"'", show_char(c), "'."));
|
return err(concat_to_string("expected character in range "
|
||||||
|
"[", show_char(lower), ", ", show_char(upper), "] but got ",
|
||||||
|
"'", show_char(c), "'."));
|
||||||
|
}
|
||||||
|
return err("");
|
||||||
}
|
}
|
||||||
|
|
||||||
loc.advance();
|
loc.advance();
|
||||||
@@ -125,7 +135,8 @@ template<typename Combinator>
|
|||||||
struct exclude
|
struct exclude
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
@@ -133,13 +144,16 @@ struct exclude
|
|||||||
if(loc.iter() == loc.end()) {return err("not sufficient characters");}
|
if(loc.iter() == loc.end()) {return err("not sufficient characters");}
|
||||||
auto first = loc.iter();
|
auto first = loc.iter();
|
||||||
|
|
||||||
auto rslt = Combinator::invoke(loc);
|
auto rslt = Combinator::invoke(loc, msg);
|
||||||
if(rslt.is_ok())
|
if(rslt.is_ok())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
return err(concat_to_string(
|
if(msg)
|
||||||
"invalid pattern (", Combinator::pattern(), ") appeared ",
|
{
|
||||||
rslt.unwrap().str()));
|
return err(concat_to_string("invalid pattern (",
|
||||||
|
Combinator::pattern(), ") appeared ", rslt.unwrap().str()));
|
||||||
|
}
|
||||||
|
return err("");
|
||||||
}
|
}
|
||||||
loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but...
|
loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but...
|
||||||
return ok(region<Cont>(loc, first, loc.iter()));
|
return ok(region<Cont>(loc, first, loc.iter()));
|
||||||
@@ -156,12 +170,13 @@ template<typename Combinator>
|
|||||||
struct maybe
|
struct maybe
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
const auto rslt = Combinator::invoke(loc);
|
const auto rslt = Combinator::invoke(loc, msg);
|
||||||
if(rslt.is_ok())
|
if(rslt.is_ok())
|
||||||
{
|
{
|
||||||
return rslt;
|
return rslt;
|
||||||
@@ -182,34 +197,36 @@ template<typename Head, typename ... Tail>
|
|||||||
struct sequence<Head, Tail...>
|
struct sequence<Head, Tail...>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc, msg);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
return err(rslt.unwrap_err());
|
return err(rslt.unwrap_err());
|
||||||
}
|
}
|
||||||
return sequence<Tail...>::invoke(loc, std::move(rslt.unwrap()), first);
|
return sequence<Tail...>::invoke(loc, std::move(rslt.unwrap()), first, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// called from the above function only, recursively.
|
// called from the above function only, recursively.
|
||||||
template<typename Cont, typename Iterator>
|
template<typename Cont, typename Iterator>
|
||||||
static result<region<Cont>, std::string>
|
static result<region<Cont>, std::string>
|
||||||
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
|
invoke(location<Cont>& loc, region<Cont> reg, Iterator first,
|
||||||
|
const bool msg = false)
|
||||||
{
|
{
|
||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc, msg);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
return err(rslt.unwrap_err());
|
return err(rslt.unwrap_err());
|
||||||
}
|
}
|
||||||
reg += rslt.unwrap(); // concat regions
|
reg += rslt.unwrap(); // concat regions
|
||||||
return sequence<Tail...>::invoke(loc, std::move(reg), first);
|
return sequence<Tail...>::invoke(loc, std::move(reg), first, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string pattern()
|
static std::string pattern()
|
||||||
@@ -224,9 +241,10 @@ struct sequence<Head>
|
|||||||
// would be called from sequence<T ...>::invoke only.
|
// would be called from sequence<T ...>::invoke only.
|
||||||
template<typename Cont, typename Iterator>
|
template<typename Cont, typename Iterator>
|
||||||
static result<region<Cont>, std::string>
|
static result<region<Cont>, std::string>
|
||||||
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
|
invoke(location<Cont>& loc, region<Cont> reg, Iterator first,
|
||||||
|
const bool msg = false)
|
||||||
{
|
{
|
||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc, msg);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
@@ -245,14 +263,15 @@ template<typename Head, typename ... Tail>
|
|||||||
struct either<Head, Tail...>
|
struct either<Head, Tail...>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
|
|
||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc, msg);
|
||||||
if(rslt.is_ok()) {return rslt;}
|
if(rslt.is_ok()) {return rslt;}
|
||||||
return either<Tail...>::invoke(loc);
|
return either<Tail...>::invoke(loc, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string pattern()
|
static std::string pattern()
|
||||||
@@ -264,11 +283,12 @@ template<typename Head>
|
|||||||
struct either<Head>
|
struct either<Head>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
||||||
"internal error: container::value_type should be `char`.");
|
"internal error: container::value_type should be `char`.");
|
||||||
return Head::invoke(loc);
|
return Head::invoke(loc, msg);
|
||||||
}
|
}
|
||||||
static std::string pattern()
|
static std::string pattern()
|
||||||
{
|
{
|
||||||
@@ -287,13 +307,14 @@ template<typename T, std::size_t N>
|
|||||||
struct repeat<T, exactly<N>>
|
struct repeat<T, exactly<N>>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
region<Cont> retval(loc);
|
region<Cont> retval(loc);
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
for(std::size_t i=0; i<N; ++i)
|
for(std::size_t i=0; i<N; ++i)
|
||||||
{
|
{
|
||||||
auto rslt = T::invoke(loc);
|
auto rslt = T::invoke(loc, msg);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
@@ -313,14 +334,15 @@ template<typename T, std::size_t N>
|
|||||||
struct repeat<T, at_least<N>>
|
struct repeat<T, at_least<N>>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
region<Cont> retval(loc);
|
region<Cont> retval(loc);
|
||||||
|
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
for(std::size_t i=0; i<N; ++i)
|
for(std::size_t i=0; i<N; ++i)
|
||||||
{
|
{
|
||||||
auto rslt = T::invoke(loc);
|
auto rslt = T::invoke(loc, msg);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
loc.reset(first);
|
loc.reset(first);
|
||||||
@@ -330,7 +352,7 @@ struct repeat<T, at_least<N>>
|
|||||||
}
|
}
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
auto rslt = T::invoke(loc);
|
auto rslt = T::invoke(loc, msg);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
return ok(std::move(retval));
|
return ok(std::move(retval));
|
||||||
@@ -348,12 +370,13 @@ template<typename T>
|
|||||||
struct repeat<T, unlimited>
|
struct repeat<T, unlimited>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
template<typename Cont>
|
||||||
static result<region<Cont>, std::string> invoke(location<Cont>& loc)
|
static result<region<Cont>, std::string>
|
||||||
|
invoke(location<Cont>& loc, const bool msg = false)
|
||||||
{
|
{
|
||||||
region<Cont> retval(loc);
|
region<Cont> retval(loc);
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
auto rslt = T::invoke(loc);
|
auto rslt = T::invoke(loc, msg);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
{
|
{
|
||||||
return ok(std::move(retval));
|
return ok(std::move(retval));
|
||||||
|
Reference in New Issue
Block a user