Commit d15b8699 authored by Dominik Charousset's avatar Dominik Charousset

Integrate range parsing into the INI parser

parent bda7b361
......@@ -71,8 +71,9 @@ void read_ini_comment(State& ps, Consumer&&) {
// clang-format on
}
template <class State, class Consumer>
void read_ini_value(State& ps, Consumer&& consumer);
template <class State, class Consumer, class InsideList = std::false_type>
void read_ini_value(State& ps, Consumer&& consumer,
InsideList inside_list = {});
template <class State, class Consumer>
void read_ini_list(State& ps, Consumer&& consumer) {
......@@ -85,7 +86,7 @@ void read_ini_list(State& ps, Consumer&& consumer) {
transition(before_value, " \t\n")
transition(done, ']', consumer.end_list())
fsm_epsilon(read_ini_comment(ps, consumer), before_value, ';')
fsm_epsilon(read_ini_value(ps, consumer), after_value)
fsm_epsilon(read_ini_value(ps, consumer, std::true_type{}), after_value)
}
state(after_value) {
transition(after_value, " \t\n")
......@@ -183,8 +184,8 @@ void read_ini_uri(State& ps, Consumer&& consumer) {
// clang-format on
}
template <class State, class Consumer>
void read_ini_value(State& ps, Consumer&& consumer) {
template <class State, class Consumer, class InsideList>
void read_ini_value(State& ps, Consumer&& consumer, InsideList inside_list) {
// clang-format off
start();
state(init) {
......@@ -192,7 +193,8 @@ void read_ini_value(State& ps, Consumer&& consumer) {
fsm_epsilon(read_atom(ps, consumer), done, '\'')
fsm_epsilon(read_number(ps, consumer), done, '.')
fsm_epsilon(read_bool(ps, consumer), done, "ft")
fsm_epsilon(read_number_or_timespan(ps, consumer), done, "0123456789+-")
fsm_epsilon(read_number_or_timespan(ps, consumer, inside_list),
done, "0123456789+-")
fsm_epsilon(read_ini_uri(ps, consumer), done, '<')
fsm_transition(read_ini_list(ps, consumer.begin_list()), done, '[')
fsm_transition(read_ini_map(ps, consumer.begin_map()), done, '{')
......
......@@ -42,19 +42,34 @@ namespace caf::detail::parser {
/// Reads a number or a duration, i.e., on success produces an `int64_t`, a
/// `double`, or a `timespan`.
template <class State, class Consumer>
void read_number_or_timespan(State& ps, Consumer& consumer) {
template <class State, class Consumer, class EnableRange = std::false_type>
void read_number_or_timespan(State& ps, Consumer& consumer,
EnableRange enable_range = {}) {
using namespace std::chrono;
struct interim_consumer {
size_t invocations = 0;
Consumer* outer = nullptr;
variant<none_t, int64_t, double> interim;
void value(int64_t x) {
switch (++invocations) {
case 1:
interim = x;
break;
case 2:
CAF_ASSERT(holds_alternative<int64_t>(interim));
outer->value(get<int64_t>(interim));
interim = none;
[[fallthrough]];
default:
outer->value(x);
}
}
void value(double x) {
interim = x;
}
};
interim_consumer ic;
ic.outer = &consumer;
auto has_int = [&] { return holds_alternative<int64_t>(ic.interim); };
auto has_dbl = [&] { return holds_alternative<double>(ic.interim); };
auto get_int = [&] { return get<int64_t>(ic.interim); };
......@@ -66,10 +81,11 @@ void read_number_or_timespan(State& ps, Consumer& consumer) {
consumer.value(get_int());
}
});
static constexpr std::true_type enable_float = std::true_type{};
// clang-format off
start();
state(init) {
fsm_epsilon(read_number(ps, ic), has_number)
fsm_epsilon(read_number(ps, ic, enable_float, enable_range), has_number)
}
term_state(has_number) {
epsilon_if(has_int(), has_integer)
......
......@@ -126,8 +126,9 @@ some-other-bool=false
some-list=[
; here we have some list entries
123,
1..3,
23 ; twenty-three!
,
,2..4..2,
"abc",
'def', ; some comment and a trailing comma
]
......@@ -179,7 +180,12 @@ const auto ini0_log = make_log(
"key: some-list",
"[",
"value (integer): 123",
"value (integer): 1",
"value (integer): 2",
"value (integer): 3",
"value (integer): 23",
"value (integer): 2",
"value (integer): 4",
"value (string): \"abc\"",
"value (atom): 'def'",
"]",
......
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