diff --git a/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp b/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp new file mode 100644 index 00000000..788f04e8 --- /dev/null +++ b/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp @@ -0,0 +1,113 @@ +/** @file DExpectExprSsm.hpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "ParserStateMachine.hpp" +#include "syntaxstatetype.hpp" +//#include +#include +#include + +namespace xo { + namespace scm { + + class DExpectExprSsm { + public: + using TypeDescr = xo::reflect::TypeDescr; + using DArena = xo::mm::DArena; + using ppindentinfo = xo::print::ppindentinfo; + + public: + explicit DExpectExprSsm(bool allow_defs, + bool cxl_on_rightparen); + + static DExpectExprSsm * make(DArena & parser_mm, + bool allow_defs, + bool cxl_on_rightparen); + + static void start(DArena & parser_mm, + bool allow_defs, + bool cxl_on_rightparen, + ParserStateMachine * p_psm); + + /** @defgroup scm-expectexpr-ssm-facet syntaxstatemachine facet methods **/ + ///@{ + + /** identifies the ssm implemented here **/ + syntaxstatetype ssm_type() const noexcept; + + /** text describing expected/allowed input to this ssm in current state. + * Intended to drive error mesages + **/ + std::string_view get_expect_str() const noexcept; + + /** operate state machine for this syntax on incoming symbol-token @p tk + * with overall parser state in @p p_psm + **/ + void on_symbol_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming token @p tk, + * overall parser state in @p p_psm + **/ + void on_def_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming token @p tk, + * overall parser state in @p p_psm + **/ + void on_if_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming colon token @p tk, + * overall parser state in @p p_psm + **/ + void on_colon_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming singleassign token @p tk, + * overall parser state in @p p_psm + **/ + void on_singleassign_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax after parsing a symbol @p sym; + * overall parser state in @p p_psm + **/ + void on_parsed_symbol(std::string_view sym, + ParserStateMachine * p_psm); + + /** update state for this syntax after parsing a type-description @p td, + * overall parser state in @p p_psm + **/ + void on_parsed_typedescr(TypeDescr td, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-define-printable-facet printable facet methods **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + /** if true: allow a define-expression here; otherwise reject **/ + bool allow_defs_ = false; + /** if true: expecting either: + * 1a. expression + * 1b. right brace '}', in which case no expression + * if false: expecting only: + * 2a. expression + **/ + bool cxl_on_rightbrace_ = false; + + + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DExpectExprSsm.hpp */ diff --git a/xo-reader2/src/reader2/CMakeLists.txt b/xo-reader2/src/reader2/CMakeLists.txt index 5ce73d67..661aae2e 100644 --- a/xo-reader2/src/reader2/CMakeLists.txt +++ b/xo-reader2/src/reader2/CMakeLists.txt @@ -28,6 +28,8 @@ set(SELF_SRCS ISyntaxStateMachine_DExpectTypeSsm.cpp IPrintable_DExpectTypeSsm.cpp + DExpectExprSsm.cpp + reader2_register_facets.cpp reader2_register_types.cpp ) diff --git a/xo-reader2/src/reader2/DExpectExprSsm.cpp b/xo-reader2/src/reader2/DExpectExprSsm.cpp new file mode 100644 index 00000000..696aa790 --- /dev/null +++ b/xo-reader2/src/reader2/DExpectExprSsm.cpp @@ -0,0 +1,301 @@ +/** @file DExpectExprSsm.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "DExpectExprSsm.hpp" +#include "ParserStateMachine.hpp" + +#ifdef NOT_YET +#include "exprstatestack.hpp" +#include "define_xs.hpp" +#include "lambda_xs.hpp" +#include "if_else_xs.hpp" +#include "paren_xs.hpp" +#include "sequence_xs.hpp" +#include "progress_xs.hpp" +#include "xo/expression/Lambda.hpp" +#include "xo/expression/Constant.hpp" +#include "xo/expression/pretty_expression.hpp" +#endif + +namespace xo { +#ifdef NOT_YET + using xo::scm::Constant; +#endif + + namespace scm { + +#ifdef NOT_YET + std::unique_ptr + expect_expr_xs::make(bool allow_defs, + bool cxl_on_rightbrace) + { + return std::make_unique(expect_expr_xs(allow_defs, + cxl_on_rightbrace)); + + } + + void + expect_expr_xs::start(bool allow_defs, + bool cxl_on_rightbrace, + parserstatemachine * p_psm) + { + p_psm->push_exprstate(expect_expr_xs::make(allow_defs, + cxl_on_rightbrace)); + } + + void + expect_expr_xs::start(parserstatemachine * p_psm) { + start(false /*!allow_defs*/, + false /*!cxl_on_rightbrace*/, + p_psm); + } + + expect_expr_xs::expect_expr_xs(bool allow_defs, + bool cxl_on_rightbrace) + : exprstate(exprstatetype::expect_rhs_expression), + allow_defs_{allow_defs}, + cxl_on_rightbrace_{cxl_on_rightbrace} + {} + + const char * + expect_expr_xs::get_expect_str() const + { + if (allow_defs_) { + return "def|lambda|lparen|lbrace|literal|var"; + } else { + return "lambda|lparen|lbrace|literal|var"; + } + } + + void + expect_expr_xs::on_def_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + if (allow_defs_) { + define_xs::start(p_psm); + } else { + exprstate::on_def_token(tk, p_psm); + } + } + + void + expect_expr_xs::on_lambda_token(const token_type & /*tk*/, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + //constexpr const char * self_name = "exprstate::on_leftparen"; + + lambda_xs::start(p_psm); + } + + void + expect_expr_xs::on_if_token(const token_type & /*tk*/, + parserstatemachine * p_psm) + { + if_else_xs::start(p_psm); + } + + void + expect_expr_xs::on_leftparen_token(const token_type & /*tk*/, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + //constexpr const char * self_name = "exprstate::on_leftparen"; + + /* push lparen_0 to remember to look for subsequent rightparen. */ + paren_xs::start(p_psm); + } + + void + expect_expr_xs::on_leftbrace_token(const token_type & /*tk*/, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + /* push lparen_0 to remember to look for subsequent rightparen. */ + sequence_xs::start(p_psm); + } + + void + expect_expr_xs::on_rightbrace_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + if (cxl_on_rightbrace_) { + auto self = p_psm->pop_exprstate(); + + /* do not call .on_expr(), since '}' cancelled */ + + p_psm->on_rightbrace_token(tk); + } else { + exprstate::on_rightbrace_token(tk, p_psm); + } + } + + void + expect_expr_xs::on_symbol_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log(xtag("tk", tk)); + + constexpr const char * c_self_name = "expect_expr_xs::on_symbol_token"; + + /* various possibilities when looking for rhs expression: + * + * x := y // (1) + * x := f(a) // (2) + * x := f(a,b) // (3) + * + * need lookahead token following symbol to distinguish + * between (1) (symbol completes rhs expression) + * and {(2), (3)} (symbol is function call) + */ + + bp var = p_psm->lookup_var(tk.text()); + + if (!var) { + this->unknown_variable_error(c_self_name, tk, p_psm); + return; + } + + /* e.g. + * def pi = 3.14159265; + * def mypi = pi; + * ^ + * def pi2 = pi * 2; + * ^ + * def y = foo(pi2); + * ^ + */ + progress_xs::start(var.promote(), p_psm); + + #ifdef NOT_YET + p_stack->push_exprstate(exprstate(exprstatetype::expr_progress, + Variable::make(name, type))); +#endif + +#ifdef LATER + p_psm->pop_exprstate(); + p_psm->top_exprstate().on_symbol(tk.text(), + p_stack, p_emit_expr); +#endif + return; + } + + void + expect_expr_xs::on_bool_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + progress_xs::start + (Constant::make(tk.bool_value()), + p_psm); + } + + void + expect_expr_xs::on_i64_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag()), + xtag("tk", tk), + xtag("do", "push progress xs w/ tk value")); + + progress_xs::start + (Constant::make(tk.i64_value()), + p_psm); + } + + void + expect_expr_xs::on_f64_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + //constexpr const char * self_name = "exprstate::on_f64_token"; + + /* e.g. + * def pi = 3.14159265; + * \---tk---/ + */ + progress_xs::start + (Constant::make(tk.f64_value()), + p_psm); + } + + void + expect_expr_xs::on_string_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + /* e.g. + * def msg = "hello, world"; + * \----tk----/ + */ + progress_xs::start + (Constant::make(tk.text()), + p_psm); + } + + void + expect_expr_xs::on_expr(bp expr, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log(xtag("exstype", this->exs_type_), + xtag("expr", expr.promote())); + log && log("pop expect_expr_xs, forward to parent"); + + std::unique_ptr self = p_psm->pop_exprstate(); + + p_psm->on_expr(expr); + } /*on_expr*/ + + void + expect_expr_xs::on_expr_with_semicolon(bp expr, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log(xtag("exstype", this->exs_type_), + xtag("expr", expr.promote())); + log && log("pop expect_expr_xs, forward to parent"); + + std::unique_ptr self = p_psm->pop_exprstate(); + + p_psm->on_expr_with_semicolon(expr); + } /*on_expr_with_semicolon*/ + + void + expect_expr_xs::print(std::ostream & os) const { + os << ""; + } + + bool + expect_expr_xs::pretty_print(const xo::print::ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct(ppii, "expect_expr_xs", + refrtag("allow_defs", allow_defs_), + refrtag("cxl_on_rightbrace", cxl_on_rightbrace_)); + } +#endif + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DExpectExprSsm.cpp */