xo-parser: refactor: xtract exprstatestack from parser

This commit is contained in:
Roland Conybeare 2024-08-01 10:32:23 +10:00
commit a5bd857efd
2 changed files with 76 additions and 28 deletions

View file

@ -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<exprstate> 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<exprstate> stack_;
exprstatestack xs_stack_;
}; /*parser*/

View file

@ -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 << "<exprstatestack"
<< xtag("size", stack_.size())
<< std::endl;
for (std::size_t i = 0, z = stack_.size(); i < z; ++i) {
os << " [" << z-i-1 << "] "
<< stack_[i]
<< std::endl;
}
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 << "<parser"
<< xtag("stack", stack_.size())
<< std::endl;
for (std::size_t i = 0, z = stack_.size(); i < z; ++i) {
os << " [" << i << "] "
<< stack_[i]
<< std::endl;
}
xs_stack_.print(os);
os << ">" << std::endl;
}