diff --git a/peglib.h b/peglib.h index c663dbd..8a9344c 100644 --- a/peglib.h +++ b/peglib.h @@ -459,11 +459,15 @@ inline constexpr unsigned int operator"" _(const char *s, size_t l) { /* * Semantic values */ +class Context; + struct SemanticValues : protected std::vector { + SemanticValues() = default; + SemanticValues(Context *c): c_(c) {} + // Input text const char *path = nullptr; const char *ss = nullptr; - std::function &()> source_line_index; // Matched string std::string_view sv() const { return sv_; } @@ -553,6 +557,9 @@ private: friend class Holder; friend class PrecedenceClimbing; + const std::vector &source_line_index() const; + + Context *c_ = nullptr; std::string_view sv_; size_t choice_count_ = 0; size_t choice_ = 0; @@ -773,7 +780,6 @@ private: /* * Context */ -class Context; class Ope; class Definition; @@ -882,7 +888,7 @@ public: SemanticValues &push() { assert(value_stack_size <= value_stack.size()); if (value_stack_size == value_stack.size()) { - value_stack.emplace_back(std::make_shared()); + value_stack.emplace_back(std::make_shared(this)); } else { auto &vs = *value_stack[value_stack_size]; if (!vs.empty()) { @@ -898,15 +904,6 @@ public: auto &vs = *value_stack[value_stack_size++]; vs.path = path; vs.ss = s; - 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; } @@ -2469,6 +2466,19 @@ inline size_t parse_literal(const char *s, size_t n, SemanticValues &vs, return i; } +inline const std::vector &SemanticValues::source_line_index() const { + if (!c_) { + std::vector(); + } + if (c_->source_line_index.empty()) { + for (size_t pos = 0; pos < c_->l; pos++) { + if (c_->s[pos] == '\n') { c_->source_line_index.push_back(pos); } + } + c_->source_line_index.push_back(c_->l); + } + return c_->source_line_index; +} + inline void Context::set_error_pos(const char *a_s, const char *literal) { if (log) { if (error_info.error_pos <= a_s) {