From 717f5929c2fff906cf96cfbe7e537b2deb51e9f4 Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Fri, 31 May 2019 17:07:52 +0900 Subject: [PATCH] feat: use detail::none_t instead of char 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. --- toml/combinator.hpp | 46 ++++++++++++++++++++++----------------------- toml/parser.hpp | 4 ++-- toml/result.hpp | 21 +++++++++++++++++++++ 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/toml/combinator.hpp b/toml/combinator.hpp index 1e9e3c4..9f9fa9c 100644 --- a/toml/combinator.hpp +++ b/toml/combinator.hpp @@ -56,19 +56,19 @@ struct character static constexpr char target = C; template - static result, char> + static result, none_t> invoke(location& loc) { static_assert(std::is_same::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 @@ -89,19 +89,19 @@ struct in_range static constexpr char lower = Low; template - static result, char> + static result, none_t> invoke(location& loc) { static_assert(std::is_same::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(); @@ -117,20 +117,20 @@ template struct exclude { template - static result, char> + static result, none_t> invoke(location& loc) { static_assert(std::is_same::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(loc, first, loc.iter())); @@ -142,7 +142,7 @@ template struct maybe { template - static result, char> + static result, none_t> invoke(location& loc) { static_assert(std::is_same::value, @@ -164,7 +164,7 @@ template struct sequence { template - static result, char> + static result, none_t> invoke(location& loc) { static_assert(std::is_same::value, @@ -175,21 +175,21 @@ struct sequence if(rslt.is_err()) { loc.reset(first); - return err(rslt.unwrap_err()); + return none(); } return sequence::invoke(loc, std::move(rslt.unwrap()), first); } // called from the above function only, recursively. template - static result, char> + static result, none_t> invoke(location& loc, region 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::invoke(loc, std::move(reg), first); @@ -201,14 +201,14 @@ struct sequence { // would be called from sequence::invoke only. template - static result, char> + static result, none_t> invoke(location& loc, region 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); @@ -222,7 +222,7 @@ template struct either { template - static result, char> + static result, none_t> invoke(location& loc) { static_assert(std::is_same::value, @@ -237,7 +237,7 @@ template struct either { template - static result, char> + static result, none_t> invoke(location& loc) { static_assert(std::is_same::value, @@ -257,7 +257,7 @@ template struct repeat> { template - static result, char> + static result, none_t> invoke(location& loc) { region retval(loc); @@ -268,7 +268,7 @@ struct repeat> if(rslt.is_err()) { loc.reset(first); - return err(rslt.unwrap_err()); + return none(); } retval += rslt.unwrap(); } @@ -280,7 +280,7 @@ template struct repeat> { template - static result, char> + static result, none_t> invoke(location& loc) { region retval(loc); @@ -292,7 +292,7 @@ struct repeat> if(rslt.is_err()) { loc.reset(first); - return err(rslt.unwrap_err()); + return none(); } retval += rslt.unwrap(); } @@ -312,7 +312,7 @@ template struct repeat { template - static result, char> + static result, none_t> invoke(location& loc) { region retval(loc); diff --git a/toml/parser.hpp b/toml/parser.hpp index ce9d4e1..a345611 100644 --- a/toml/parser.hpp +++ b/toml/parser.hpp @@ -376,7 +376,7 @@ parse_ml_basic_string(location& 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< @@ -432,7 +432,7 @@ parse_basic_string(location& loc) std::string retval; retval.reserve(token.unwrap().size()); - quot = err('\0'); + quot = none(); while(!quot) { using lex_unescaped_seq = repeat; diff --git a/toml/result.hpp b/toml/result.hpp index c7a304d..77cd46c 100644 --- a/toml/result.hpp +++ b/toml/result.hpp @@ -692,5 +692,26 @@ void swap(result& lhs, result& rhs) // return lhs.is_ok() ? lhs : rhs; // } +// ---------------------------------------------------------------------------- +// re-use result as a optional 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 +std::basic_ostream& +operator<<(std::basic_ostream& os, const none_t&) +{ + os << "none"; + return os; +} +inline failure none() noexcept {return failure{none_t{}};} +} // detail } // toml11 #endif// TOML11_RESULT_H