diff --git a/include/xo/parser/parser.hpp b/include/xo/parser/parser.hpp index 11a3a2e2..b81b5ff3 100644 --- a/include/xo/parser/parser.hpp +++ b/include/xo/parser/parser.hpp @@ -282,6 +282,45 @@ namespace xo { return os; } + /** @class exprstatestack + * @brief A stack of exprstate objects + **/ + class exprstatestack { + public: + exprstatestack() {} + + bool empty() const { return stack_.empty(); } + std::size_t size() const { return stack_.size(); } + + exprstate & top_exprstate(); + void push_exprstate(const exprstate & exs); + void pop_exprstate(); + + /** relative to top-of-stack. + * 0 -> top (last in), z-1 -> bottom (first in) + **/ + exprstate & operator[](std::size_t i) { + std::size_t z = stack_.size(); + + assert(i < z); + + return stack_[z - i - 1]; + } + + const exprstate & operator[](std::size_t i) const { + std::size_t z = stack_.size(); + + assert(i < z); + + return stack_[z - i - 1]; + } + + void print (std::ostream & os) const; + + private: + std::vector stack_; + }; + /** schematica parser * * Examples: @@ -400,17 +439,17 @@ namespace xo { parser() = default; /** for diagnostics: number of entries in parser stack **/ - std::size_t stack_size() const { return stack_.size(); } + std::size_t stack_size() const { return xs_stack_.size(); } /** for diagnostics: exprstatetype at level @p i * (taken relative to top of stack) * * @pre 0 <= i < stack_size **/ exprstatetype i_exstype(std::size_t i) const { - std::size_t z = stack_.size(); + std::size_t z = xs_stack_.size(); if (i < z) { - return stack_[(z - 1) - i].exs_type(); + return xs_stack_[i].exs_type(); } /* out of bounds */ @@ -433,11 +472,6 @@ namespace xo { /** print human-readable representation on stream @p os **/ void print(std::ostream & os) const; - private: - exprstate & top_exprstate(); - void push_exprstate(const exprstate & exs); - void pop_exprstate(); - private: /** state recording state associated with enclosing expressions. * @@ -448,7 +482,7 @@ namespace xo { * - bottom of stack is stack_[0] * - top of stack is stack_[N-1] **/ - std::vector stack_; + exprstatestack xs_stack_; }; /*parser*/ diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp index 312b38f0..a4f93b70 100644 --- a/src/parser/parser.cpp +++ b/src/parser/parser.cpp @@ -625,10 +625,10 @@ namespace xo { os << ">"; } - // ----- parser ----- + // ----- exprstatestack ----- exprstate & - parser::top_exprstate() { + exprstatestack::top_exprstate() { std::size_t z = stack_.size(); if (z == 0) { @@ -640,7 +640,7 @@ namespace xo { } void - parser::push_exprstate(const exprstate & exs) { + exprstatestack::push_exprstate(const exprstate & exs) { std::size_t z = stack_.size(); stack_.resize(z+1); @@ -649,16 +649,33 @@ namespace xo { } void - parser::pop_exprstate() { + exprstatestack::pop_exprstate() { std::size_t z = stack_.size(); if (z > 0) stack_.resize(z-1); } + void + exprstatestack::print(std::ostream & os) const { + os << "" << std::endl; + } + + // ----- parser ----- + void parser::begin_translation_unit() { - this->push_exprstate + xs_stack_.push_exprstate (exprstate::expect_toplevel_expression_sequence()); } @@ -668,7 +685,7 @@ namespace xo { constexpr bool c_debug_flag = true; scope log(XO_DEBUG(c_debug_flag)); - if (stack_.empty()) { + if (xs_stack_.empty()) { throw std::runtime_error(tostr("parser::include_token", ": parser not expecting input" "(call parser.begin_translation_unit()..?)", @@ -676,7 +693,7 @@ namespace xo { } /* stack_ is non-empty */ - expraction action = this->top_exprstate().on_input(tk); + expraction action = xs_stack_.top_exprstate().on_input(tk); /* loop until reach parsing state that requires more input */ for (;;) { @@ -690,23 +707,25 @@ namespace xo { return action.expr_ir().expr(); case expractiontype::pop: - this->pop_exprstate(); + xs_stack_.pop_exprstate(); - if (stack_.empty()) { + if (xs_stack_.empty()) { throw std::runtime_error(tostr("parser::include_token", ": pop leaves empty stack")); } - action = this->top_exprstate().on_exprir(action.expr_ir()); + action = (xs_stack_ + .top_exprstate() + .on_exprir(action.expr_ir())); break; case expractiontype::push1: - this->push_exprstate(action.push_exs1()); + xs_stack_.push_exprstate(action.push_exs1()); return nullptr; case expractiontype::push2: - this->push_exprstate(action.push_exs1()); - this->push_exprstate(action.push_exs2()); + xs_stack_.push_exprstate(action.push_exs1()); + xs_stack_.push_exprstate(action.push_exs2()); return nullptr; case expractiontype::invalid: @@ -721,14 +740,9 @@ namespace xo { void parser::print(std::ostream & os) const { os << "" << std::endl; }