xo-reader: feat: parse infix exprs for +,-,*,/ operators

This commit is contained in:
Roland Conybeare 2024-08-14 23:44:17 -04:00
commit 29596a7c1d
5 changed files with 141 additions and 8 deletions

View file

@ -1,8 +1,12 @@
/* @file progress_xs.cpp */
#include "progress_xs.hpp"
#include "expect_expr_xs.hpp"
#include "xo/expression/Apply.hpp"
namespace xo {
using xo::ast::Apply;
namespace scm {
std::unique_ptr<progress_xs>
progress_xs::make(rp<Expression> valex) {
@ -28,12 +32,54 @@ namespace xo {
}
void
progress_xs::on_expr(ref::brw<Expression> /*expr*/,
exprstatestack * /*p_stack*/,
progress_xs::on_expr(ref::brw<Expression> expr,
exprstatestack * p_stack,
rp<Expression> * /*p_emit_expr*/)
{
constexpr const char * c_self_name = "progress_xs::on_expr";
rp<Expression> result;
/* consecutive expressions isn't legal */
assert(false);
switch (op_type_) {
case optype::invalid:
throw std::runtime_error(tostr(c_self_name,
": consecutive unseparated exprs not legal"));
break;
case optype::op_add:
result = Apply::make_add2_f64(this->gen_expr_ /*lhs*/,
expr.promote() /*rhs*/);
break;
case optype::op_subtract:
result = Apply::make_sub2_f64(this->gen_expr_ /*lhs*/,
expr.promote() /*rhs*/);
break;
case optype::op_multiply:
result = Apply::make_mul2_f64(this->gen_expr_ /*lhs*/,
expr.promote() /*rhs*/);
break;
case optype::op_divide:
result = Apply::make_div2_f64(this->gen_expr_ /*lhs*/,
expr.promote() /*rhs*/);
break;
case optype::n_optype:
/* unreachable */
assert(false);
}
assert(result.get());
/* this expression complete.. */
std::unique_ptr<exprstate> self = p_stack->pop_exprstate();
/* ..but more operators could follow, so don't commit yet */
p_stack->push_exprstate(progress_xs::make(result));
}
void
@ -75,7 +121,7 @@ namespace xo {
rp<Expression> expr = this->gen_expr_;
std::unique_ptr<exprstate> self = p_stack->pop_exprstate(); /* NOT KOSHER. invalidates *this */
std::unique_ptr<exprstate> self = p_stack->pop_exprstate();
p_stack->top_exprstate().on_expr(expr,
p_stack,
@ -160,17 +206,58 @@ namespace xo {
}
void
progress_xs::on_operator_token(const token_type & tk,
exprstatestack * p_stack,
rp<Expression> * p_emit_expr)
{
constexpr const char * c_self_name = "progress_xs::on_operator_token";
if (op_type_ == optype::invalid) {
switch(tk.tk_type()) {
case tokentype::tk_plus:
this->op_type_ = optype::op_add;
break;
case tokentype::tk_minus:
this->op_type_ = optype::op_subtract;
break;
case tokentype::tk_star:
this->op_type_ = optype::op_multiply;
break;
case tokentype::tk_slash:
this->op_type_ = optype::op_divide;
break;
default:
/* unreachable */
assert(false);
exprstate::on_operator_token(tk, p_stack, p_emit_expr);
}
/* infix operator must be followed by non-empty expression */
p_stack->push_exprstate(expect_expr_xs::expect_rhs_expression());
} else {
throw std::runtime_error(tostr(c_self_name,
": expected expression following operator",
xtag("tk", tk)));
}
}
void
progress_xs::on_f64_token(const token_type & tk,
exprstatestack * /*p_stack*/,
rp<Expression> * /*p_emit_expr*/)
exprstatestack * p_stack,
rp<Expression> * p_emit_expr)
{
constexpr bool c_debug_flag = true;
scope log(XO_DEBUG(c_debug_flag));
constexpr const char * self_name = "progress_xs::on_f64";
this->illegal_input_error(self_name, tk);
if (this->op_type_ == optype::invalid) {
this->illegal_input_error(self_name, tk);
} else {
assert(false);
exprstate::on_f64_token(tk, p_stack, p_emit_expr);
}
}
void