Skip to content

Commit

Permalink
feat: use detail::none_t instead of char
Browse files Browse the repository at this point in the history
Although the error value from combinators currently does not have any
information, it can have an information because it is a char value. It
is better to use no-information-type explicitly to make it clear that
it does not have any information. So I added none_t in toml::detai and
use it in combinators and parsers as an error value from combinators.
  • Loading branch information
ToruNiina committed May 31, 2019
1 parent 81abb6c commit 717f592
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 25 deletions.
46 changes: 23 additions & 23 deletions toml/combinator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,19 @@ struct character
static constexpr char target = C;

template<typename Cont>
static result<region<Cont>, char>
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");

if(loc.iter() == loc.end()) {return err('\0');}
if(loc.iter() == loc.end()) {return none();}
const auto first = loc.iter();

const char c = *(loc.iter());
if(c != target)
{
return err(c);
return none();
}
loc.advance(); // update location

Expand All @@ -89,19 +89,19 @@ struct in_range
static constexpr char lower = Low;

template<typename Cont>
static result<region<Cont>, char>
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");

if(loc.iter() == loc.end()) {return err('\0');}
if(loc.iter() == loc.end()) {return none();}
const auto first = loc.iter();

const char c = *(loc.iter());
if(c < lower || upper < c)
{
return err(c);
return none();
}

loc.advance();
Expand All @@ -117,20 +117,20 @@ template<typename Combinator>
struct exclude
{
template<typename Cont>
static result<region<Cont>, char>
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
"internal error: container::value_type should be `char`.");

if(loc.iter() == loc.end()) {return err('\0');}
if(loc.iter() == loc.end()) {return none();}
auto first = loc.iter();

auto rslt = Combinator::invoke(loc);
if(rslt.is_ok())
{
loc.reset(first);
return err(*first);
return none();
}
loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but...
return ok(region<Cont>(loc, first, loc.iter()));
Expand All @@ -142,7 +142,7 @@ template<typename Combinator>
struct maybe
{
template<typename Cont>
static result<region<Cont>, char>
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
Expand All @@ -164,7 +164,7 @@ template<typename Head, typename ... Tail>
struct sequence<Head, Tail...>
{
template<typename Cont>
static result<region<Cont>, char>
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
Expand All @@ -175,21 +175,21 @@ struct sequence<Head, Tail...>
if(rslt.is_err())
{
loc.reset(first);
return err(rslt.unwrap_err());
return none();
}
return sequence<Tail...>::invoke(loc, std::move(rslt.unwrap()), first);
}

// called from the above function only, recursively.
template<typename Cont, typename Iterator>
static result<region<Cont>, char>
static result<region<Cont>, none_t>
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
{
const auto rslt = Head::invoke(loc);
if(rslt.is_err())
{
loc.reset(first);
return err(rslt.unwrap_err());
return none();
}
reg += rslt.unwrap(); // concat regions
return sequence<Tail...>::invoke(loc, std::move(reg), first);
Expand All @@ -201,14 +201,14 @@ struct sequence<Head>
{
// would be called from sequence<T ...>::invoke only.
template<typename Cont, typename Iterator>
static result<region<Cont>, char>
static result<region<Cont>, none_t>
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
{
const auto rslt = Head::invoke(loc);
if(rslt.is_err())
{
loc.reset(first);
return err(rslt.unwrap_err());
return none();
}
reg += rslt.unwrap(); // concat regions
return ok(reg);
Expand All @@ -222,7 +222,7 @@ template<typename Head, typename ... Tail>
struct either<Head, Tail...>
{
template<typename Cont>
static result<region<Cont>, char>
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
Expand All @@ -237,7 +237,7 @@ template<typename Head>
struct either<Head>
{
template<typename Cont>
static result<region<Cont>, char>
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
static_assert(std::is_same<char, typename Cont::value_type>::value,
Expand All @@ -257,7 +257,7 @@ template<typename T, std::size_t N>
struct repeat<T, exactly<N>>
{
template<typename Cont>
static result<region<Cont>, char>
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
region<Cont> retval(loc);
Expand All @@ -268,7 +268,7 @@ struct repeat<T, exactly<N>>
if(rslt.is_err())
{
loc.reset(first);
return err(rslt.unwrap_err());
return none();
}
retval += rslt.unwrap();
}
Expand All @@ -280,7 +280,7 @@ template<typename T, std::size_t N>
struct repeat<T, at_least<N>>
{
template<typename Cont>
static result<region<Cont>, char>
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
region<Cont> retval(loc);
Expand All @@ -292,7 +292,7 @@ struct repeat<T, at_least<N>>
if(rslt.is_err())
{
loc.reset(first);
return err(rslt.unwrap_err());
return none();
}
retval += rslt.unwrap();
}
Expand All @@ -312,7 +312,7 @@ template<typename T>
struct repeat<T, unlimited>
{
template<typename Cont>
static result<region<Cont>, char>
static result<region<Cont>, none_t>
invoke(location<Cont>& loc)
{
region<Cont> retval(loc);
Expand Down
4 changes: 2 additions & 2 deletions toml/parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ parse_ml_basic_string(location<Container>& loc)
// immediate newline is ignored (if exists)
/* discard return value */ lex_newline::invoke(inner_loc);

delim = err('\0');
delim = none();
while(!delim)
{
using lex_unescaped_seq = repeat<
Expand Down Expand Up @@ -432,7 +432,7 @@ parse_basic_string(location<Container>& loc)
std::string retval;
retval.reserve(token.unwrap().size());

quot = err('\0');
quot = none();
while(!quot)
{
using lex_unescaped_seq = repeat<lex_basic_unescaped, unlimited>;
Expand Down
21 changes: 21 additions & 0 deletions toml/result.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -692,5 +692,26 @@ void swap(result<T, E>& lhs, result<T, E>& rhs)
// return lhs.is_ok() ? lhs : rhs;
// }

// ----------------------------------------------------------------------------
// re-use result<T, E> as a optional<T> with none_t

namespace detail
{
struct none_t {};
inline bool operator==(const none_t&, const none_t&) noexcept {return true;}
inline bool operator!=(const none_t&, const none_t&) noexcept {return false;}
inline bool operator< (const none_t&, const none_t&) noexcept {return false;}
inline bool operator<=(const none_t&, const none_t&) noexcept {return true;}
inline bool operator> (const none_t&, const none_t&) noexcept {return false;}
inline bool operator>=(const none_t&, const none_t&) noexcept {return true;}
template<typename charT, typename traitsT>
std::basic_ostream<charT, traitsT>&
operator<<(std::basic_ostream<charT, traitsT>& os, const none_t&)
{
os << "none";
return os;
}
inline failure<none_t> none() noexcept {return failure<none_t>{none_t{}};}
} // detail
} // toml11
#endif// TOML11_RESULT_H

0 comments on commit 717f592

Please sign in to comment.