From 81bbc080fd961307b17187b63c94fae654b47fa5 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Tue, 22 Jul 2025 23:09:55 -0500 Subject: [PATCH] xo-reader: refactor to simplify parser+parserstatemachine --- xo-reader/include/xo/reader/envframestack.hpp | 2 +- xo-reader/include/xo/reader/parser.hpp | 35 +++------- .../include/xo/reader/parserstatemachine.hpp | 39 ++++++----- xo-reader/src/reader/define_xs.cpp | 1 + xo-reader/src/reader/envframestack.cpp | 2 +- xo-reader/src/reader/exprseq_xs.cpp | 4 +- xo-reader/src/reader/exprstate.cpp | 11 ++- xo-reader/src/reader/parser.cpp | 43 ++++-------- xo-reader/src/reader/parserstatemachine.cpp | 69 ++++++++----------- .../src/reader/pretty_parserstatemachine.cpp | 8 +-- 10 files changed, 85 insertions(+), 129 deletions(-) diff --git a/xo-reader/include/xo/reader/envframestack.hpp b/xo-reader/include/xo/reader/envframestack.hpp index 1f00a3f3..9e6a1d6f 100644 --- a/xo-reader/include/xo/reader/envframestack.hpp +++ b/xo-reader/include/xo/reader/envframestack.hpp @@ -36,7 +36,7 @@ namespace xo { **/ void upsert(bp target); - bp top_envframe(); + bp top_envframe() const; void push_envframe(const rp & x); rp pop_envframe(); diff --git a/xo-reader/include/xo/reader/parser.hpp b/xo-reader/include/xo/reader/parser.hpp index 5ac3cec9..c45278a1 100644 --- a/xo-reader/include/xo/reader/parser.hpp +++ b/xo-reader/include/xo/reader/parser.hpp @@ -8,6 +8,7 @@ #include "exprstatestack.hpp" #include "envframestack.hpp" #include "parser_result.hpp" +#include "parserstatemachine.hpp" #include namespace xo { @@ -167,17 +168,17 @@ namespace xo { bool is_at_toplevel() const { return stack_size() == 0; } /** for diagnostics: number of entries in parser stack **/ - std::size_t stack_size() const { return xs_stack_.size(); } + std::size_t stack_size() const { return psm_.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 = xs_stack_.size(); + std::size_t z = psm_.xs_stack_.size(); if (i < z) { - return xs_stack_[i]->exs_type(); + return psm_.xs_stack_[i]->exs_type(); } /* out of bounds */ @@ -185,10 +186,10 @@ namespace xo { } exprstate const * i_exstate(std::size_t i) const { - std::size_t z = xs_stack_.size(); + std::size_t z = psm_.xs_stack_.size(); if (i < z) { - return xs_stack_[i].get(); + return psm_.xs_stack_[i].get(); } /* out of bounds */ @@ -229,28 +230,8 @@ namespace xo { void print(std::ostream & os) const; private: - /** state recording state associated with enclosing expressions. - * - * Note: at least asof c++23, the std::stack api doesn't support access - * to members other than the top. - * - * for stack with N elements (N = stack_.size()): - * - bottom of stack is stack_[0] - * - top of stack is stack_[N-1] - **/ - exprstatestack xs_stack_; - - /** environment frames for lexical context. - * push a frame on each nested lambda; - * pop when lambda body goes out of scope - **/ - envframestack env_stack_; - - /** parser result state **/ - parser_result result_; - - /** enable/disable debug logging **/ - bool debug_flag_; + /** state machine **/ + parserstatemachine psm_; }; /*parser*/ inline std::ostream & diff --git a/xo-reader/include/xo/reader/parserstatemachine.hpp b/xo-reader/include/xo/reader/parserstatemachine.hpp index 1bf0905c..2b8340e9 100644 --- a/xo-reader/include/xo/reader/parserstatemachine.hpp +++ b/xo-reader/include/xo/reader/parserstatemachine.hpp @@ -6,6 +6,7 @@ #pragma once #include "exprstate.hpp" +#include "exprstatestack.hpp" #include "envframestack.hpp" #include "parser_result.hpp" @@ -26,14 +27,8 @@ namespace xo { using token_type = token; public: - parserstatemachine(exprstatestack * p_stack, - envframestack * p_env_stack, - parser_result * p_result, - bool debug_flag) - : p_stack_{p_stack}, - p_env_stack_{p_env_stack}, - p_result_{p_result}, - debug_flag_{debug_flag} + explicit parserstatemachine(bool debug_flag) + : debug_flag_{debug_flag} {} //const parser_result & result() const { return result_; } @@ -65,7 +60,7 @@ namespace xo { /** @return pop innermost environment frame and return it **/ rp pop_envframe(); /** @return number of stacked environment frames **/ - size_t env_stack_size() const { return p_env_stack_->size(); } + size_t env_stack_size() const { return env_stack_.size(); } // ----- parsing outputs ----- @@ -92,16 +87,24 @@ namespace xo { void print(std::ostream & os) const; public: - /** stack of incomplete parser work. - * generally speaking, push when to start new work for nested content; - * pop when work complete + /** state recording state associated with enclosing expressions. + * + * Note: at least asof c++23, the std::stack api doesn't support access + * to members other than the top. + * + * for stack with N elements (N = stack_.size()): + * - bottom of stack is stack_[0] + * - top of stack is stack_[N-1] **/ - exprstatestack * p_stack_ = nullptr; - /** stack of environment frames, one for each enclosing lambda **/ - envframestack * p_env_stack_ = nullptr; - /** parser result object **/ - parser_result * p_result_ = nullptr; - /** enable debug logging **/ + exprstatestack xs_stack_; + /** environment frames for lexical context. + * push a frame on each nested lambda; + * pop when lambda body goes out of scope + **/ + envframestack env_stack_; + /** parser result state **/ + parser_result result_; + /** enable/disable debug logging **/ bool debug_flag_ = false; }; diff --git a/xo-reader/src/reader/define_xs.cpp b/xo-reader/src/reader/define_xs.cpp index 8d91ea9d..502d5dc5 100644 --- a/xo-reader/src/reader/define_xs.cpp +++ b/xo-reader/src/reader/define_xs.cpp @@ -126,6 +126,7 @@ namespace xo { rp def_expr = this->def_expr_; this->defxs_type_ = defexprstatetype::def_6; + return; } constexpr const char * c_self_name = "define_xs::on_expr"; diff --git a/xo-reader/src/reader/envframestack.cpp b/xo-reader/src/reader/envframestack.cpp index 97bca077..9db3146a 100644 --- a/xo-reader/src/reader/envframestack.cpp +++ b/xo-reader/src/reader/envframestack.cpp @@ -13,7 +13,7 @@ namespace xo { namespace scm { bp - envframestack::top_envframe() { + envframestack::top_envframe() const { std::size_t z = stack_.size(); if (z == 0) { diff --git a/xo-reader/src/reader/exprseq_xs.cpp b/xo-reader/src/reader/exprseq_xs.cpp index 03399cca..b689831e 100644 --- a/xo-reader/src/reader/exprseq_xs.cpp +++ b/xo-reader/src/reader/exprseq_xs.cpp @@ -190,7 +190,7 @@ namespace xo { * arbitrary number of expressions. */ - *(p_psm->p_result_) = parser_result::expression(expr.promote()); + p_psm->result_ = parser_result::expression(expr.promote()); } void @@ -203,7 +203,7 @@ namespace xo { * semicolons are sometimes mandatory to avoid ambiguity. */ - *(p_psm->p_result_) = parser_result::expression(expr.promote()); + p_psm->result_ = parser_result::expression(expr.promote()); } } /*namespace scm*/ diff --git a/xo-reader/src/reader/exprstate.cpp b/xo-reader/src/reader/exprstate.cpp index 57d0c22f..d4b5e34a 100644 --- a/xo-reader/src/reader/exprstate.cpp +++ b/xo-reader/src/reader/exprstate.cpp @@ -321,8 +321,7 @@ namespace xo { exprstate::on_bool_token(const token_type & tk, parserstatemachine * p_psm) { - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(p_psm->debug_flag())); constexpr const char * c_self_name = "exprstate::on_bool"; const char * exp = get_expect_str(); @@ -334,8 +333,7 @@ namespace xo { exprstate::on_i64_token(const token_type & tk, parserstatemachine * p_psm) { - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(p_psm->debug_flag())); constexpr const char * c_self_name = "exprstate::on_i64"; const char * exp = get_expect_str(); @@ -347,8 +345,7 @@ namespace xo { exprstate::on_f64_token(const token_type & tk, parserstatemachine * p_psm) { - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); + scope log(XO_DEBUG(p_psm->debug_flag())); constexpr const char * c_self_name = "exprstate::on_f64"; const char * exp = get_expect_str(); @@ -364,7 +361,7 @@ namespace xo { scope log(XO_DEBUG(c_debug_flag)); log && log(xtag("tk", tk)); log && log(xtag("state", *this)); - log && log(xtag("psm", *p_psm)); + log && log(xtag("psm", p_psm)); log && log(xtag("proofoflogging", true)); switch (tk.tk_type()) { diff --git a/xo-reader/src/reader/parser.cpp b/xo-reader/src/reader/parser.cpp index 5e9aed09..83615867 100644 --- a/xo-reader/src/reader/parser.cpp +++ b/xo-reader/src/reader/parser.cpp @@ -18,50 +18,35 @@ namespace xo { using xo::ast::Expression; - //using xo::ast::GlobalEnv; using xo::ast::LocalEnv; - //using xo::ast::DefineExpr; - //using xo::ast::ConvertExpr; - //using xo::ast::Constant; - //using xo::reflect::Reflect; using xo::reflect::TypeDescr; namespace scm { // ----- parser ----- parser::parser(bool debug_flag) - : xs_stack_{}, env_stack_{}, result_{}, debug_flag_{debug_flag} + : psm_{debug_flag} { /* top-level environment. initially empty */ rp toplevel_env = LocalEnv::make_empty(); - this->env_stack_.push_envframe(toplevel_env); + this->psm_.env_stack_.push_envframe(toplevel_env); } bool parser::has_incomplete_expr() const { /* (don't count toplevel exprseq) */ - return xs_stack_.size() > 1; + return psm_.xs_stack_.size() > 1; } void parser::begin_interactive_session() { - parserstatemachine psm(&xs_stack_, - &env_stack_, - &result_, - debug_flag_); - - exprseq_xs::start(exprseqtype::toplevel_interactive, &psm); + exprseq_xs::start(exprseqtype::toplevel_interactive, &psm_); } void parser::begin_translation_unit() { - parserstatemachine psm(&xs_stack_, - &env_stack_, - &result_, - debug_flag_); - - exprseq_xs::start(exprseqtype::toplevel_batch, &psm); + exprseq_xs::start(exprseqtype::toplevel_batch, &psm_); } const parser_result & @@ -70,7 +55,7 @@ namespace xo { constexpr bool c_debug_flag = true; scope log(XO_DEBUG(c_debug_flag), xtag("tk", tk)); - if (xs_stack_.empty()) { + if (psm_.xs_stack_.empty()) { throw std::runtime_error(tostr("parser::include_token", ": parser not expecting input" "(call parser.begin_translation_unit()..?)", @@ -79,21 +64,19 @@ namespace xo { /* stack_ is non-empty */ - log && log(xtag("top", xs_stack_.top_exprstate())); + log && log(xtag("top", psm_.xs_stack_.top_exprstate())); - parserstatemachine psm(&xs_stack_, &env_stack_, &result_, debug_flag_); + psm_.xs_stack_.top_exprstate().on_input(tk, &psm_); - xs_stack_.top_exprstate().on_input(tk, &psm); - - return result_; + return psm_.result_; } /*include_token*/ void parser::reset_to_idle_toplevel() { - xs_stack_.reset_to_toplevel(); - env_stack_.reset_to_toplevel(); - result_ = parser_result::none(); + psm_.xs_stack_.reset_to_toplevel(); + psm_.env_stack_.reset_to_toplevel(); + psm_.result_ = parser_result::none(); } /*discard_current_state*/ void @@ -101,7 +84,7 @@ namespace xo { os << "" << std::endl; } diff --git a/xo-reader/src/reader/parserstatemachine.cpp b/xo-reader/src/reader/parserstatemachine.cpp index bb53cde4..b3121cc5 100644 --- a/xo-reader/src/reader/parserstatemachine.cpp +++ b/xo-reader/src/reader/parserstatemachine.cpp @@ -17,32 +17,32 @@ namespace xo { namespace scm { bp parserstatemachine::lookup_var(const std::string & x) const { - return p_env_stack_->lookup(x); + return env_stack_.lookup(x); } void parserstatemachine::upsert_var(bp x) { - p_env_stack_->upsert(x); + env_stack_.upsert(x); } std::unique_ptr parserstatemachine::pop_exprstate() { - return p_stack_->pop_exprstate(); + return xs_stack_.pop_exprstate(); } exprstate & parserstatemachine::top_exprstate() { - return p_stack_->top_exprstate(); + return xs_stack_.top_exprstate(); } void parserstatemachine::push_exprstate(std::unique_ptr x) { - p_stack_->push_exprstate(std::move(x)); + xs_stack_.push_exprstate(std::move(x)); } bp parserstatemachine::top_envframe() const { - return p_env_stack_->top_envframe(); + return env_stack_.top_envframe(); } void @@ -52,7 +52,7 @@ namespace xo { log && log(xtag("frame", x)); - p_env_stack_->push_envframe(x); + env_stack_.push_envframe(x); } rp @@ -60,7 +60,7 @@ namespace xo { constexpr bool c_debug_flag = true; scope log(XO_DEBUG(c_debug_flag)); - return p_env_stack_->pop_envframe(); + return env_stack_.pop_envframe(); } void @@ -70,10 +70,9 @@ namespace xo { scope log(XO_DEBUG(c_debug_flag)); log && log(xtag("x", x), - xtag("psm", *this)); + xtag("psm", this)); - this->p_stack_ - ->top_exprstate().on_expr(x, this); + this->xs_stack_.top_exprstate().on_expr(x, this); } void @@ -83,12 +82,11 @@ namespace xo { scope log(XO_DEBUG(c_debug_flag)); log && log(xtag("x", x), - xtag("psm", *this)); + xtag("psm", this)); - assert(!this->p_stack_->empty()); + assert(!this->xs_stack_.empty()); - this->p_stack_ - ->top_exprstate().on_expr_with_semicolon(x, this); + this->xs_stack_.top_exprstate().on_expr_with_semicolon(x, this); } void @@ -98,10 +96,9 @@ namespace xo { scope log(XO_DEBUG(c_debug_flag)); log && log(xtag("x", x), - xtag("psm", *this)); + xtag("psm", this)); - this->p_stack_ - ->top_exprstate().on_symbol(x, this); + this->xs_stack_.top_exprstate().on_symbol(x, this); } void @@ -111,10 +108,9 @@ namespace xo { scope log(XO_DEBUG(c_debug_flag)); log && log(xtag("tk", tk), - xtag("psm", *this)); + xtag("psm", this)); - this->p_stack_ - ->top_exprstate().on_semicolon_token(tk, this); + this->xs_stack_.top_exprstate().on_semicolon_token(tk, this); } void @@ -124,10 +120,9 @@ namespace xo { scope log(XO_DEBUG(c_debug_flag)); log && log(xtag("tk", tk), - xtag("psm", *this)); + xtag("psm", this)); - this->p_stack_ - ->top_exprstate().on_operator_token(tk, this); + this->xs_stack_.top_exprstate().on_operator_token(tk, this); } void @@ -137,10 +132,9 @@ namespace xo { scope log(XO_DEBUG(c_debug_flag)); log && log(xtag("tk", tk), - xtag("psm", *this)); + xtag("psm", this)); - this->p_stack_ - ->top_exprstate().on_leftbrace_token(tk, this); + this->xs_stack_.top_exprstate().on_leftbrace_token(tk, this); } void @@ -149,10 +143,9 @@ namespace xo { scope log(XO_DEBUG(debug_flag_)); log && log(xtag("tk", tk), - xtag("psm", *this)); + xtag("psm", this)); - this->p_stack_ - ->top_exprstate().on_rightbrace_token(tk, this); + this->xs_stack_.top_exprstate().on_rightbrace_token(tk, this); } void @@ -161,10 +154,9 @@ namespace xo { scope log(XO_DEBUG(debug_flag_)); log && log(xtag("tk", tk), - xtag("psm", *this)); + xtag("psm", this)); - this->p_stack_ - ->top_exprstate().on_then_token(tk, this); + this->xs_stack_.top_exprstate().on_then_token(tk, this); } void @@ -173,23 +165,22 @@ namespace xo { scope log(XO_DEBUG(debug_flag_)); log && log(xtag("tk", tk), - xtag("psm", *this)); + xtag("psm", this)); - this->p_stack_ - ->top_exprstate().on_else_token(tk, this); + this->xs_stack_.top_exprstate().on_else_token(tk, this); } void parserstatemachine::on_error(const char * self_name, std::string errmsg) { - *(this->p_result_) = parser_result::error(self_name, std::move(errmsg)); + this->result_ = parser_result::error(self_name, std::move(errmsg)); } void parserstatemachine::print(std::ostream & os) const { os << ""; } } /*namespace scm*/ diff --git a/xo-reader/src/reader/pretty_parserstatemachine.cpp b/xo-reader/src/reader/pretty_parserstatemachine.cpp index e0f01a81..693c1983 100644 --- a/xo-reader/src/reader/pretty_parserstatemachine.cpp +++ b/xo-reader/src/reader/pretty_parserstatemachine.cpp @@ -19,17 +19,17 @@ namespace xo { if (!pps->print_upto("print_upto_tag("stack", x.p_stack_)) + if (!pps->print_upto_tag("stack", &x.xs_stack_)) return false; - if (!pps->print_upto_tag("env_stack", x.p_env_stack_)) + if (!pps->print_upto_tag("env_stack", &x.env_stack_)) return false; return pps->print_upto(">"); } else { pps->write("newline_pretty_tag(ppii.ci1(), "stack", x.p_stack_); - pps->newline_pretty_tag(ppii.ci1(), "env_stack", x.p_env_stack_); + pps->newline_pretty_tag(ppii.ci1(), "stack", &x.xs_stack_); + pps->newline_pretty_tag(ppii.ci1(), "env_stack", &x.env_stack_); pps->write(">"); return false;