From bba6898ee15e7dcc3a8db683046ec99b7f48e5d3 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Thu, 15 Aug 2024 00:14:55 -0400 Subject: [PATCH] xo-reader: fix+prep: setup for associative behaviore --- include/xo/reader/progress_xs.hpp | 28 +++++++- src/reader/progress_xs.cpp | 110 ++++++++++++++++++++++-------- 2 files changed, 106 insertions(+), 32 deletions(-) diff --git a/include/xo/reader/progress_xs.hpp b/include/xo/reader/progress_xs.hpp index 9a7381c7..fb56c141 100644 --- a/include/xo/reader/progress_xs.hpp +++ b/include/xo/reader/progress_xs.hpp @@ -6,6 +6,7 @@ #pragma once #include "exprstate.hpp" +#include //#include namespace xo { @@ -22,6 +23,15 @@ namespace xo { n_optype }; + extern const char * + optype_descr(optype x); + + inline std::ostream & + operator<< (std::ostream & os, optype x) { + os << optype_descr(x); + return os; + } + /** @class progress_xs * @brief state machine for parsing a schematica runtime-value-expression **/ @@ -74,11 +84,25 @@ namespace xo { virtual void print(std::ostream & os) const override; private: - /** populate an expression here **/ - rp gen_expr_; + /** assemble expression representing + * value of + * @code + * f(lhs_, rhs_) + * @endcode + * + * where f determined by @ref op_type_ + **/ + rp assemble_expr(); + + private: + /** populate an expression here, may be followed by an operator **/ + rp lhs_; /** infix operator, if supplied **/ optype op_type_ = optype::invalid; + + /** populate an expression here, following infix operator */ + rp rhs_; }; } /*namespace scm*/ } /*namespace xo*/ diff --git a/src/reader/progress_xs.cpp b/src/reader/progress_xs.cpp index 241c5da4..b7a1775b 100644 --- a/src/reader/progress_xs.cpp +++ b/src/reader/progress_xs.cpp @@ -5,9 +5,29 @@ #include "xo/expression/Apply.hpp" namespace xo { + using xo::ast::Expression; using xo::ast::Apply; namespace scm { + const char * + optype_descr(optype x) { + switch (x) { + case optype::invalid: + return "?optype"; + case optype::op_add: + return "op+"; + case optype::op_subtract: + return "op-"; + case optype::op_multiply: + return "op*"; + case optype::op_divide: + return "op/"; + case optype::n_optype: + break; + } + return "???"; + } + std::unique_ptr progress_xs::make(rp valex) { return std::make_unique(progress_xs(std::move(valex))); @@ -15,7 +35,7 @@ namespace xo { progress_xs::progress_xs(rp valex) : exprstate(exprstatetype::expr_progress), - gen_expr_{std::move(valex)} + lhs_{std::move(valex)} {} bool @@ -31,48 +51,66 @@ namespace xo { this->illegal_input_error(self_name, tk) ; } - void - progress_xs::on_expr(ref::brw expr, - exprstatestack * p_stack, - rp * /*p_emit_expr*/) - { - constexpr const char * c_self_name = "progress_xs::on_expr"; + rp + progress_xs::assemble_expr() { + /* need to defer building Apply incase expr followed by higher-precedence operator: + * consider input like + * 3.14 + 2.0 * ... + */ - rp result; - - /* consecutive expressions isn't legal */ + /* consecutive expressions not legal, e.g: + * 3.14 6.28 + * but expressions surrounding an infix operators is: + * 3.14 / 6.28 + */ switch (op_type_) { case optype::invalid: - throw std::runtime_error(tostr(c_self_name, - ": consecutive unseparated exprs not legal")); - - break; + return this->lhs_; case optype::op_add: - result = Apply::make_add2_f64(this->gen_expr_ /*lhs*/, - expr.promote() /*rhs*/); - break; + return Apply::make_add2_f64(this->lhs_, + this->rhs_); case optype::op_subtract: - result = Apply::make_sub2_f64(this->gen_expr_ /*lhs*/, - expr.promote() /*rhs*/); - break; + return Apply::make_sub2_f64(this->lhs_, + this->rhs_); case optype::op_multiply: - result = Apply::make_mul2_f64(this->gen_expr_ /*lhs*/, - expr.promote() /*rhs*/); - break; + return Apply::make_mul2_f64(this->lhs_, + this->rhs_); case optype::op_divide: - result = Apply::make_div2_f64(this->gen_expr_ /*lhs*/, - expr.promote() /*rhs*/); - break; + return Apply::make_div2_f64(this->lhs_, + this->rhs_); case optype::n_optype: /* unreachable */ assert(false); + return nullptr; } + return nullptr; + } + + void + progress_xs::on_expr(ref::brw expr, + exprstatestack * /*p_stack*/, + rp * /*p_emit_expr*/) + { + /* note: previous token probably an operator, + * handled from progress_xs::on_operator_token(), + * which pushes expect_expr_xs::expect_rhs_expression() + */ + + constexpr const char * c_self_name = "progress_xs::on_expr"; + + + if (op_type_ == optype::invalid) { + throw std::runtime_error(tostr(c_self_name, + ": consecutive unseparated exprs not legal")); + } + +#ifdef NOT_QUITE assert(result.get()); /* this expression complete.. */ @@ -80,6 +118,9 @@ namespace xo { /* ..but more operators could follow, so don't commit yet */ p_stack->push_exprstate(progress_xs::make(result)); +#endif + + this->rhs_ = expr.promote(); } void @@ -116,10 +157,12 @@ namespace xo { exprstatestack * p_stack, rp * p_emit_expr) { + /* note: implementation parllels .on_rightparen_token() */ + constexpr bool c_debug_flag = true; scope log(XO_DEBUG(c_debug_flag)); - rp expr = this->gen_expr_; + rp expr = this->assemble_expr(); std::unique_ptr self = p_stack->pop_exprstate(); @@ -171,6 +214,9 @@ namespace xo { exprstatestack * p_stack, rp * p_emit_expr) { + /* note: implementation parallels .on_semicolon_token() */ + + constexpr bool c_debug_flag = true; scope log(XO_DEBUG(c_debug_flag)); @@ -188,7 +234,7 @@ namespace xo { */ /* right paren confirms stack expression */ - rp expr = this->gen_expr_; + rp expr = this->assemble_expr(); std::unique_ptr self = p_stack->pop_exprstate(); @@ -264,8 +310,12 @@ namespace xo { progress_xs::print(std::ostream & os) const { os << ""; }