xo-reader2 scaffold (fomo+arena version of xo-reader/) [WIP]

This commit is contained in:
Roland Conybeare 2026-01-18 17:59:46 -05:00
commit 7ee57309b5
25 changed files with 1378 additions and 11 deletions

View file

@ -0,0 +1,30 @@
# reader2/CMakeLists.txt
set(SELF_LIB xo_reader2)
set(SELF_SRCS
#init_reader2.cpp
ParserStateMachine.cpp
ParserStack.cpp
ParserResult.cpp
ISyntaxStateMachine_Any.cpp
DExprSeqState.cpp
ISyntaxStateMachine_DExprSeqState.cpp
#reader2_register_facets.cpp
#reader2_register_types.cpp
)
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
# note: deps here must also appear in cmake/xo_expression2Config.cmake.in
xo_dependency(${SELF_LIB} xo_gc)
xo_dependency(${SELF_LIB} xo_tokenizer2)
xo_dependency(${SELF_LIB} xo_expression2)
#xo_dependency(${SELF_LIB} reflect)
#xo_dependency(${SELF_LIB} xo_object2)
#xo_dependency(${SELF_LIB} xo_printable2)
#xo_dependency(${SELF_LIB} xo_flatstring)
#xo_dependency(${SELF_LIB} subsys)
#xo_dependency(${SELF_LIB} indentlog)

View file

@ -0,0 +1,101 @@
/** @file DExprSeqState.cpp
*
* @author Roland Conybeare, Jan 2026
**/
#include "DExprSeqState.hpp"
#include "ssm/ISyntaxStateMachine_DExprSeqState.hpp"
namespace xo {
using xo::mm::AAllocator;
using xo::facet::with_facet;
using xo::reflect::typeseq;
namespace scm {
DExprSeqState::DExprSeqState(exprseqtype ty) : seqtype_{ty}
{}
namespace {
obj<ASyntaxStateMachine>
make_exprseq_ssm(obj<AAllocator> mm,
exprseqtype seqtype)
{
void * mem = mm.alloc(typeseq::id<DExprSeqState>(),
sizeof(DExprSeqState));
DExprSeqState * ssm = new (mem) DExprSeqState(seqtype);
return with_facet<ASyntaxStateMachine>::mkobj(ssm);
}
}
void
DExprSeqState::start_interactive(obj<AAllocator> mm,
ParserStateMachine * p_psm)
{
p_psm->push_ssm(make_exprseq_ssm(mm,
exprseqtype::toplevel_interactive));
}
void
DExprSeqState::start_batch(obj<AAllocator> mm,
ParserStateMachine * p_psm)
{
(void)mm;
(void)p_psm;
#ifdef NOT_YET
p_psm->push_ssm(make_exprseq_ssm(mm,
exprseqtype::toplevel_batch));
#endif
}
// SyntaxStateMachine facet methods
syntaxstatetype
DExprSeqState::ssm_type() const noexcept
{
return syntaxstatetype::expect_toplevel_expression_sequence;
}
std::string_view
DExprSeqState::get_expect_str() const noexcept
{
// TODO: provisional. Will expand as more syntax implemented
switch (seqtype_) {
case exprseqtype::toplevel_interactive:
return "def|expression|...";
case exprseqtype::toplevel_batch:
return "def|...";
case exprseqtype::N:
break;
}
assert(false);
return "impossible-DExprSeqState::get_expr_str";
}
void
DExprSeqState::on_if_token(const Token & tk,
ParserStateMachine * p_psm)
{
switch (seqtype_) {
case exprseqtype::toplevel_interactive:
assert(false); // DfElseState::start(p_psm);
break;
case exprseqtype::toplevel_batch:
p_psm->illegal_input_on_token("DExprSeqState::on_if_token",
tk,
this->get_expect_str());
break;
case exprseqtype::N:
assert(false); // unreachable
break;
}
}
} /*namespace scm*/
} /*namespace xo*/
/* end DExprSeqState.cpp */

View file

@ -0,0 +1,47 @@
/** @file ISyntaxStateMachine_Any.cpp
*
**/
#include "ssm/ISyntaxStateMachine_Any.hpp"
#include <iostream>
namespace xo {
namespace scm {
using xo::facet::DVariantPlaceholder;
using xo::facet::typeseq;
using xo::facet::valid_facet_implementation;
void
ISyntaxStateMachine_Any::_fatal()
{
/* control here on uninitialized IAllocator_Any.
* Initialized instance will have specific implementation type
*/
std::cerr << "fatal"
<< ": attempt to call uninitialized"
<< " ISyntaxStateMachine_Any method"
<< std::endl;
std::terminate();
}
typeseq
ISyntaxStateMachine_Any::s_typeseq = typeseq::id<DVariantPlaceholder>();
bool
ISyntaxStateMachine_Any::_valid
= valid_facet_implementation<ASyntaxStateMachine, ISyntaxStateMachine_Any>();
// nonconst methods
auto
ISyntaxStateMachine_Any::on_if_token(Opaque, const Token &, ParserStateMachine *) -> void
{
_fatal();
}
} /*namespace scm*/
} /*namespace xo*/
/* end ISyntaxStateMachine_Any.cpp */

View file

@ -0,0 +1,39 @@
/** @file ISyntaxStateMachine_DExprSeqState.cpp
*
* Generated automagically from ingredients:
* 1. code generator:
* [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet]
* arguments:
* --input [idl/ISyntaxStateMachine_DExprSeqState.json5]
* 2. jinja2 template for abstract facet .hpp file:
* [iface_facet_any.hpp.j2]
* 3. idl for facet methods
* [idl/ISyntaxStateMachine_DExprSeqState.json5]
**/
#include "ssm/ISyntaxStateMachine_DExprSeqState.hpp"
namespace xo {
namespace scm {
auto
ISyntaxStateMachine_DExprSeqState::ssm_type(const DExprSeqState & self) noexcept -> syntaxstatetype
{
return self.ssm_type();
}
auto
ISyntaxStateMachine_DExprSeqState::get_expect_str(const DExprSeqState & self) noexcept -> std::string_view
{
return self.get_expect_str();
}
auto
ISyntaxStateMachine_DExprSeqState::on_if_token(DExprSeqState & self, const Token & tk, ParserStateMachine * p_psm) -> void
{
self.on_if_token(tk, p_psm);
}
} /*namespace scm*/
} /*namespace xo*/
/* end ISyntaxStateMachine_DExprSeqState.cpp */

View file

@ -0,0 +1,32 @@
/** @file ParserResult.cpp
*
* @author Roland Conybeare, Jan 2026
**/
#include "ParserResult.hpp"
namespace xo {
namespace scm {
ParserResult::ParserResult(parser_result_type type,
obj<AExpression> expr,
std::string_view error_src_fn,
const DString * error_description)
: result_type_{type},
result_expr_{expr},
error_src_fn_{error_src_fn},
error_description_{error_description}
{}
ParserResult
ParserResult::error(std::string_view ssm_name,
const DString * errmsg)
{
return ParserResult(parser_result_type::error,
obj<AExpression>(),
ssm_name,
errmsg);
}
} /*namespace scm*/
} /*namespace xo*/
/* end ParserResult.cpp */

View file

@ -0,0 +1,28 @@
/** @file ParserStack.cpp
*
* @author Roland Conybeare, Jan 2026
**/
#include "ParserStack.hpp"
#include "SyntaxStateMachine.hpp"
namespace xo {
using xo::facet::typeseq;
namespace scm {
ParserStack *
ParserStack::push(obj<AAllocator> mm,
obj<ASyntaxStateMachine> ssm)
{
void * mem = mm.alloc(typeseq::id<ParserStack>(),
sizeof(ParserStack));
return new (mem) ParserStack(ssm, parent_);
}
} /*namespace scm*/
} /*namespace xo*/
/* end ParserStack.cpp */

View file

@ -0,0 +1,134 @@
/** @file ParserStateMachine.cpp
*
* @author Roland Conybeare, Jan 2026
**/
#include "ParserStateMachine.hpp"
#include "ParserStack.hpp"
#include "SyntaxStateMachine.hpp"
#include <xo/alloc2/arena/IAllocator_DArena.hpp>
#include <xo/indentlog/scope.hpp>
#include <xo/indentlog/print/tostr.hpp>
#include <xo/indentlog/print/tag.hpp>
#include <stdexcept>
namespace xo {
using xo::facet::with_facet;
namespace scm {
void
ParserStateMachine::push_ssm(obj<ASyntaxStateMachine> ssm)
{
scope log(XO_DEBUG(debug_flag_));
// note: using parser_alloc_ for parser stack, since stacklike behavior
auto alloc = with_facet<AAllocator>::mkobj(&parser_alloc_);
this->stack_ = stack_->push(alloc, ssm);
}
void
ParserStateMachine::on_token(const Token & tk)
{
scope log(XO_DEBUG(debug_flag_), xtag("tk", tk));
if (!stack_) {
// parsing stack should always have toplevel expression sequence
throw std::runtime_error(tostr("unexpected empty parsing stack",
xtag("token", tk),
xtag("help", "do it the same. but better!")
));
}
switch (tk.tk_type()) {
case tokentype::tk_if:
this->on_if_token(tk);
break;
// all the not-yet handled cases
case tokentype::tk_invalid:
case tokentype::tk_bool:
case tokentype::tk_i64:
case tokentype::tk_f64:
case tokentype::tk_string:
case tokentype::tk_symbol:
case tokentype::tk_leftparen:
case tokentype::tk_rightparen:
case tokentype::tk_leftbracket:
case tokentype::tk_rightbracket:
case tokentype::tk_leftbrace:
case tokentype::tk_rightbrace:
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_colon:
case tokentype::tk_doublecolon:
case tokentype::tk_semicolon:
case tokentype::tk_singleassign:
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_def:
case tokentype::tk_lambda:
case tokentype::tk_then:
case tokentype::tk_else:
case tokentype::tk_let:
case tokentype::tk_in:
case tokentype::tk_end:
case tokentype::N:
throw std::runtime_error(tostr("NOT IMPLEMENTED",
xtag("token", tk)));
}
}
void
ParserStateMachine::on_if_token(const Token & tk)
{
scope log(XO_DEBUG(debug_flag_), xtag("tk", tk));
stack_->top().on_if_token(tk, this);
}
void
ParserStateMachine::capture_error(std::string_view ssm_name,
const DString * errmsg)
{
this->result_ = ParserResult::error(ssm_name, errmsg);
}
void
ParserStateMachine::illegal_input_on_token(std::string_view ssm_name,
const Token & tk,
std::string_view expect_str)
{
// TODO:
// - want to write error message using DArena
// - need something like log_streambuf and/or tostr() that's arena-aware
auto errmsg_string = tostr("Unexpected token for parsing state",
xtag("token", tk),
xtag("expecting", expect_str),
xtag("ssm", ssm_name),
xtag("via", "ParserStateMachine::illegal_input_on_token"));
auto errmsg = DString::from_view(expr_alloc_,
std::string_view(errmsg_string));
this->capture_error(ssm_name, errmsg);
}
} /*namespace scm*/
} /*namespace xo*/
/* end ParserStateMachine.cpp */