xo-reader: fix+prep: setup for associative behaviore
This commit is contained in:
parent
29596a7c1d
commit
bba6898ee1
2 changed files with 106 additions and 32 deletions
|
|
@ -6,6 +6,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "exprstate.hpp"
|
#include "exprstate.hpp"
|
||||||
|
#include <iostream>
|
||||||
//#include <cstdint>
|
//#include <cstdint>
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
|
|
@ -22,6 +23,15 @@ namespace xo {
|
||||||
n_optype
|
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
|
/** @class progress_xs
|
||||||
* @brief state machine for parsing a schematica runtime-value-expression
|
* @brief state machine for parsing a schematica runtime-value-expression
|
||||||
**/
|
**/
|
||||||
|
|
@ -74,11 +84,25 @@ namespace xo {
|
||||||
virtual void print(std::ostream & os) const override;
|
virtual void print(std::ostream & os) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** populate an expression here **/
|
/** assemble expression representing
|
||||||
rp<Expression> gen_expr_;
|
* value of
|
||||||
|
* @code
|
||||||
|
* f(lhs_, rhs_)
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* where f determined by @ref op_type_
|
||||||
|
**/
|
||||||
|
rp<Expression> assemble_expr();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** populate an expression here, may be followed by an operator **/
|
||||||
|
rp<Expression> lhs_;
|
||||||
|
|
||||||
/** infix operator, if supplied **/
|
/** infix operator, if supplied **/
|
||||||
optype op_type_ = optype::invalid;
|
optype op_type_ = optype::invalid;
|
||||||
|
|
||||||
|
/** populate an expression here, following infix operator */
|
||||||
|
rp<Expression> rhs_;
|
||||||
};
|
};
|
||||||
} /*namespace scm*/
|
} /*namespace scm*/
|
||||||
} /*namespace xo*/
|
} /*namespace xo*/
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,29 @@
|
||||||
#include "xo/expression/Apply.hpp"
|
#include "xo/expression/Apply.hpp"
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
|
using xo::ast::Expression;
|
||||||
using xo::ast::Apply;
|
using xo::ast::Apply;
|
||||||
|
|
||||||
namespace scm {
|
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>
|
std::unique_ptr<progress_xs>
|
||||||
progress_xs::make(rp<Expression> valex) {
|
progress_xs::make(rp<Expression> valex) {
|
||||||
return std::make_unique<progress_xs>(progress_xs(std::move(valex)));
|
return std::make_unique<progress_xs>(progress_xs(std::move(valex)));
|
||||||
|
|
@ -15,7 +35,7 @@ namespace xo {
|
||||||
|
|
||||||
progress_xs::progress_xs(rp<Expression> valex)
|
progress_xs::progress_xs(rp<Expression> valex)
|
||||||
: exprstate(exprstatetype::expr_progress),
|
: exprstate(exprstatetype::expr_progress),
|
||||||
gen_expr_{std::move(valex)}
|
lhs_{std::move(valex)}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -31,48 +51,66 @@ namespace xo {
|
||||||
this->illegal_input_error(self_name, tk) ;
|
this->illegal_input_error(self_name, tk) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
rp<Expression>
|
||||||
progress_xs::on_expr(ref::brw<Expression> expr,
|
progress_xs::assemble_expr() {
|
||||||
exprstatestack * p_stack,
|
/* need to defer building Apply incase expr followed by higher-precedence operator:
|
||||||
rp<Expression> * /*p_emit_expr*/)
|
* consider input like
|
||||||
{
|
* 3.14 + 2.0 * ...
|
||||||
constexpr const char * c_self_name = "progress_xs::on_expr";
|
*/
|
||||||
|
|
||||||
rp<Expression> result;
|
/* consecutive expressions not legal, e.g:
|
||||||
|
* 3.14 6.28
|
||||||
/* consecutive expressions isn't legal */
|
* but expressions surrounding an infix operators is:
|
||||||
|
* 3.14 / 6.28
|
||||||
|
*/
|
||||||
switch (op_type_) {
|
switch (op_type_) {
|
||||||
case optype::invalid:
|
case optype::invalid:
|
||||||
throw std::runtime_error(tostr(c_self_name,
|
return this->lhs_;
|
||||||
": consecutive unseparated exprs not legal"));
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case optype::op_add:
|
case optype::op_add:
|
||||||
result = Apply::make_add2_f64(this->gen_expr_ /*lhs*/,
|
return Apply::make_add2_f64(this->lhs_,
|
||||||
expr.promote() /*rhs*/);
|
this->rhs_);
|
||||||
break;
|
|
||||||
|
|
||||||
case optype::op_subtract:
|
case optype::op_subtract:
|
||||||
result = Apply::make_sub2_f64(this->gen_expr_ /*lhs*/,
|
return Apply::make_sub2_f64(this->lhs_,
|
||||||
expr.promote() /*rhs*/);
|
this->rhs_);
|
||||||
break;
|
|
||||||
|
|
||||||
case optype::op_multiply:
|
case optype::op_multiply:
|
||||||
result = Apply::make_mul2_f64(this->gen_expr_ /*lhs*/,
|
return Apply::make_mul2_f64(this->lhs_,
|
||||||
expr.promote() /*rhs*/);
|
this->rhs_);
|
||||||
break;
|
|
||||||
|
|
||||||
case optype::op_divide:
|
case optype::op_divide:
|
||||||
result = Apply::make_div2_f64(this->gen_expr_ /*lhs*/,
|
return Apply::make_div2_f64(this->lhs_,
|
||||||
expr.promote() /*rhs*/);
|
this->rhs_);
|
||||||
break;
|
|
||||||
|
|
||||||
case optype::n_optype:
|
case optype::n_optype:
|
||||||
/* unreachable */
|
/* unreachable */
|
||||||
assert(false);
|
assert(false);
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
progress_xs::on_expr(ref::brw<Expression> expr,
|
||||||
|
exprstatestack * /*p_stack*/,
|
||||||
|
rp<Expression> * /*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());
|
assert(result.get());
|
||||||
|
|
||||||
/* this expression complete.. */
|
/* this expression complete.. */
|
||||||
|
|
@ -80,6 +118,9 @@ namespace xo {
|
||||||
|
|
||||||
/* ..but more operators could follow, so don't commit yet */
|
/* ..but more operators could follow, so don't commit yet */
|
||||||
p_stack->push_exprstate(progress_xs::make(result));
|
p_stack->push_exprstate(progress_xs::make(result));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
this->rhs_ = expr.promote();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -116,10 +157,12 @@ namespace xo {
|
||||||
exprstatestack * p_stack,
|
exprstatestack * p_stack,
|
||||||
rp<Expression> * p_emit_expr)
|
rp<Expression> * p_emit_expr)
|
||||||
{
|
{
|
||||||
|
/* note: implementation parllels .on_rightparen_token() */
|
||||||
|
|
||||||
constexpr bool c_debug_flag = true;
|
constexpr bool c_debug_flag = true;
|
||||||
scope log(XO_DEBUG(c_debug_flag));
|
scope log(XO_DEBUG(c_debug_flag));
|
||||||
|
|
||||||
rp<Expression> expr = this->gen_expr_;
|
rp<Expression> expr = this->assemble_expr();
|
||||||
|
|
||||||
std::unique_ptr<exprstate> self = p_stack->pop_exprstate();
|
std::unique_ptr<exprstate> self = p_stack->pop_exprstate();
|
||||||
|
|
||||||
|
|
@ -171,6 +214,9 @@ namespace xo {
|
||||||
exprstatestack * p_stack,
|
exprstatestack * p_stack,
|
||||||
rp<Expression> * p_emit_expr)
|
rp<Expression> * p_emit_expr)
|
||||||
{
|
{
|
||||||
|
/* note: implementation parallels .on_semicolon_token() */
|
||||||
|
|
||||||
|
|
||||||
constexpr bool c_debug_flag = true;
|
constexpr bool c_debug_flag = true;
|
||||||
scope log(XO_DEBUG(c_debug_flag));
|
scope log(XO_DEBUG(c_debug_flag));
|
||||||
|
|
||||||
|
|
@ -188,7 +234,7 @@ namespace xo {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* right paren confirms stack expression */
|
/* right paren confirms stack expression */
|
||||||
rp<Expression> expr = this->gen_expr_;
|
rp<Expression> expr = this->assemble_expr();
|
||||||
|
|
||||||
std::unique_ptr<exprstate> self = p_stack->pop_exprstate();
|
std::unique_ptr<exprstate> self = p_stack->pop_exprstate();
|
||||||
|
|
||||||
|
|
@ -264,8 +310,12 @@ namespace xo {
|
||||||
progress_xs::print(std::ostream & os) const {
|
progress_xs::print(std::ostream & os) const {
|
||||||
os << "<progress_xs"
|
os << "<progress_xs"
|
||||||
<< xtag("type", exs_type_);
|
<< xtag("type", exs_type_);
|
||||||
if (gen_expr_)
|
if (lhs_)
|
||||||
os << xtag("gen_expr", gen_expr_);
|
os << xtag("lhs", lhs_);
|
||||||
|
if (op_type_ != optype::invalid)
|
||||||
|
os << xtag("op", op_type_);
|
||||||
|
if (rhs_)
|
||||||
|
os << xtag("rhs", rhs_);
|
||||||
os << ">";
|
os << ">";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue