diff --git a/peglib.h b/peglib.h index 7eda33f..b4fffe6 100644 --- a/peglib.h +++ b/peglib.h @@ -461,7 +461,7 @@ struct SemanticValues : protected std::vector { // Input text const char *path = nullptr; const char *ss = nullptr; - const std::vector *source_line_index = nullptr; + std::function &()> source_line_index; // Matched string std::string_view sv() const { return sv_; } @@ -473,7 +473,7 @@ struct SemanticValues : protected std::vector { // Line number and column at which the matched string is std::pair line_info() const { - const auto &idx = *source_line_index; + auto &idx = source_line_index(); auto cur = static_cast(std::distance(ss, sv_.data())); auto it = std::lower_bound( @@ -560,7 +560,7 @@ private: /* * Semantic action */ -template std::any call(F fn, Args &&...args) { +template std::any call(F fn, Args &&... args) { using R = decltype(fn(std::forward(args)...)); if constexpr (std::is_void::value) { fn(std::forward(args)...); @@ -838,11 +838,6 @@ public: cache_success(enablePackratParsing ? def_count * (l + 1) : 0), tracer_enter(tracer_enter), tracer_leave(tracer_leave), log(log) { - for (size_t pos = 0; pos < l; pos++) { - if (s[pos] == '\n') { source_line_index.push_back(pos); } - } - source_line_index.push_back(l); - args_stack.resize(1); push_capture_scope(); @@ -905,7 +900,16 @@ public: auto &vs = *value_stack[value_stack_size++]; vs.path = path; vs.ss = s; - vs.source_line_index = &source_line_index; + vs.source_line_index = [&]() -> const std::vector & { + if (source_line_index.empty()) { + for (size_t pos = 0; pos < l; pos++) { + if (s[pos] == '\n') { source_line_index.push_back(pos); } + } + source_line_index.push_back(l); + } + return source_line_index; + }; + return vs; } @@ -976,7 +980,7 @@ public: class Sequence : public Ope { public: template - Sequence(const Args &...args) + Sequence(const Args &... args) : opes_{static_cast>(args)...} {} Sequence(const std::vector> &opes) : opes_(opes) {} Sequence(std::vector> &&opes) : opes_(opes) {} @@ -1019,7 +1023,7 @@ public: class PrioritizedChoice : public Ope { public: template - PrioritizedChoice(bool for_label, const Args &...args) + PrioritizedChoice(bool for_label, const Args &... args) : opes_{static_cast>(args)...}, for_label_(for_label) {} PrioritizedChoice(const std::vector> &opes) @@ -1577,16 +1581,16 @@ public: /* * Factories */ -template std::shared_ptr seq(Args &&...args) { +template std::shared_ptr seq(Args &&... args) { return std::make_shared(static_cast>(args)...); } -template std::shared_ptr cho(Args &&...args) { +template std::shared_ptr cho(Args &&... args) { return std::make_shared( false, static_cast>(args)...); } -template std::shared_ptr cho4label_(Args &&...args) { +template std::shared_ptr cho4label_(Args &&... args) { return std::make_shared( true, static_cast>(args)...); } @@ -2430,24 +2434,29 @@ inline size_t parse_literal(const char *s, size_t n, SemanticValues &vs, } // Word check - SemanticValues dummy_vs; - Context dummy_c(nullptr, c.s, c.l, 0, nullptr, nullptr, false, nullptr, - nullptr, nullptr); - std::any dummy_dt; + if (c.wordOpe) { + std::call_once(init_is_word, [&]() { + SemanticValues dummy_vs; + Context dummy_c(nullptr, c.s, c.l, 0, nullptr, nullptr, false, nullptr, + nullptr, nullptr); + std::any dummy_dt; - std::call_once(init_is_word, [&]() { - if (c.wordOpe) { auto len = c.wordOpe->parse(lit.data(), lit.size(), dummy_vs, dummy_c, dummy_dt); is_word = success(len); - } - }); + }); + + if (is_word) { + SemanticValues dummy_vs; + Context dummy_c(nullptr, c.s, c.l, 0, nullptr, nullptr, false, nullptr, + nullptr, nullptr); + std::any dummy_dt; - if (is_word) { - NotPredicate ope(c.wordOpe); - auto len = ope.parse(s + i, n - i, dummy_vs, dummy_c, dummy_dt); - if (fail(len)) { return len; } - i += len; + NotPredicate ope(c.wordOpe); + auto len = ope.parse(s + i, n - i, dummy_vs, dummy_c, dummy_dt); + if (fail(len)) { return len; } + i += len; + } } // Skip whiltespace