Commit b2272073 authored by Dominik Charousset's avatar Dominik Charousset

Make parser state class public

As part of redesigning the config_value_access API, we have to expose
the parser state class to CAF users.
parent 6f23959e
...@@ -76,8 +76,6 @@ public: ...@@ -76,8 +76,6 @@ public:
using variant_type = detail::tl_apply_t<types, variant>; using variant_type = detail::tl_apply_t<types, variant>;
using parse_state = detail::parse_state;
// -- constructors, destructors, and assignment operators -------------------- // -- constructors, destructors, and assignment operators --------------------
config_value() = default; config_value() = default;
...@@ -238,7 +236,7 @@ struct default_config_value_access { ...@@ -238,7 +236,7 @@ struct default_config_value_access {
return x; return x;
} }
static void parse_cli(config_value::parse_state& ps, T& x) { static void parse_cli(string_parser_state& ps, T& x) {
detail::parse(ps, x); detail::parse(ps, x);
} }
}; };
...@@ -411,7 +409,7 @@ struct select_config_value_access<T, select_config_value_hint::is_integral> { ...@@ -411,7 +409,7 @@ struct select_config_value_access<T, select_config_value_hint::is_integral> {
return x; return x;
} }
static void parse_cli(config_value::parse_state& ps, T& x) { static void parse_cli(string_parser_state& ps, T& x) {
detail::parse(ps, x); detail::parse(ps, x);
} }
}; };
...@@ -471,7 +469,7 @@ struct select_config_value_access<T, select_config_value_hint::is_list> { ...@@ -471,7 +469,7 @@ struct select_config_value_access<T, select_config_value_hint::is_list> {
return result; return result;
} }
static void parse_cli(config_value::parse_state& ps, T& xs) { static void parse_cli(string_parser_state& ps, T& xs) {
config_value::dictionary result; config_value::dictionary result;
bool has_open_token = ps.consume('['); bool has_open_token = ps.consume('[');
do { do {
...@@ -544,7 +542,7 @@ struct select_config_value_access<T, select_config_value_hint::is_map> { ...@@ -544,7 +542,7 @@ struct select_config_value_access<T, select_config_value_hint::is_map> {
return std::move(*result); return std::move(*result);
} }
static void parse_cli(config_value::parse_state& ps, map_type& xs) { static void parse_cli(string_parser_state& ps, map_type& xs) {
detail::parse(ps, xs); detail::parse(ps, xs);
} }
...@@ -581,7 +579,7 @@ struct config_value_access<float> { ...@@ -581,7 +579,7 @@ struct config_value_access<float> {
return x; return x;
} }
static inline void parse_cli(config_value::parse_state& ps, float& x) { static inline void parse_cli(string_parser_state& ps, float& x) {
detail::parse(ps, x); detail::parse(ps, x);
} }
}; };
...@@ -633,7 +631,7 @@ struct config_value_access<std::tuple<Ts...>> { ...@@ -633,7 +631,7 @@ struct config_value_access<std::tuple<Ts...>> {
return result; return result;
} }
static void parse_cli(config_value::parse_state& ps, tuple_type& xs) { static void parse_cli(string_parser_state& ps, tuple_type& xs) {
rec_parse(ps, xs, detail::int_token<0>(), detail::type_list<Ts...>()); rec_parse(ps, xs, detail::int_token<0>(), detail::type_list<Ts...>());
} }
...@@ -703,13 +701,13 @@ private: ...@@ -703,13 +701,13 @@ private:
} }
template <int Pos> template <int Pos>
static void rec_parse(config_value::parse_state&, tuple_type&, static void rec_parse(string_parser_state&, tuple_type&,
detail::int_token<Pos>, detail::type_list<>) { detail::int_token<Pos>, detail::type_list<>) {
// nop // nop
} }
template <int Pos, class U, class... Us> template <int Pos, class U, class... Us>
static void rec_parse(config_value::parse_state& ps, tuple_type& xs, static void rec_parse(string_parser_state& ps, tuple_type& xs,
detail::int_token<Pos>, detail::type_list<U, Us...>) { detail::int_token<Pos>, detail::type_list<U, Us...>) {
using trait = select_config_value_access_t<U>; using trait = select_config_value_access_t<U>;
trait::parse_cli(std::get<Pos>(xs)); trait::parse_cli(std::get<Pos>(xs));
......
...@@ -25,94 +25,94 @@ ...@@ -25,94 +25,94 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "caf/detail/parser/state.hpp"
#include "caf/detail/squashed_int.hpp" #include "caf/detail/squashed_int.hpp"
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
#include "caf/error.hpp" #include "caf/error.hpp"
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
#include "caf/none.hpp" #include "caf/none.hpp"
#include "caf/parser_state.hpp"
#include "caf/string_view.hpp" #include "caf/string_view.hpp"
#include "caf/unit.hpp" #include "caf/unit.hpp"
namespace caf { namespace caf {
namespace detail { namespace detail {
using parse_state = parser::state<string_view::iterator>;
// -- boolean type ------------------------------------------------------------- // -- boolean type -------------------------------------------------------------
void parse(parse_state& ps, bool& x); void parse(string_parser_state& ps, bool& x);
// -- signed integer types ----------------------------------------------------- // -- signed integer types -----------------------------------------------------
void parse(parse_state& ps, int8_t& x); void parse(string_parser_state& ps, int8_t& x);
void parse(parse_state& ps, int16_t& x); void parse(string_parser_state& ps, int16_t& x);
void parse(parse_state& ps, int32_t& x); void parse(string_parser_state& ps, int32_t& x);
void parse(parse_state& ps, int64_t& x); void parse(string_parser_state& ps, int64_t& x);
// -- unsigned integer types --------------------------------------------------- // -- unsigned integer types ---------------------------------------------------
void parse(parse_state& ps, uint8_t& x); void parse(string_parser_state& ps, uint8_t& x);
void parse(parse_state& ps, uint16_t& x); void parse(string_parser_state& ps, uint16_t& x);
void parse(parse_state& ps, uint32_t& x); void parse(string_parser_state& ps, uint32_t& x);
void parse(parse_state& ps, uint64_t& x); void parse(string_parser_state& ps, uint64_t& x);
// -- non-fixed size integer types --------------------------------------------- // -- non-fixed size integer types ---------------------------------------------
template <class T> template <class T>
detail::enable_if_t<std::is_integral<T>::value> parse(parse_state& ps, T& x) { detail::enable_if_t<std::is_integral<T>::value> parse(string_parser_state& ps,
T& x) {
using squashed_type = squashed_int_t<T>; using squashed_type = squashed_int_t<T>;
return parse(ps, reinterpret_cast<squashed_type&>(x)); return parse(ps, reinterpret_cast<squashed_type&>(x));
} }
// -- floating point types ----------------------------------------------------- // -- floating point types -----------------------------------------------------
void parse(parse_state& ps, float& x); void parse(string_parser_state& ps, float& x);
void parse(parse_state& ps, double& x); void parse(string_parser_state& ps, double& x);
// -- CAF types ---------------------------------------------------------------- // -- CAF types ----------------------------------------------------------------
void parse(parse_state& ps, timespan& x); void parse(string_parser_state& ps, timespan& x);
void parse(parse_state& ps, atom_value& x); void parse(string_parser_state& ps, atom_value& x);
void parse(parse_state& ps, ipv4_address& x); void parse(string_parser_state& ps, ipv4_address& x);
void parse(parse_state& ps, ipv4_subnet& x); void parse(string_parser_state& ps, ipv4_subnet& x);
void parse(parse_state& ps, ipv4_endpoint& x); void parse(string_parser_state& ps, ipv4_endpoint& x);
void parse(parse_state& ps, ipv6_address& x); void parse(string_parser_state& ps, ipv6_address& x);
void parse(parse_state& ps, ipv6_subnet& x); void parse(string_parser_state& ps, ipv6_subnet& x);
void parse(parse_state& ps, ipv6_endpoint& x); void parse(string_parser_state& ps, ipv6_endpoint& x);
void parse(parse_state& ps, uri& x); void parse(string_parser_state& ps, uri& x);
// -- STL types ---------------------------------------------------------------- // -- STL types ----------------------------------------------------------------
void parse(parse_state& ps, std::string& x); void parse(string_parser_state& ps, std::string& x);
// -- container types ---------------------------------------------------------- // -- container types ----------------------------------------------------------
void parse_element(parse_state& ps, std::string& x, const char* char_blacklist); void parse_element(string_parser_state& ps, std::string& x,
const char* char_blacklist);
template <class T> template <class T>
enable_if_t<!is_pair<T>::value> parse_element(parse_state& ps, T& x, enable_if_t<!is_pair<T>::value> parse_element(string_parser_state& ps, T& x,
const char*) { const char*) {
parse(ps, x); parse(ps, x);
} }
template <class First, class Second, size_t N> template <class First, class Second, size_t N>
void parse_element(parse_state& ps, std::pair<First, Second>& kvp, void parse_element(string_parser_state& ps, std::pair<First, Second>& kvp,
const char (&char_blacklist)[N]) { const char (&char_blacklist)[N]) {
static_assert(N > 0, "empty array"); static_assert(N > 0, "empty array");
// TODO: consider to guard the blacklist computation with // TODO: consider to guard the blacklist computation with
...@@ -133,7 +133,7 @@ void parse_element(parse_state& ps, std::pair<First, Second>& kvp, ...@@ -133,7 +133,7 @@ void parse_element(parse_state& ps, std::pair<First, Second>& kvp,
} }
template <class T> template <class T>
enable_if_tt<is_iterable<T>> parse(parse_state& ps, T& xs) { enable_if_tt<is_iterable<T>> parse(string_parser_state& ps, T& xs) {
using value_type = deconst_kvp_t<typename T::value_type>; using value_type = deconst_kvp_t<typename T::value_type>;
static constexpr auto is_map_type = is_pair<value_type>::value; static constexpr auto is_map_type = is_pair<value_type>::value;
static constexpr auto opening_char = is_map_type ? '{' : '['; static constexpr auto opening_char = is_map_type ? '{' : '[';
...@@ -181,7 +181,7 @@ enable_if_tt<is_iterable<T>> parse(parse_state& ps, T& xs) { ...@@ -181,7 +181,7 @@ enable_if_tt<is_iterable<T>> parse(parse_state& ps, T& xs) {
template <class T> template <class T>
error parse(string_view str, T& x) { error parse(string_view str, T& x) {
parse_state ps{str.begin(), str.end()}; string_parser_state ps{str.begin(), str.end()};
parse(ps, x); parse(ps, x);
if (ps.code == pec::success) if (ps.code == pec::success)
return none; return none;
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/detail/parser/chars.hpp" #include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/is_char.hpp" #include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/scope_guard.hpp" #include "caf/detail/scope_guard.hpp"
#include "caf/pec.hpp" #include "caf/pec.hpp"
...@@ -40,9 +39,8 @@ namespace parser { ...@@ -40,9 +39,8 @@ namespace parser {
/// Reads a number, i.e., on success produces either an `int64_t` or a /// Reads a number, i.e., on success produces either an `int64_t` or a
/// `double`. /// `double`.
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_atom(state<Iterator, Sentinel>& ps, Consumer&& consumer, void read_atom(State& ps, Consumer&& consumer, bool accept_unquoted = false) {
bool accept_unquoted = false) {
size_t pos = 0; size_t pos = 0;
char buf[11]; char buf[11];
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/detail/parser/chars.hpp" #include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/is_char.hpp" #include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/scope_guard.hpp" #include "caf/detail/scope_guard.hpp"
#include "caf/pec.hpp" #include "caf/pec.hpp"
...@@ -37,8 +36,8 @@ namespace detail { ...@@ -37,8 +36,8 @@ namespace detail {
namespace parser { namespace parser {
/// Reads a boolean. /// Reads a boolean.
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_bool(state<Iterator, Sentinel>& ps, Consumer&& consumer) { void read_bool(State& ps, Consumer&& consumer) {
bool res = false; bool res = false;
auto g = make_scope_guard([&] { auto g = make_scope_guard([&] {
if (ps.code <= pec::trailing_character) if (ps.code <= pec::trailing_character)
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "caf/detail/parser/chars.hpp" #include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/is_char.hpp" #include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/is_digit.hpp" #include "caf/detail/parser/is_digit.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/parser/sub_ascii.hpp" #include "caf/detail/parser/sub_ascii.hpp"
#include "caf/detail/scope_guard.hpp" #include "caf/detail/scope_guard.hpp"
#include "caf/optional.hpp" #include "caf/optional.hpp"
...@@ -45,8 +44,8 @@ namespace parser { ...@@ -45,8 +44,8 @@ namespace parser {
/// @param consumer Sink for generated values. /// @param consumer Sink for generated values.
/// @param start_value Allows another parser to pre-initialize this parser with /// @param start_value Allows another parser to pre-initialize this parser with
/// the pre-decimal value. /// the pre-decimal value.
template <class Iterator, class Sentinel, class Consumer, class ValueType> template <class State, class Consumer, class ValueType>
void read_floating_point(state<Iterator, Sentinel>& ps, Consumer&& consumer, void read_floating_point(State& ps, Consumer&& consumer,
optional<ValueType> start_value, optional<ValueType> start_value,
bool negative = false) { bool negative = false) {
// Any exponent larger than 511 always overflows. // Any exponent larger than 511 always overflows.
...@@ -185,8 +184,8 @@ void read_floating_point(state<Iterator, Sentinel>& ps, Consumer&& consumer, ...@@ -185,8 +184,8 @@ void read_floating_point(state<Iterator, Sentinel>& ps, Consumer&& consumer,
// clang-format on // clang-format on
} }
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_floating_point(state<Iterator, Sentinel>& ps, Consumer&& consumer) { void read_floating_point(State& ps, Consumer&& consumer) {
using consumer_type = typename std::decay<Consumer>::type; using consumer_type = typename std::decay<Consumer>::type;
using value_type = typename consumer_type::value_type; using value_type = typename consumer_type::value_type;
return read_floating_point(ps, consumer, optional<value_type>{}); return read_floating_point(ps, consumer, optional<value_type>{});
......
...@@ -58,8 +58,8 @@ namespace parser { ...@@ -58,8 +58,8 @@ namespace parser {
// }] // }]
// //
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_ini_comment(state<Iterator, Sentinel>& ps, Consumer&&) { void read_ini_comment(State& ps, Consumer&&) {
start(); start();
term_state(init) { term_state(init) {
transition(done, '\n') transition(done, '\n')
...@@ -71,11 +71,11 @@ void read_ini_comment(state<Iterator, Sentinel>& ps, Consumer&&) { ...@@ -71,11 +71,11 @@ void read_ini_comment(state<Iterator, Sentinel>& ps, Consumer&&) {
fin(); fin();
} }
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_ini_value(state<Iterator, Sentinel>& ps, Consumer&& consumer); void read_ini_value(State& ps, Consumer&& consumer);
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_ini_list(state<Iterator, Sentinel>& ps, Consumer&& consumer) { void read_ini_list(State& ps, Consumer&& consumer) {
start(); start();
state(init) { state(init) {
epsilon(before_value) epsilon(before_value)
...@@ -98,8 +98,8 @@ void read_ini_list(state<Iterator, Sentinel>& ps, Consumer&& consumer) { ...@@ -98,8 +98,8 @@ void read_ini_list(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
fin(); fin();
} }
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_ini_map(state<Iterator, Sentinel>& ps, Consumer&& consumer) { void read_ini_map(State& ps, Consumer&& consumer) {
std::string key; std::string key;
auto alnum_or_dash = [](char x) { auto alnum_or_dash = [](char x) {
return isalnum(x) || x == '-' || x == '_'; return isalnum(x) || x == '-' || x == '_';
...@@ -154,8 +154,8 @@ void read_ini_map(state<Iterator, Sentinel>& ps, Consumer&& consumer) { ...@@ -154,8 +154,8 @@ void read_ini_map(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
// clang-format on // clang-format on
} }
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_ini_uri(state<Iterator, Sentinel>& ps, Consumer&& consumer) { void read_ini_uri(State& ps, Consumer&& consumer) {
uri_builder builder; uri_builder builder;
auto g = make_scope_guard([&] { auto g = make_scope_guard([&] {
if (ps.code <= pec::trailing_character) if (ps.code <= pec::trailing_character)
...@@ -180,8 +180,8 @@ void read_ini_uri(state<Iterator, Sentinel>& ps, Consumer&& consumer) { ...@@ -180,8 +180,8 @@ void read_ini_uri(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
fin(); fin();
} }
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_ini_value(state<Iterator, Sentinel>& ps, Consumer&& consumer) { void read_ini_value(State& ps, Consumer&& consumer) {
start(); start();
state(init) { state(init) {
fsm_epsilon(read_string(ps, consumer), done, '"') fsm_epsilon(read_string(ps, consumer), done, '"')
...@@ -200,8 +200,8 @@ void read_ini_value(state<Iterator, Sentinel>& ps, Consumer&& consumer) { ...@@ -200,8 +200,8 @@ void read_ini_value(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
} }
/// Reads an INI formatted input. /// Reads an INI formatted input.
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_ini_section(state<Iterator, Sentinel>& ps, Consumer&& consumer) { void read_ini_section(State& ps, Consumer&& consumer) {
using std::swap; using std::swap;
std::string tmp; std::string tmp;
auto alnum = [](char x) { return isalnum(x) || x == '_'; }; auto alnum = [](char x) { return isalnum(x) || x == '_'; };
...@@ -254,8 +254,8 @@ void read_ini_section(state<Iterator, Sentinel>& ps, Consumer&& consumer) { ...@@ -254,8 +254,8 @@ void read_ini_section(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
/// Reads a nested group, e.g., "[foo.bar]" would consume "[foo.]" in read_ini /// Reads a nested group, e.g., "[foo.bar]" would consume "[foo.]" in read_ini
/// and then delegate to this function for parsing "bar]". /// and then delegate to this function for parsing "bar]".
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_nested_group(state<Iterator, Sentinel>& ps, Consumer&& consumer) { void read_nested_group(State& ps, Consumer&& consumer) {
using std::swap; using std::swap;
std::string key; std::string key;
auto alnum = [](char x) { return isalnum(x) || x == '_'; }; auto alnum = [](char x) { return isalnum(x) || x == '_'; };
...@@ -290,8 +290,8 @@ void read_nested_group(state<Iterator, Sentinel>& ps, Consumer&& consumer) { ...@@ -290,8 +290,8 @@ void read_nested_group(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
} }
/// Reads an INI formatted input. /// Reads an INI formatted input.
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_ini(state<Iterator, Sentinel>& ps, Consumer&& consumer) { void read_ini(State& ps, Consumer&& consumer) {
using std::swap; using std::swap;
std::string tmp{"global"}; std::string tmp{"global"};
auto alnum = [](char x) { return isalnum(x) || x == '_'; }; auto alnum = [](char x) { return isalnum(x) || x == '_'; };
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "caf/detail/parser/chars.hpp" #include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/is_char.hpp" #include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/is_digit.hpp" #include "caf/detail/parser/is_digit.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/parser/sub_ascii.hpp" #include "caf/detail/parser/sub_ascii.hpp"
#include "caf/detail/scope_guard.hpp" #include "caf/detail/scope_guard.hpp"
#include "caf/ipv4_address.hpp" #include "caf/ipv4_address.hpp"
...@@ -48,8 +47,8 @@ struct read_ipv4_octet_consumer { ...@@ -48,8 +47,8 @@ struct read_ipv4_octet_consumer {
} }
}; };
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_ipv4_octet(state<Iterator, Sentinel>& ps, Consumer& consumer) { void read_ipv4_octet(State& ps, Consumer& consumer) {
uint8_t res = 0; uint8_t res = 0;
// Reads the a decimal place. // Reads the a decimal place.
auto rd_decimal = [&](char c) { auto rd_decimal = [&](char c) {
...@@ -72,8 +71,8 @@ void read_ipv4_octet(state<Iterator, Sentinel>& ps, Consumer& consumer) { ...@@ -72,8 +71,8 @@ void read_ipv4_octet(state<Iterator, Sentinel>& ps, Consumer& consumer) {
/// Reads a number, i.e., on success produces either an `int64_t` or a /// Reads a number, i.e., on success produces either an `int64_t` or a
/// `double`. /// `double`.
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_ipv4_address(state<Iterator, Sentinel>& ps, Consumer&& consumer) { void read_ipv4_address(State& ps, Consumer&& consumer) {
read_ipv4_octet_consumer f; read_ipv4_octet_consumer f;
auto g = make_scope_guard([&] { auto g = make_scope_guard([&] {
if (ps.code <= pec::trailing_character) { if (ps.code <= pec::trailing_character) {
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include "caf/detail/parser/chars.hpp" #include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/is_char.hpp" #include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/is_digit.hpp" #include "caf/detail/parser/is_digit.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/parser/sub_ascii.hpp" #include "caf/detail/parser/sub_ascii.hpp"
#include "caf/detail/scope_guard.hpp" #include "caf/detail/scope_guard.hpp"
#include "caf/ipv4_address.hpp" #include "caf/ipv4_address.hpp"
...@@ -57,8 +56,8 @@ namespace parser { ...@@ -57,8 +56,8 @@ namespace parser {
// h16 = 1*4HEXDIG // h16 = 1*4HEXDIG
/// Reads 16 (hex) bits of an IPv6 address. /// Reads 16 (hex) bits of an IPv6 address.
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_ipv6_h16(state<Iterator, Sentinel>& ps, Consumer& consumer) { void read_ipv6_h16(State& ps, Consumer& consumer) {
uint16_t res = 0; uint16_t res = 0;
size_t digits = 0; size_t digits = 0;
// Reads the a hexadecimal place. // Reads the a hexadecimal place.
...@@ -83,8 +82,8 @@ void read_ipv6_h16(state<Iterator, Sentinel>& ps, Consumer& consumer) { ...@@ -83,8 +82,8 @@ void read_ipv6_h16(state<Iterator, Sentinel>& ps, Consumer& consumer) {
} }
/// Reads 16 (hex) or 32 (IPv4 notation) bits of an IPv6 address. /// Reads 16 (hex) or 32 (IPv4 notation) bits of an IPv6 address.
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_ipv6_h16_or_l32(state<Iterator, Sentinel>& ps, Consumer& consumer) { void read_ipv6_h16_or_l32(State& ps, Consumer& consumer) {
enum mode_t { indeterminate, v6_bits, v4_octets }; enum mode_t { indeterminate, v6_bits, v4_octets };
mode_t mode = indeterminate; mode_t mode = indeterminate;
uint16_t hex_res = 0; uint16_t hex_res = 0;
...@@ -173,8 +172,8 @@ read_ipv6_address_piece_consumer<F> make_read_ipv6_address_piece_consumer(F f) { ...@@ -173,8 +172,8 @@ read_ipv6_address_piece_consumer<F> make_read_ipv6_address_piece_consumer(F f) {
/// Reads a number, i.e., on success produces either an `int64_t` or a /// Reads a number, i.e., on success produces either an `int64_t` or a
/// `double`. /// `double`.
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_ipv6_address(state<Iterator, Sentinel>& ps, Consumer&& consumer) { void read_ipv6_address(State& ps, Consumer&& consumer) {
// IPv6 allows omitting blocks of zeros, splitting the string into a part // IPv6 allows omitting blocks of zeros, splitting the string into a part
// before the zeros (prefix) and a part after the zeros (suffix). For example, // before the zeros (prefix) and a part after the zeros (suffix). For example,
// ff::1 is 00FF0000000000000000000000000001 // ff::1 is 00FF0000000000000000000000000001
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "caf/detail/parser/is_char.hpp" #include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/is_digit.hpp" #include "caf/detail/parser/is_digit.hpp"
#include "caf/detail/parser/read_floating_point.hpp" #include "caf/detail/parser/read_floating_point.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/parser/sub_ascii.hpp" #include "caf/detail/parser/sub_ascii.hpp"
#include "caf/detail/scope_guard.hpp" #include "caf/detail/scope_guard.hpp"
#include "caf/pec.hpp" #include "caf/pec.hpp"
...@@ -41,8 +40,8 @@ namespace parser { ...@@ -41,8 +40,8 @@ namespace parser {
/// Reads a number, i.e., on success produces either an `int64_t` or a /// Reads a number, i.e., on success produces either an `int64_t` or a
/// `double`. /// `double`.
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_number(state<Iterator, Sentinel>& ps, Consumer& consumer) { void read_number(State& ps, Consumer& consumer) {
// Our result when reading an integer number. // Our result when reading an integer number.
int64_t result = 0; int64_t result = 0;
// Computes the result on success. // Computes the result on success.
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include "caf/detail/parser/is_char.hpp" #include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/read_number.hpp" #include "caf/detail/parser/read_number.hpp"
#include "caf/detail/parser/read_timespan.hpp" #include "caf/detail/parser/read_timespan.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/scope_guard.hpp" #include "caf/detail/scope_guard.hpp"
#include "caf/none.hpp" #include "caf/none.hpp"
#include "caf/optional.hpp" #include "caf/optional.hpp"
...@@ -45,9 +44,8 @@ namespace parser { ...@@ -45,9 +44,8 @@ namespace parser {
/// Reads a number or a duration, i.e., on success produces an `int64_t`, a /// Reads a number or a duration, i.e., on success produces an `int64_t`, a
/// `double`, or a `timespan`. /// `double`, or a `timespan`.
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_number_or_timespan(state<Iterator, Sentinel>& ps, void read_number_or_timespan(State& ps, Consumer& consumer) {
Consumer& consumer) {
using namespace std::chrono; using namespace std::chrono;
struct interim_consumer { struct interim_consumer {
variant<none_t, int64_t, double> interim; variant<none_t, int64_t, double> interim;
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "caf/detail/parser/chars.hpp" #include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/is_char.hpp" #include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/is_digit.hpp" #include "caf/detail/parser/is_digit.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/parser/sub_ascii.hpp" #include "caf/detail/parser/sub_ascii.hpp"
#include "caf/detail/scope_guard.hpp" #include "caf/detail/scope_guard.hpp"
#include "caf/pec.hpp" #include "caf/pec.hpp"
...@@ -41,8 +40,8 @@ namespace parser { ...@@ -41,8 +40,8 @@ namespace parser {
/// Reads a number, i.e., on success produces either an `int64_t` or a /// Reads a number, i.e., on success produces either an `int64_t` or a
/// `double`. /// `double`.
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_signed_integer(state<Iterator, Sentinel>& ps, Consumer&& consumer) { void read_signed_integer(State& ps, Consumer&& consumer) {
using consumer_type = typename std::decay<Consumer>::type; using consumer_type = typename std::decay<Consumer>::type;
using value_type = typename consumer_type::value_type; using value_type = typename consumer_type::value_type;
static_assert(std::is_integral<value_type>::value static_assert(std::is_integral<value_type>::value
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/detail/parser/chars.hpp" #include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/scope_guard.hpp" #include "caf/detail/scope_guard.hpp"
#include "caf/pec.hpp" #include "caf/pec.hpp"
...@@ -37,8 +36,8 @@ namespace parser { ...@@ -37,8 +36,8 @@ namespace parser {
/// Reads a quoted or unquoted string. Quoted strings allow escaping, while /// Reads a quoted or unquoted string. Quoted strings allow escaping, while
/// unquoted strings may only include alphanumeric characters. /// unquoted strings may only include alphanumeric characters.
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_string(state<Iterator, Sentinel>& ps, Consumer&& consumer) { void read_string(State& ps, Consumer&& consumer) {
std::string res; std::string res;
auto g = caf::detail::make_scope_guard([&] { auto g = caf::detail::make_scope_guard([&] {
if (ps.code <= pec::trailing_character) if (ps.code <= pec::trailing_character)
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/detail/parser/read_signed_integer.hpp" #include "caf/detail/parser/read_signed_integer.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/scope_guard.hpp" #include "caf/detail/scope_guard.hpp"
#include "caf/optional.hpp" #include "caf/optional.hpp"
#include "caf/pec.hpp" #include "caf/pec.hpp"
...@@ -39,8 +38,8 @@ namespace detail { ...@@ -39,8 +38,8 @@ namespace detail {
namespace parser { namespace parser {
/// Reads a timespan. /// Reads a timespan.
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_timespan(state<Iterator, Sentinel>& ps, Consumer&& consumer, void read_timespan(State& ps, Consumer&& consumer,
optional<int64_t> num = none) { optional<int64_t> num = none) {
using namespace std::chrono; using namespace std::chrono;
struct interim_consumer { struct interim_consumer {
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include "caf/detail/parser/chars.hpp" #include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/is_char.hpp" #include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/is_digit.hpp" #include "caf/detail/parser/is_digit.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/parser/sub_ascii.hpp" #include "caf/detail/parser/sub_ascii.hpp"
#include "caf/detail/scope_guard.hpp" #include "caf/detail/scope_guard.hpp"
#include "caf/pec.hpp" #include "caf/pec.hpp"
...@@ -41,8 +40,8 @@ namespace parser { ...@@ -41,8 +40,8 @@ namespace parser {
/// Reads a number, i.e., on success produces either an `int64_t` or a /// Reads a number, i.e., on success produces either an `int64_t` or a
/// `double`. /// `double`.
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_unsigned_integer(state<Iterator, Sentinel>& ps, Consumer&& consumer) { void read_unsigned_integer(State& ps, Consumer&& consumer) {
using consumer_type = typename std::decay<Consumer>::type; using consumer_type = typename std::decay<Consumer>::type;
using value_type = typename consumer_type::value_type; using value_type = typename consumer_type::value_type;
static_assert(std::is_integral<value_type>::value static_assert(std::is_integral<value_type>::value
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include "caf/detail/parser/add_ascii.hpp" #include "caf/detail/parser/add_ascii.hpp"
#include "caf/detail/parser/chars.hpp" #include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/read_ipv6_address.hpp" #include "caf/detail/parser/read_ipv6_address.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/scope_guard.hpp" #include "caf/detail/scope_guard.hpp"
#include "caf/pec.hpp" #include "caf/pec.hpp"
#include "caf/uri.hpp" #include "caf/uri.hpp"
...@@ -47,8 +46,8 @@ namespace parser { ...@@ -47,8 +46,8 @@ namespace parser {
// generate ranges for the subcomponents. URIs can't have linebreaks, so we can // generate ranges for the subcomponents. URIs can't have linebreaks, so we can
// safely keep track of the position by looking at the column. // safely keep track of the position by looking at the column.
template <class Iterator, class Sentinel> template <class State>
void read_uri_percent_encoded(state<Iterator, Sentinel>& ps, std::string& str) { void read_uri_percent_encoded(State& ps, std::string& str) {
uint8_t char_code = 0; uint8_t char_code = 0;
auto g = make_scope_guard([&] { auto g = make_scope_guard([&] {
if (ps.code <= pec::trailing_character) if (ps.code <= pec::trailing_character)
...@@ -75,8 +74,8 @@ inline bool uri_unprotected_char(char c) { ...@@ -75,8 +74,8 @@ inline bool uri_unprotected_char(char c) {
transition(next_state, uri_unprotected_char, dest += ch) \ transition(next_state, uri_unprotected_char, dest += ch) \
fsm_transition(read_uri_percent_encoded(ps, dest), next_state, '%') fsm_transition(read_uri_percent_encoded(ps, dest), next_state, '%')
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_uri_query(state<Iterator, Sentinel>& ps, Consumer&& consumer) { void read_uri_query(State& ps, Consumer&& consumer) {
// Local variables. // Local variables.
uri::query_map result; uri::query_map result;
std::string key; std::string key;
...@@ -113,8 +112,8 @@ void read_uri_query(state<Iterator, Sentinel>& ps, Consumer&& consumer) { ...@@ -113,8 +112,8 @@ void read_uri_query(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
fin(); fin();
} }
template <class Iterator, class Sentinel, class Consumer> template <class State, class Consumer>
void read_uri(state<Iterator, Sentinel>& ps, Consumer&& consumer) { void read_uri(State& ps, Consumer&& consumer) {
// Local variables. // Local variables.
std::string str; std::string str;
uint16_t port = 0; uint16_t port = 0;
......
...@@ -56,6 +56,8 @@ template <class> struct timeout_definition; ...@@ -56,6 +56,8 @@ template <class> struct timeout_definition;
template <class, class> class stream_stage; template <class, class> class stream_stage;
template <class Iterator, class Sentinel = Iterator> struct parser_state;
// -- 3 param templates -------------------------------------------------------- // -- 3 param templates --------------------------------------------------------
template <class, class, int> class actor_cast_access; template <class, class, int> class actor_cast_access;
......
...@@ -59,10 +59,10 @@ expected<config_value> parse_impl(T* ptr, string_view str) { ...@@ -59,10 +59,10 @@ expected<config_value> parse_impl(T* ptr, string_view str) {
return parse_impl(&tmp, str); return parse_impl(&tmp, str);
} }
using trait = select_config_value_access_t<T>; using trait = select_config_value_access_t<T>;
config_value::parse_state ps{str.begin(), str.end()}; string_parser_state ps{str.begin(), str.end()};
trait::parse_cli(ps, *ptr); trait::parse_cli(ps, *ptr);
if (ps.code != pec::success) if (ps.code != pec::success)
return ps.make_error(ps.code); return make_error(ps);
return config_value{trait::convert(*ptr)}; return config_value{trait::convert(*ptr)};
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* | |___ / ___ \| _| Framework * * | |___ / ___ \| _| Framework *
* \____/_/ \_|_| * * \____/_/ \_|_| *
* * * *
* Copyright 2011-2018 Dominik Charousset * * Copyright 2011-2019 Dominik Charousset *
* * * *
* Distributed under the terms and conditions of the BSD 3-Clause License or * * Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software * * (at your option) under the terms and conditions of the Boost Software *
...@@ -21,30 +21,39 @@ ...@@ -21,30 +21,39 @@
#include <cctype> #include <cctype>
#include <cstdint> #include <cstdint>
#include "caf/error.hpp" #include "caf/fwd.hpp"
#include "caf/pec.hpp" #include "caf/pec.hpp"
#include "caf/string_view.hpp"
namespace caf { namespace caf {
namespace detail {
namespace parser {
template <class Iterator, class Sentinel = Iterator> /// Stores all informations necessary for implementing an FSM-based parser.
struct state { template <class Iterator, class Sentinel>
struct parser_state {
/// Current position of the parser.
Iterator i; Iterator i;
/// End-of-input marker.
Sentinel e; Sentinel e;
/// Current state of the parser.
pec code; pec code;
/// Current line in the input.
int32_t line; int32_t line;
/// Position in the current line.
int32_t column; int32_t column;
state() noexcept : i(), e(), code(pec::success), line(1), column(1) { parser_state() noexcept : i(), e(), code(pec::success), line(1), column(1) {
// nop // nop
} }
explicit state(Iterator first) noexcept : state() { explicit parser_state(Iterator first) noexcept : parser_state() {
i = first; i = first;
} }
state(Iterator first, Sentinel last) noexcept : state() { parser_state(Iterator first, Sentinel last) noexcept : parser_state() {
i = first; i = first;
e = last; e = last;
} }
...@@ -91,13 +100,17 @@ struct state { ...@@ -91,13 +100,17 @@ struct state {
} }
return false; return false;
} }
error make_error(pec code) {
return caf::make_error(code, static_cast<size_t>(line),
static_cast<size_t>(column));
}
}; };
} // namespace parser /// Returns an error object from the current code in `ps` as well as its
} // namespace detail /// current position.
template <class Iterator, class Sentinel>
auto make_error(const parser_state<Iterator, Sentinel>& ps)
-> decltype(make_error(ps.code, ps.line, ps.column)) {
return make_error(ps.code, ps.line, ps.column);
}
/// Specialization for parsers operating on string views.
using string_parser_state = parser_state<string_view::iterator>;
} // namespace caf } // namespace caf
...@@ -74,7 +74,7 @@ error make_error(pec code); ...@@ -74,7 +74,7 @@ error make_error(pec code);
/// Returns an error object from given error code with additional context /// Returns an error object from given error code with additional context
/// information for where the parser stopped in the input. /// information for where the parser stopped in the input.
error make_error(pec code, size_t line, size_t column); error make_error(pec code, int32_t line, int32_t column);
/// Returns an error object from given error code with additional context /// Returns an error object from given error code with additional context
/// information for where the parser stopped in the argument. /// information for where the parser stopped in the argument.
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include <vector> #include <vector>
#include "caf/detail/comparable.hpp" #include "caf/detail/comparable.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/unordered_flat_map.hpp" #include "caf/detail/unordered_flat_map.hpp"
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
#include "caf/intrusive_ptr.hpp" #include "caf/intrusive_ptr.hpp"
......
...@@ -494,8 +494,7 @@ error actor_system_config::parse_config(std::istream& source, ...@@ -494,8 +494,7 @@ error actor_system_config::parse_config(std::istream& source,
if (!source) if (!source)
return make_error(sec::runtime_error, "source stream invalid"); return make_error(sec::runtime_error, "source stream invalid");
detail::ini_consumer consumer{opts, result}; detail::ini_consumer consumer{opts, result};
detail::parser::state<ini_iter, ini_sentinel> res; parser_state<ini_iter, ini_sentinel> res{ini_iter{&source}};
res.i = ini_iter{&source};
detail::parser::read_ini(res, consumer); detail::parser::read_ini(res, consumer);
if (res.i != res.e) if (res.i != res.e)
return make_error(res.code, res.line, res.column); return make_error(res.code, res.line, res.column);
......
...@@ -26,7 +26,9 @@ ...@@ -26,7 +26,9 @@
#include "caf/detail/parser/read_ini.hpp" #include "caf/detail/parser/read_ini.hpp"
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
#include "caf/expected.hpp" #include "caf/expected.hpp"
#include "caf/parser_state.hpp"
#include "caf/pec.hpp" #include "caf/pec.hpp"
#include "caf/string_view.hpp"
namespace caf { namespace caf {
...@@ -66,10 +68,8 @@ expected<config_value> config_value::parse(string_view::iterator first, ...@@ -66,10 +68,8 @@ expected<config_value> config_value::parse(string_view::iterator first,
if (++i == last) if (++i == last)
return make_error(pec::unexpected_eof); return make_error(pec::unexpected_eof);
// Dispatch to parser. // Dispatch to parser.
parser::state<string_view::iterator> res;
detail::ini_value_consumer f; detail::ini_value_consumer f;
res.i = i; string_parser_state res{i, last};
res.e = last;
parser::read_ini_value(res, f); parser::read_ini_value(res, f);
if (res.code == pec::success) if (res.code == pec::success)
return std::move(f.result); return std::move(f.result);
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#include "caf/uri_builder.hpp" #include "caf/uri_builder.hpp"
#define PARSE_IMPL(type, parser_name) \ #define PARSE_IMPL(type, parser_name) \
void parse(parse_state& ps, type& x) { \ void parse(string_parser_state& ps, type& x) { \
parser::read_##parser_name(ps, make_consumer(x)); \ parser::read_##parser_name(ps, make_consumer(x)); \
} }
...@@ -55,7 +55,7 @@ struct literal { ...@@ -55,7 +55,7 @@ struct literal {
} }
}; };
void parse(parse_state& ps, literal& x) { void parse(string_parser_state& ps, literal& x) {
CAF_ASSERT(x.str.size() > 0); CAF_ASSERT(x.str.size() > 0);
if (ps.current() != x.str[0]) { if (ps.current() != x.str[0]) {
ps.code = pec::unexpected_character; ps.code = pec::unexpected_character;
...@@ -72,12 +72,12 @@ void parse(parse_state& ps, literal& x) { ...@@ -72,12 +72,12 @@ void parse(parse_state& ps, literal& x) {
ps.code = ps.at_end() ? pec::success : pec::trailing_character; ps.code = ps.at_end() ? pec::success : pec::trailing_character;
} }
void parse_sequence(parse_state&) { void parse_sequence(string_parser_state&) {
// End of recursion. // End of recursion.
} }
template <class T, class... Ts> template <class T, class... Ts>
void parse_sequence(parse_state& ps, T&& x, Ts&&... xs) { void parse_sequence(string_parser_state& ps, T&& x, Ts&&... xs) {
parse(ps, x); parse(ps, x);
// TODO: use `if constexpr` when switching to C++17 // TODO: use `if constexpr` when switching to C++17
if (sizeof...(Ts) > 0) { if (sizeof...(Ts) > 0) {
...@@ -111,11 +111,11 @@ PARSE_IMPL(double, floating_point) ...@@ -111,11 +111,11 @@ PARSE_IMPL(double, floating_point)
PARSE_IMPL(timespan, timespan) PARSE_IMPL(timespan, timespan)
void parse(parse_state& ps, atom_value& x) { void parse(string_parser_state& ps, atom_value& x) {
parser::read_atom(ps, make_consumer(x), true); parser::read_atom(ps, make_consumer(x), true);
} }
void parse(parse_state& ps, uri& x) { void parse(string_parser_state& ps, uri& x) {
uri_builder builder; uri_builder builder;
if (ps.consume('<')) { if (ps.consume('<')) {
parser::read_uri(ps, builder); parser::read_uri(ps, builder);
...@@ -126,7 +126,7 @@ void parse(parse_state& ps, uri& x) { ...@@ -126,7 +126,7 @@ void parse(parse_state& ps, uri& x) {
return; return;
} }
} else { } else {
read_uri(ps, builder); parser::read_uri(ps, builder);
} }
if (ps.code <= pec::trailing_character) if (ps.code <= pec::trailing_character)
x = builder.make(); x = builder.make();
...@@ -134,7 +134,7 @@ void parse(parse_state& ps, uri& x) { ...@@ -134,7 +134,7 @@ void parse(parse_state& ps, uri& x) {
PARSE_IMPL(ipv4_address, ipv4_address) PARSE_IMPL(ipv4_address, ipv4_address)
void parse(parse_state& ps, ipv4_subnet& x) { void parse(string_parser_state& ps, ipv4_subnet& x) {
ipv4_address addr; ipv4_address addr;
uint8_t prefix_length; uint8_t prefix_length;
parse_sequence(ps, addr, literal{"/"}, prefix_length); parse_sequence(ps, addr, literal{"/"}, prefix_length);
...@@ -147,7 +147,7 @@ void parse(parse_state& ps, ipv4_subnet& x) { ...@@ -147,7 +147,7 @@ void parse(parse_state& ps, ipv4_subnet& x) {
} }
} }
void parse(parse_state& ps, ipv4_endpoint& x) { void parse(string_parser_state& ps, ipv4_endpoint& x) {
ipv4_address addr; ipv4_address addr;
uint16_t port; uint16_t port;
parse_sequence(ps, addr, literal{":"}, port); parse_sequence(ps, addr, literal{":"}, port);
...@@ -157,7 +157,7 @@ void parse(parse_state& ps, ipv4_endpoint& x) { ...@@ -157,7 +157,7 @@ void parse(parse_state& ps, ipv4_endpoint& x) {
PARSE_IMPL(ipv6_address, ipv6_address) PARSE_IMPL(ipv6_address, ipv6_address)
void parse(parse_state& ps, ipv6_subnet& x) { void parse(string_parser_state& ps, ipv6_subnet& x) {
// TODO: this algorithm is currently not one-pass. The reason we need to // TODO: this algorithm is currently not one-pass. The reason we need to
// check whether the input is a valid ipv4_subnet first is that "1.2.3.0" is // check whether the input is a valid ipv4_subnet first is that "1.2.3.0" is
// a valid IPv6 address, but "1.2.3.0/16" results in the wrong subnet when // a valid IPv6 address, but "1.2.3.0/16" results in the wrong subnet when
...@@ -185,7 +185,7 @@ void parse(parse_state& ps, ipv6_subnet& x) { ...@@ -185,7 +185,7 @@ void parse(parse_state& ps, ipv6_subnet& x) {
} }
} }
void parse(parse_state& ps, ipv6_endpoint& x) { void parse(string_parser_state& ps, ipv6_endpoint& x) {
ipv6_address addr; ipv6_address addr;
uint16_t port; uint16_t port;
if (ps.consume('[')) { if (ps.consume('[')) {
...@@ -200,7 +200,7 @@ void parse(parse_state& ps, ipv6_endpoint& x) { ...@@ -200,7 +200,7 @@ void parse(parse_state& ps, ipv6_endpoint& x) {
x = ipv6_endpoint{addr, port}; x = ipv6_endpoint{addr, port};
} }
void parse(parse_state& ps, std::string& x) { void parse(string_parser_state& ps, std::string& x) {
ps.skip_whitespaces(); ps.skip_whitespaces();
if (ps.current() == '"') { if (ps.current() == '"') {
parser::read_string(ps, make_consumer(x)); parser::read_string(ps, make_consumer(x));
...@@ -213,7 +213,7 @@ void parse(parse_state& ps, std::string& x) { ...@@ -213,7 +213,7 @@ void parse(parse_state& ps, std::string& x) {
ps.code = pec::success; ps.code = pec::success;
} }
void parse_element(parse_state& ps, std::string& x, void parse_element(string_parser_state& ps, std::string& x,
const char* char_blacklist) { const char* char_blacklist) {
ps.skip_whitespaces(); ps.skip_whitespaces();
if (ps.current() == '"') { if (ps.current() == '"') {
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "caf/detail/network_order.hpp" #include "caf/detail/network_order.hpp"
#include "caf/detail/parser/read_ipv4_address.hpp" #include "caf/detail/parser/read_ipv4_address.hpp"
#include "caf/error.hpp" #include "caf/error.hpp"
#include "caf/parser_state.hpp"
#include "caf/pec.hpp" #include "caf/pec.hpp"
#include "caf/string_view.hpp" #include "caf/string_view.hpp"
...@@ -89,8 +90,8 @@ std::string to_string(const ipv4_address& x) { ...@@ -89,8 +90,8 @@ std::string to_string(const ipv4_address& x) {
error parse(string_view str, ipv4_address& dest) { error parse(string_view str, ipv4_address& dest) {
using namespace detail; using namespace detail;
parser::state<string_view::iterator> res{str.begin(), str.end()};
ipv4_address_consumer f{dest}; ipv4_address_consumer f{dest};
string_parser_state res{str.begin(), str.end()};
parser::read_ipv4_address(res, f); parser::read_ipv4_address(res, f);
if (res.code == pec::success) if (res.code == pec::success)
return none; return none;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "caf/detail/parser/read_ipv6_address.hpp" #include "caf/detail/parser/read_ipv6_address.hpp"
#include "caf/error.hpp" #include "caf/error.hpp"
#include "caf/ipv4_address.hpp" #include "caf/ipv4_address.hpp"
#include "caf/parser_state.hpp"
#include "caf/pec.hpp" #include "caf/pec.hpp"
#include "caf/string_view.hpp" #include "caf/string_view.hpp"
...@@ -212,8 +213,8 @@ std::string to_string(ipv6_address x) { ...@@ -212,8 +213,8 @@ std::string to_string(ipv6_address x) {
error parse(string_view str, ipv6_address& dest) { error parse(string_view str, ipv6_address& dest) {
using namespace detail; using namespace detail;
parser::state<string_view::iterator> res{str.begin(), str.end()};
ipv6_address_consumer f{dest}; ipv6_address_consumer f{dest};
string_parser_state res{str.begin(), str.end()};
parser::read_ipv6_address(res, f); parser::read_ipv6_address(res, f);
if (res.code == pec::success) if (res.code == pec::success)
return none; return none;
......
...@@ -54,7 +54,7 @@ error make_error(pec code) { ...@@ -54,7 +54,7 @@ error make_error(pec code) {
return {static_cast<uint8_t>(code), atom("parser")}; return {static_cast<uint8_t>(code), atom("parser")};
} }
error make_error(pec code, size_t line, size_t column) { error make_error(pec code, int32_t line, int32_t column) {
config_value::dictionary context; config_value::dictionary context;
context["line"] = line; context["line"] = line;
context["column"] = column; context["column"] = column;
......
...@@ -146,12 +146,11 @@ std::string to_string(const uri::authority_type& x) { ...@@ -146,12 +146,11 @@ std::string to_string(const uri::authority_type& x) {
} }
error parse(string_view str, uri& dest) { error parse(string_view str, uri& dest) {
detail::parse_state ps{str.begin(), str.end()}; string_parser_state ps{str.begin(), str.end()};
parse(ps, dest); parse(ps, dest);
if (ps.code == pec::success) if (ps.code == pec::success)
return none; return none;
return make_error(ps.code, static_cast<size_t>(ps.line), return make_error(ps);
static_cast<size_t>(ps.column));
} }
expected<uri> make_uri(string_view str) { expected<uri> make_uri(string_view str) {
......
...@@ -33,7 +33,7 @@ using ls = std::vector<std::string>; ...@@ -33,7 +33,7 @@ using ls = std::vector<std::string>;
namespace { namespace {
const char test_ini[] = R"( constexpr const string_view test_ini = R"(
is_server=true is_server=true
port=4242 port=4242
nodes=["sun", "venus", ] nodes=["sun", "venus", ]
...@@ -44,7 +44,7 @@ file-name = "foobar.ini" ; our file name ...@@ -44,7 +44,7 @@ file-name = "foobar.ini" ; our file name
impl = 'foo';some atom impl = 'foo';some atom
)"; )";
const char test_ini2[] = R"( constexpr const string_view test_ini2 = R"(
is_server = true is_server = true
logger = { logger = {
file-name = "foobar.ini" file-name = "foobar.ini"
...@@ -58,7 +58,6 @@ nodes = ["sun", "venus"] ...@@ -58,7 +58,6 @@ nodes = ["sun", "venus"]
)"; )";
struct fixture { struct fixture {
detail::parser::state<std::string::const_iterator> res;
config_option_set options; config_option_set options;
settings config; settings config;
...@@ -78,20 +77,18 @@ struct fixture { ...@@ -78,20 +77,18 @@ struct fixture {
CAF_TEST_FIXTURE_SCOPE(ini_consumer_tests, fixture) CAF_TEST_FIXTURE_SCOPE(ini_consumer_tests, fixture)
CAF_TEST(ini_value_consumer) { CAF_TEST(ini_value_consumer) {
std::string str = R"("hello world")"; string_view str = R"("hello world")";
detail::ini_value_consumer consumer; detail::ini_value_consumer consumer;
res.i = str.begin(); string_parser_state res{str.begin(), str.end()};
res.e = str.end();
detail::parser::read_ini_value(res, consumer); detail::parser::read_ini_value(res, consumer);
CAF_CHECK_EQUAL(res.code, pec::success); CAF_CHECK_EQUAL(res.code, pec::success);
CAF_CHECK_EQUAL(get<string>(consumer.result), "hello world"); CAF_CHECK_EQUAL(get<string>(consumer.result), "hello world");
} }
CAF_TEST(ini_consumer) { CAF_TEST(ini_consumer) {
std::string str = test_ini; string_view str = test_ini;
detail::ini_consumer consumer{options, config}; detail::ini_consumer consumer{options, config};
res.i = str.begin(); string_parser_state res{str.begin(), str.end()};
res.e = str.end();
detail::parser::read_ini(res, consumer); detail::parser::read_ini(res, consumer);
CAF_CHECK_EQUAL(res.code, pec::success); CAF_CHECK_EQUAL(res.code, pec::success);
CAF_CHECK_EQUAL(get<bool>(config, "is_server"), true); CAF_CHECK_EQUAL(get<bool>(config, "is_server"), true);
...@@ -103,12 +100,11 @@ CAF_TEST(ini_consumer) { ...@@ -103,12 +100,11 @@ CAF_TEST(ini_consumer) {
} }
CAF_TEST(simplified syntax) { CAF_TEST(simplified syntax) {
std::string str = test_ini; string_view str = test_ini;
CAF_MESSAGE("read test_ini"); CAF_MESSAGE("read test_ini");
{ {
detail::ini_consumer consumer{options, config}; detail::ini_consumer consumer{options, config};
res.i = str.begin(); string_parser_state res{str.begin(), str.end()};
res.e = str.end();
detail::parser::read_ini(res, consumer); detail::parser::read_ini(res, consumer);
CAF_CHECK_EQUAL(res.code, pec::success); CAF_CHECK_EQUAL(res.code, pec::success);
} }
...@@ -117,8 +113,7 @@ CAF_TEST(simplified syntax) { ...@@ -117,8 +113,7 @@ CAF_TEST(simplified syntax) {
CAF_MESSAGE("read test_ini2"); CAF_MESSAGE("read test_ini2");
{ {
detail::ini_consumer consumer{options, config2}; detail::ini_consumer consumer{options, config2};
res.i = str.begin(); string_parser_state res{str.begin(), str.end()};
res.e = str.end();
detail::parser::read_ini(res, consumer); detail::parser::read_ini(res, consumer);
CAF_CHECK_EQUAL(res.code, pec::success); CAF_CHECK_EQUAL(res.code, pec::success);
} }
......
...@@ -61,11 +61,11 @@ timespan operator"" _h(unsigned long long x) { ...@@ -61,11 +61,11 @@ timespan operator"" _h(unsigned long long x) {
template <class T> template <class T>
expected<T> read(string_view str) { expected<T> read(string_view str) {
T result; T result;
detail::parse_state ps{str.begin(), str.end()}; string_parser_state ps{str.begin(), str.end()};
detail::parse(ps, result); detail::parse(ps, result);
if (ps.code == pec::success) if (ps.code == pec::success)
return result; return result;
return make_error(ps.code, ps.line, ps.column); return make_error(ps);
} }
} // namespace } // namespace
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include <string> #include <string>
#include "caf/parser_state.hpp"
#include "caf/string_view.hpp"
#include "caf/variant.hpp" #include "caf/variant.hpp"
using namespace caf; using namespace caf;
...@@ -40,11 +42,9 @@ struct atom_parser_consumer { ...@@ -40,11 +42,9 @@ struct atom_parser_consumer {
using res_t = variant<pec, atom_value>; using res_t = variant<pec, atom_value>;
struct atom_parser { struct atom_parser {
res_t operator()(std::string str) { res_t operator()(string_view str) {
detail::parser::state<std::string::iterator> res;
atom_parser_consumer f; atom_parser_consumer f;
res.i = str.begin(); string_parser_state res{str.begin(), str.end()};
res.e = str.end();
detail::parser::read_atom(res, f); detail::parser::read_atom(res, f);
if (res.code == pec::success) if (res.code == pec::success)
return f.x; return f.x;
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include <string> #include <string>
#include "caf/parser_state.hpp"
#include "caf/string_view.hpp"
#include "caf/variant.hpp" #include "caf/variant.hpp"
using namespace caf; using namespace caf;
...@@ -40,11 +42,9 @@ struct bool_parser_consumer { ...@@ -40,11 +42,9 @@ struct bool_parser_consumer {
using res_t = variant<pec, bool>; using res_t = variant<pec, bool>;
struct bool_parser { struct bool_parser {
res_t operator()(std::string str) { res_t operator()(string_view str) {
detail::parser::state<std::string::iterator> res;
bool_parser_consumer f; bool_parser_consumer f;
res.i = str.begin(); string_parser_state res{str.begin(), str.end()};
res.e = str.end();
detail::parser::read_bool(res, f); detail::parser::read_bool(res, f);
if (res.code == pec::success) if (res.code == pec::success)
return f.x; return f.x;
......
...@@ -24,8 +24,9 @@ ...@@ -24,8 +24,9 @@
#include <string> #include <string>
#include "caf/detail/parser/state.hpp" #include "caf/parser_state.hpp"
#include "caf/pec.hpp" #include "caf/string_view.hpp"
#include "caf/variant.hpp"
using namespace caf; using namespace caf;
...@@ -43,7 +44,7 @@ struct double_consumer { ...@@ -43,7 +44,7 @@ struct double_consumer {
optional<double> read(string_view str) { optional<double> read(string_view str) {
double_consumer consumer; double_consumer consumer;
detail::parser::state<string_view::iterator> ps{str.begin(), str.end()}; string_parser_state ps{str.begin(), str.end()};
detail::parser::read_floating_point(ps, consumer); detail::parser::read_floating_point(ps, consumer);
if (ps.code != pec::success) if (ps.code != pec::success)
return none; return none;
......
...@@ -25,6 +25,11 @@ ...@@ -25,6 +25,11 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "caf/config_value.hpp"
#include "caf/parser_state.hpp"
#include "caf/pec.hpp"
#include "caf/string_view.hpp"
using namespace caf; using namespace caf;
namespace { namespace {
...@@ -85,11 +90,9 @@ struct ini_consumer { ...@@ -85,11 +90,9 @@ struct ini_consumer {
}; };
struct fixture { struct fixture {
expected<log_type> parse(std::string str, bool expect_success = true) { expected<log_type> parse(string_view str, bool expect_success = true) {
detail::parser::state<std::string::iterator> res;
test_consumer f; test_consumer f;
res.i = str.begin(); string_parser_state res{str.begin(), str.end()};
res.e = str.end();
detail::parser::read_ini(res, f); detail::parser::read_ini(res, f);
if ((res.code == pec::success) != expect_success) { if ((res.code == pec::success) != expect_success) {
CAF_MESSAGE("unexpected parser result state: " << res.code); CAF_MESSAGE("unexpected parser result state: " << res.code);
...@@ -105,7 +108,7 @@ log_type make_log(Ts&&... xs) { ...@@ -105,7 +108,7 @@ log_type make_log(Ts&&... xs) {
} }
// Tests basic functionality. // Tests basic functionality.
const auto ini0 = R"( constexpr const string_view ini0 = R"(
[1group] [1group]
1value=321 1value=321
[_foo] [_foo]
...@@ -204,7 +207,7 @@ const auto ini0_log = make_log( ...@@ -204,7 +207,7 @@ const auto ini0_log = make_log(
// clang-format on // clang-format on
// Tests nested parameters. // Tests nested parameters.
const auto ini1 = R"( constexpr const string_view ini1 = R"(
foo { foo {
bar = { bar = {
value1 = 1 value1 = 1
...@@ -241,11 +244,11 @@ const auto ini1_log = make_log( ...@@ -241,11 +244,11 @@ const auto ini1_log = make_log(
); );
// clang-format on // clang-format on
const auto ini2 = "#"; constexpr const string_view ini2 = "#";
const auto ini2_log = make_log(); const auto ini2_log = make_log();
const auto ini3 = "; foobar\n!"; constexpr const string_view ini3 = "; foobar\n!";
const auto ini3_log = make_log(); const auto ini3_log = make_log();
......
...@@ -27,7 +27,9 @@ ...@@ -27,7 +27,9 @@
#include "caf/detail/parser/add_ascii.hpp" #include "caf/detail/parser/add_ascii.hpp"
#include "caf/detail/parser/sub_ascii.hpp" #include "caf/detail/parser/sub_ascii.hpp"
#include "caf/expected.hpp" #include "caf/expected.hpp"
#include "caf/parser_state.hpp"
#include "caf/pec.hpp" #include "caf/pec.hpp"
#include "caf/string_view.hpp"
#include "caf/variant.hpp" #include "caf/variant.hpp"
using namespace caf; using namespace caf;
...@@ -67,11 +69,9 @@ bool operator==(const res_t& x, const res_t& y) { ...@@ -67,11 +69,9 @@ bool operator==(const res_t& x, const res_t& y) {
} }
struct numbers_parser { struct numbers_parser {
res_t operator()(std::string str) { res_t operator()(string_view str) {
detail::parser::state<std::string::iterator> res;
numbers_parser_consumer f; numbers_parser_consumer f;
res.i = str.begin(); string_parser_state res{str.begin(), str.end()};
res.e = str.end();
detail::parser::read_number(res, f); detail::parser::read_number(res, f);
if (res.code == pec::success) if (res.code == pec::success)
return f.x; return f.x;
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include <string> #include <string>
#include "caf/parser_state.hpp"
#include "caf/string_view.hpp"
#include "caf/variant.hpp" #include "caf/variant.hpp"
using namespace caf; using namespace caf;
...@@ -68,11 +70,9 @@ bool operator==(const res_t& x, const res_t& y) { ...@@ -68,11 +70,9 @@ bool operator==(const res_t& x, const res_t& y) {
} }
struct number_or_timespan_parser { struct number_or_timespan_parser {
res_t operator()(std::string str) { res_t operator()(string_view str) {
detail::parser::state<std::string::iterator> res;
number_or_timespan_parser_consumer f; number_or_timespan_parser_consumer f;
res.i = str.begin(); string_parser_state res{str.begin(), str.end()};
res.e = str.end();
detail::parser::read_number_or_timespan(res, f); detail::parser::read_number_or_timespan(res, f);
if (res.code == pec::success) if (res.code == pec::success)
return f.x; return f.x;
......
...@@ -22,8 +22,9 @@ ...@@ -22,8 +22,9 @@
#include "caf/test/dsl.hpp" #include "caf/test/dsl.hpp"
#include "caf/detail/parser/state.hpp" #include "caf/parser_state.hpp"
#include "caf/string_view.hpp" #include "caf/string_view.hpp"
#include "caf/variant.hpp"
using namespace caf; using namespace caf;
...@@ -43,7 +44,7 @@ struct signed_integer_consumer { ...@@ -43,7 +44,7 @@ struct signed_integer_consumer {
template <class T> template <class T>
optional<T> read(string_view str) { optional<T> read(string_view str) {
signed_integer_consumer<T> consumer; signed_integer_consumer<T> consumer;
detail::parser::state<string_view::iterator> ps{str.begin(), str.end()}; string_parser_state ps{str.begin(), str.end()};
detail::parser::read_signed_integer(ps, consumer); detail::parser::read_signed_integer(ps, consumer);
if (ps.code != pec::success) if (ps.code != pec::success)
return none; return none;
...@@ -53,7 +54,7 @@ optional<T> read(string_view str) { ...@@ -53,7 +54,7 @@ optional<T> read(string_view str) {
template <class T> template <class T>
bool underflow(string_view str) { bool underflow(string_view str) {
signed_integer_consumer<T> consumer; signed_integer_consumer<T> consumer;
detail::parser::state<string_view::iterator> ps{str.begin(), str.end()}; string_parser_state ps{str.begin(), str.end()};
detail::parser::read_signed_integer(ps, consumer); detail::parser::read_signed_integer(ps, consumer);
return ps.code == pec::integer_underflow; return ps.code == pec::integer_underflow;
} }
...@@ -61,7 +62,7 @@ bool underflow(string_view str) { ...@@ -61,7 +62,7 @@ bool underflow(string_view str) {
template <class T> template <class T>
bool overflow(string_view str) { bool overflow(string_view str) {
signed_integer_consumer<T> consumer; signed_integer_consumer<T> consumer;
detail::parser::state<string_view::iterator> ps{str.begin(), str.end()}; string_parser_state ps{str.begin(), str.end()};
detail::parser::read_signed_integer(ps, consumer); detail::parser::read_signed_integer(ps, consumer);
return ps.code == pec::integer_overflow; return ps.code == pec::integer_overflow;
} }
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include <string> #include <string>
#include "caf/parser_state.hpp"
#include "caf/string_view.hpp"
#include "caf/variant.hpp" #include "caf/variant.hpp"
using namespace caf; using namespace caf;
...@@ -40,11 +42,9 @@ struct string_parser_consumer { ...@@ -40,11 +42,9 @@ struct string_parser_consumer {
using res_t = variant<pec, std::string>; using res_t = variant<pec, std::string>;
struct string_parser { struct string_parser {
res_t operator()(std::string str) { res_t operator()(string_view str) {
detail::parser::state<std::string::iterator> res;
string_parser_consumer f; string_parser_consumer f;
res.i = str.begin(); string_parser_state res{str.begin(), str.end()};
res.e = str.end();
detail::parser::read_string(res, f); detail::parser::read_string(res, f);
if (res.code == pec::success) if (res.code == pec::success)
return f.x; return f.x;
......
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
#include <chrono> #include <chrono>
#include "caf/parser_state.hpp"
#include "caf/string_view.hpp"
#include "caf/variant.hpp"
using namespace caf; using namespace caf;
namespace { namespace {
...@@ -62,7 +66,7 @@ struct timespan_consumer { ...@@ -62,7 +66,7 @@ struct timespan_consumer {
optional<timespan> read(string_view str) { optional<timespan> read(string_view str) {
timespan_consumer consumer; timespan_consumer consumer;
detail::parser::state<string_view::iterator> ps{str.begin(), str.end()}; string_parser_state ps{str.begin(), str.end()};
detail::parser::read_timespan(ps, consumer); detail::parser::read_timespan(ps, consumer);
if (ps.code != pec::success) if (ps.code != pec::success)
return none; return none;
......
...@@ -22,8 +22,9 @@ ...@@ -22,8 +22,9 @@
#include "caf/test/dsl.hpp" #include "caf/test/dsl.hpp"
#include "caf/detail/parser/state.hpp" #include "caf/parser_state.hpp"
#include "caf/string_view.hpp" #include "caf/string_view.hpp"
#include "caf/variant.hpp"
using namespace caf; using namespace caf;
...@@ -43,7 +44,7 @@ struct unsigned_integer_consumer { ...@@ -43,7 +44,7 @@ struct unsigned_integer_consumer {
template <class T> template <class T>
optional<T> read(string_view str) { optional<T> read(string_view str) {
unsigned_integer_consumer<T> consumer; unsigned_integer_consumer<T> consumer;
detail::parser::state<string_view::iterator> ps{str.begin(), str.end()}; string_parser_state ps{str.begin(), str.end()};
detail::parser::read_unsigned_integer(ps, consumer); detail::parser::read_unsigned_integer(ps, consumer);
if (ps.code != pec::success) if (ps.code != pec::success)
return none; return none;
...@@ -53,7 +54,7 @@ optional<T> read(string_view str) { ...@@ -53,7 +54,7 @@ optional<T> read(string_view str) {
template <class T> template <class T>
bool overflow(string_view str) { bool overflow(string_view str) {
unsigned_integer_consumer<T> consumer; unsigned_integer_consumer<T> consumer;
detail::parser::state<string_view::iterator> ps{str.begin(), str.end()}; string_parser_state ps{str.begin(), str.end()};
detail::parser::read_unsigned_integer(ps, consumer); detail::parser::read_unsigned_integer(ps, consumer);
return ps.code == pec::integer_overflow; return ps.code == pec::integer_overflow;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment