xo-umbrella2/src/reader2/DSequenceSsm.cpp
Roland Conybeare 3af72fec64 xo-reader2: + SyntaxStateMachine.forward_children method
Support gc traversal with goal of making ParserStateMachine a gc root
2026-03-24 17:43:45 -04:00

270 lines
8.7 KiB
C++

/* @file DSequenceSsm.cpp */
#include "DSequenceSsm.hpp"
#include "ssm/ISyntaxStateMachine_DSequenceSsm.hpp"
#include "DExpectExprSsm.hpp"
#include <xo/expression2/SequenceExpr.hpp>
#include <xo/alloc2/GCObject.hpp>
#ifdef NOT_YET
#include "expect_expr_xs.hpp"
#include "let1_xs.hpp"
#include "xo/expression/DefineExpr.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)
{
DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint();
p_psm->push_ssm(ckp, 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(true /*allow_defs*/,
true /*cxl_on_rightbrace*/,
false /*!cxl_on_rightparen*/,
p_psm);
}
obj<ASyntaxStateMachine,DSequenceSsm>
DSequenceSsm::make(DArena & mm,
obj<AAllocator> expr_mm)
{
return obj<ASyntaxStateMachine,DSequenceSsm>(_make(mm, expr_mm));
}
DSequenceSsm *
DSequenceSsm::_make(DArena & mm,
obj<AAllocator> expr_mm)
{
void * mem = mm.alloc(typeseq::id<DSequenceSsm>(),
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_deftype:
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_quote:
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_cmple:
case tokentype::tk_cmpge:
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_nil:
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<DSequenceSsm>::on_token(tk, p_psm);
}
void
DSequenceSsm::on_rightbrace_token(const Token & tk,
ParserStateMachine * p_psm)
{
(void)tk;
/** rightbrace ends DSequenceSsm **/
obj<AExpression,DSequenceExpr> 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<AExpression> 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<DefineExpr> 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<AExpression> 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<Expression> 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()));
}
void
DSequenceSsm::forward_children(obj<ACollector> gc) noexcept
{
gc.forward_inplace(&seq_expr_);
}
} /*namespace scm*/
} /*namespace xo*/
/* end DSequenceSsm.cpp */