xo-reader: refactor to simplify parser+parserstatemachine
This commit is contained in:
parent
ce760bd5cf
commit
81bbc080fd
10 changed files with 85 additions and 129 deletions
|
|
@ -36,7 +36,7 @@ namespace xo {
|
|||
**/
|
||||
void upsert(bp<Variable> target);
|
||||
|
||||
bp<LocalEnv> top_envframe();
|
||||
bp<LocalEnv> top_envframe() const;
|
||||
void push_envframe(const rp<LocalEnv> & x);
|
||||
rp<LocalEnv> pop_envframe();
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "exprstatestack.hpp"
|
||||
#include "envframestack.hpp"
|
||||
#include "parser_result.hpp"
|
||||
#include "parserstatemachine.hpp"
|
||||
#include <stdexcept>
|
||||
|
||||
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 &
|
||||
|
|
|
|||
|
|
@ -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<char>;
|
||||
|
||||
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<LocalEnv> 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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ namespace xo {
|
|||
rp<Expression> def_expr = this->def_expr_;
|
||||
|
||||
this->defxs_type_ = defexprstatetype::def_6;
|
||||
return;
|
||||
}
|
||||
|
||||
constexpr const char * c_self_name = "define_xs::on_expr";
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace xo {
|
|||
|
||||
namespace scm {
|
||||
bp<LocalEnv>
|
||||
envframestack::top_envframe() {
|
||||
envframestack::top_envframe() const {
|
||||
std::size_t z = stack_.size();
|
||||
|
||||
if (z == 0) {
|
||||
|
|
|
|||
|
|
@ -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*/
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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<LocalEnv> 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 << "<parser"
|
||||
<< std::endl;
|
||||
|
||||
xs_stack_.print(os);
|
||||
psm_.xs_stack_.print(os);
|
||||
|
||||
os << ">" << std::endl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,32 +17,32 @@ namespace xo {
|
|||
namespace scm {
|
||||
bp<Variable>
|
||||
parserstatemachine::lookup_var(const std::string & x) const {
|
||||
return p_env_stack_->lookup(x);
|
||||
return env_stack_.lookup(x);
|
||||
}
|
||||
|
||||
void
|
||||
parserstatemachine::upsert_var(bp<Variable> x) {
|
||||
p_env_stack_->upsert(x);
|
||||
env_stack_.upsert(x);
|
||||
}
|
||||
|
||||
std::unique_ptr<exprstate>
|
||||
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<exprstate> x) {
|
||||
p_stack_->push_exprstate(std::move(x));
|
||||
xs_stack_.push_exprstate(std::move(x));
|
||||
}
|
||||
|
||||
bp<LocalEnv>
|
||||
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<LocalEnv>
|
||||
|
|
@ -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 << "<psm";
|
||||
os << xtag("stack", p_stack_);
|
||||
os << xtag("env_stack", p_env_stack_);
|
||||
os << xtag("stack", &xs_stack_);
|
||||
os << xtag("env_stack", &env_stack_);
|
||||
os << ">";
|
||||
}
|
||||
} /*namespace scm*/
|
||||
|
|
|
|||
|
|
@ -19,17 +19,17 @@ namespace xo {
|
|||
if (!pps->print_upto("<psm"))
|
||||
return false;
|
||||
|
||||
if (!pps->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("<psm");
|
||||
pps->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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue