xo-reader: feat: parse infix exprs for +,-,*,/ operators
This commit is contained in:
parent
f677995f77
commit
29596a7c1d
5 changed files with 141 additions and 8 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue