/* @file DSequenceSsm.cpp */ #include "DSequenceSsm.hpp" #include "ssm/ISyntaxStateMachine_DSequenceSsm.hpp" #include "DExpectExprSsm.hpp" #ifdef NOT_YET #include "expect_expr_xs.hpp" #include "let1_xs.hpp" #include "xo/expression/DefineExpr.hpp" #include "xo/expression/Sequence.hpp" #include "xo/expression/pretty_expression.hpp" #endif namespace xo { #ifdef NOT_YET using xo::scm::DDefineExpr; #endif using xo::facet::typeseq; namespace scm { void DSequenceSsm::start(ParserStateMachine * p_psm) { p_psm->push_ssm(DSequenceSsm::make(p_psm->parser_alloc(), p_psm->expr_alloc())); /* want to accept anything that starts an expression, * except that rightbrace '}' ends it */ DExpectExprSsm::start(p_psm->parser_alloc(), true /*allow_defs*/, true /*cxl_on_rightbrace*/, p_psm); } obj DSequenceSsm::make(DArena & mm, obj expr_mm) { return obj(_make(mm, expr_mm)); } DSequenceSsm * DSequenceSsm::_make(DArena & mm, obj expr_mm) { void * mem = mm.alloc(typeseq::id(), sizeof(DSequenceSsm)); DSequenceExpr * seq_expr = DSequenceExpr::_make_empty(expr_mm); return new (mem) DSequenceSsm(seq_expr); } DSequenceSsm::DSequenceSsm(DSequenceExpr * seq_expr) : seq_expr_{seq_expr} {} syntaxstatetype DSequenceSsm::ssm_type() const noexcept { return syntaxstatetype::sequence; } std::string_view DSequenceSsm::get_expect_str() const noexcept { return "expr|semicolon|rightbrace"; } void DSequenceSsm::on_token(const Token & tk, ParserStateMachine * p_psm) { scope log(XO_DEBUG(p_psm->debug_flag()), xtag("tk", tk)); switch (tk.tk_type()) { case tokentype::tk_rightbrace: this->on_rightbrace_token(tk, p_psm); return; case tokentype::tk_symbol: case tokentype::tk_def: case tokentype::tk_if: case tokentype::tk_then: case tokentype::tk_else: case tokentype::tk_colon: case tokentype::tk_singleassign: case tokentype::tk_string: case tokentype::tk_f64: case tokentype::tk_i64: case tokentype::tk_bool: case tokentype::tk_semicolon: case tokentype::tk_invalid: case tokentype::tk_leftparen: case tokentype::tk_rightparen: case tokentype::tk_leftbracket: case tokentype::tk_rightbracket: case tokentype::tk_leftbrace: case tokentype::tk_leftangle: case tokentype::tk_rightangle: case tokentype::tk_lessequal: case tokentype::tk_greatequal: case tokentype::tk_dot: case tokentype::tk_comma: case tokentype::tk_doublecolon: case tokentype::tk_assign: case tokentype::tk_yields: case tokentype::tk_plus: case tokentype::tk_minus: case tokentype::tk_star: case tokentype::tk_slash: case tokentype::tk_cmpeq: case tokentype::tk_cmpne: case tokentype::tk_type: case tokentype::tk_lambda: case tokentype::tk_let: case tokentype::tk_in: case tokentype::tk_end: case tokentype::N: break; } // default = illegal token error DSyntaxStateMachine::on_token(tk, p_psm); } void DSequenceSsm::on_rightbrace_token(const Token & tk, ParserStateMachine * p_psm) { (void)tk; /** rightbrace ends DSequenceSsm **/ obj expr(seq_expr_); p_psm->pop_ssm(); /* make sequence from expressions seen at this level, * and report it to parent */ p_psm->top_ssm().on_parsed_expression(expr, p_psm); } void DSequenceSsm::on_parsed_expression(obj expr, ParserStateMachine * p_psm) { scope log(XO_DEBUG(p_psm->debug_flag())); // TODO: switch to printable facet log && log(xtag("expr", expr)); #ifdef NOT_YET /* TODO: if expr is a DefineExpr, * then need to rewrite... * * ...prefix * DefineExpr(lhs_name, rhs) * rest... * * becomes: * * /-- .outer_seq_expr_ * v * Sequence( * ...prefix, * * /-- .inner_lm_expr_ * v * Apply(Lambda(gen999, * [Variable(lhs_name, type(rhs))], * /-- .expr_v_ * v * sequencify(rest...)), * rhs)) * * so amongst other things, * helpful to have nested seequence_xs that propagates '}' * instead of swallowing it. */ bp def_expr = DefineExpr::from(expr); if (def_expr) { /** nested_start: control returns via * .on_expr(x) * with x something like: * Apply(Lambda(gensym(), * [Variable(def_expr->lhs_name(), * def_expr->valuetype())], * body...)) * followed immediately by * .on_rightbrace_token() **/ let1_xs::start(def_expr->lhs_name(), def_expr->rhs(), p_psm); } else { this->expr_v_.push_back(expr.promote()); expect_expr_xs::start(true /*allow_defs*/, true /*cxl_on_rightbrace*/, p_psm); } #endif this->seq_expr_->push_back(p_psm->expr_alloc(), expr); } void DSequenceSsm::on_parsed_expression_with_token(obj expr, const Token & tk, ParserStateMachine * p_psm) { scope log(XO_DEBUG(p_psm->debug_flag())); if (tk.tk_type() == tokentype::tk_semicolon) { // keep sequence on stack, consuming semicolon this->seq_expr_->push_back(p_psm->expr_alloc(), expr); return; } else if (tk.tk_type() == tokentype::tk_rightbrace) { // rightbrace ends sequence this->seq_expr_->push_back(p_psm->expr_alloc(), expr); this->on_rightbrace_token(tk, p_psm); return; } Super::on_parsed_expression_with_token(expr, tk, p_psm); } #ifdef NOT_YET void sequence_xs::on_expr_with_semicolon(bp expr, parserstatemachine * p_psm) { /* sequence continues until right brace */ this->on_expr(expr, p_psm); } #endif bool DSequenceSsm::pretty(const xo::print::ppindentinfo & ppii) const { return ppii.pps()->pretty_struct (ppii, "DSequenceSsm", refrtag("seq_expr.size", seq_expr_->size()), refrtag("expect", this->get_expect_str())); } } /*namespace scm*/ } /*namespace xo*/ /* end DSequenceSsm.cpp */