diff --git a/xo-expression2/include/xo/expression2/DIfElseExpr.hpp b/xo-expression2/include/xo/expression2/DIfElseExpr.hpp index 4a1107ca..8222834a 100644 --- a/xo-expression2/include/xo/expression2/DIfElseExpr.hpp +++ b/xo-expression2/include/xo/expression2/DIfElseExpr.hpp @@ -59,6 +59,12 @@ namespace xo { obj when_true, obj when_false); + /** create empty if-else expression using memory from @p mm **/ + static obj make_empty(obj mm); + + /** create empty if-else expression using memory from @p mm **/ + static DIfElseExpr * _make_empty(obj mm); + ///@} /** @defgroup scm-ifelseexpr-access-methods **/ ///@{ @@ -67,6 +73,10 @@ namespace xo { obj when_true() const noexcept { return when_true_; } obj when_false() const noexcept { return when_false_; } + void assign_test(obj x) { this->test_ = x; } + void assign_when_true(obj x) { this->when_true_ = x; } + void assign_when_false(obj x) { this->when_false_ = x; } + ///@} /** @defgroup scm-ifelseexpr-expression-facet **/ ///@{ diff --git a/xo-expression2/src/expression2/DIfElseExpr.cpp b/xo-expression2/src/expression2/DIfElseExpr.cpp index 0e18114e..d858dfab 100644 --- a/xo-expression2/src/expression2/DIfElseExpr.cpp +++ b/xo-expression2/src/expression2/DIfElseExpr.cpp @@ -57,6 +57,21 @@ namespace xo { when_false); } + obj + DIfElseExpr::make_empty(obj mm) + { + return obj(_make_empty(mm)); + } + + DIfElseExpr * + DIfElseExpr::_make_empty(obj mm) + { + return _make(mm, + obj() /*test*/, + obj() /*when_true*/, + obj() /*when_false*/); + } + void DIfElseExpr::assign_valuetype(TypeDescr td) noexcept { @@ -76,14 +91,33 @@ namespace xo { = FacetRegistry::instance().try_variant(when_false_); - - return ppii.pps()->pretty_struct - (ppii, - "DIfElseExpr", - refrtag("typeref", typeref_), - refrtag("test", test), - refrtag("when_true", when_true), - refrtag("when_false", when_false)); + if (when_false) { + return ppii.pps()->pretty_struct + (ppii, + "DIfElseExpr", + refrtag("typeref", typeref_), + refrtag("test", test), + refrtag("when_true", when_true), + refrtag("when_false", when_false)); + } else if (when_true) { + return ppii.pps()->pretty_struct + (ppii, + "DIfElseExpr", + refrtag("typeref", typeref_), + refrtag("test", test), + refrtag("when_true", when_true)); + } else if (test) { + return ppii.pps()->pretty_struct + (ppii, + "DIfElseExpr", + refrtag("typeref", typeref_), + refrtag("test", test)); + } else { + return ppii.pps()->pretty_struct + (ppii, + "DIfElseExpr", + refrtag("typeref", typeref_)); + } } // ---------------------------------------------------------------- @@ -141,10 +175,13 @@ namespace xo { std::uint32_t IfExpr::pretty_print(const ppindentinfo & ppii) const { + return ppii.pps()->pretty_struct(ppii, "IfExpr"); +#ifdef NOT_YET return ppii.pps()->pretty_struct(ppii, "IfExpr", refrtag("test", test_), refrtag("when_true", when_true_), refrtag("when_false", when_false_)); +#endif } rp diff --git a/xo-reader2/CMakeLists.txt b/xo-reader2/CMakeLists.txt index 43c747f6..a4124f45 100644 --- a/xo-reader2/CMakeLists.txt +++ b/xo-reader2/CMakeLists.txt @@ -86,6 +86,32 @@ xo_add_genfacetimpl( # ---------------------------------------------------------------- +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-syntaxstatemachine-ifelsessm + FACET_PKG xo_reader2 + FACET SyntaxStateMachine + REPR IfElseSsm + INPUT idl/ISyntaxStateMachine_DIfElseSsm.json5 + OUTPUT_HPP_DIR include/xo/reader2 + OUTPUT_IMPL_SUBDIR ssm + OUTPUT_CPP_DIR src/reader2 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-ifelsessm + FACET_PKG xo_printable2 + FACET Printable + REPR Ifelsessm + INPUT idl/IPrintable_DIfElseSsm.json5 + OUTPUT_HPP_DIR include/xo/reader2 + OUTPUT_IMPL_SUBDIR ssm + OUTPUT_CPP_DIR src/reader2 +) + +# ---------------------------------------------------------------- + # note: manual target; generated code committed to git xo_add_genfacetimpl( TARGET xo-reader2-facetimpl-syntaxstatemachine-expectsymbolssm diff --git a/xo-reader2/idl/IPrintable_DIfElseSsm.json5 b/xo-reader2/idl/IPrintable_DIfElseSsm.json5 new file mode 100644 index 00000000..28fab147 --- /dev/null +++ b/xo-reader2/idl/IPrintable_DIfElseSsm.json5 @@ -0,0 +1,13 @@ +{ + mode: "implementation", + includes: [ "", + "" ], + local_types: [], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DIfElseSsm", + using_doxygen: true, + repr: "DIfElseSsm", + doc: [ "implement APrintable for DIfElseSsm" ], +} diff --git a/xo-reader2/idl/ISyntaxStateMachine_DIfElseSsm.json5 b/xo-reader2/idl/ISyntaxStateMachine_DIfElseSsm.json5 new file mode 100644 index 00000000..5e7e828b --- /dev/null +++ b/xo-reader2/idl/ISyntaxStateMachine_DIfElseSsm.json5 @@ -0,0 +1,13 @@ +{ + mode: "implementation", + includes: [ "\"SyntaxStateMachine.hpp\"", + "\"ssm/ISyntaxStateMachine_Xfer.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SyntaxStateMachine.json5", + brief: "provide ASyntaxStateMachine interface for DIfElseSsm", + using_doxygen: true, + repr: "DIfElseSsm", + doc: [ "implement ASyntaxStateMachine for DIfElseSsm" ], +} diff --git a/xo-reader2/include/xo/reader2/DDefineSsm.hpp b/xo-reader2/include/xo/reader2/DDefineSsm.hpp index 9f707fca..6d15c5ee 100644 --- a/xo-reader2/include/xo/reader2/DDefineSsm.hpp +++ b/xo-reader2/include/xo/reader2/DDefineSsm.hpp @@ -113,7 +113,7 @@ namespace xo { syntaxstatetype ssm_type() const noexcept; /** text describing expected/allowed input to this ssm in current state. - * Intended to drive error mesages + * Intended to drive error messages **/ std::string_view get_expect_str() const noexcept; @@ -212,6 +212,7 @@ namespace xo { /** @defgroup scm-define-printable-facet printable facet methods **/ ///@{ + /** pretty-printer support **/ bool pretty(const ppindentinfo & ppii) const; ///@} diff --git a/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp b/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp index 85d4e5e1..b994b498 100644 --- a/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp +++ b/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp @@ -41,6 +41,34 @@ namespace xo { bool allow_defs() const noexcept { return allow_defs_; } bool cxl_on_rightbrace() const noexcept { return cxl_on_rightbrace_; } + ///@} + /** @defgroup scm-expectexpr-methods general methods **/ + ///@{ + + /** step state machine for this syntax on incoming boolean literal token @p tkk + * with overall parser state in @p p_psm + **/ + void on_bool_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming f64 token @p tk, + * overall parser state in @p p_psm + **/ + void on_f64_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming i64 token @p tk, + * overall parser state in @p p_psm + **/ + void on_i64_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax on incoming string token @p tk, + * overall parser state in @p p_psm + **/ + void on_string_token(const Token & tk, + ParserStateMachine * p_psm); + ///@} /** @defgroup scm-expectexpr-ssm-facet syntaxstatemachine facet methods **/ ///@{ @@ -89,30 +117,6 @@ namespace xo { void on_singleassign_token(const Token & tk, ParserStateMachine * p_psm); - /** update state for this syntax on incoming string token @p tk, - * overall parser state in @p p_psm - **/ - void on_string_token(const Token & tk, - ParserStateMachine * p_psm); - - /** update state for this syntax on incoming f64 token @p tk, - * overall parser state in @p p_psm - **/ - void on_f64_token(const Token & tk, - ParserStateMachine * p_psm); - - /** update state for this syntax on incoming i64 token @p tk, - * overall parser state in @p p_psm - **/ - void on_i64_token(const Token & tk, - ParserStateMachine * p_psm); - - /** update state for this syntax on incoming bool token @p tk, - * overall parser state in @p p_psm - **/ - void on_bool_token(const Token & tk, - ParserStateMachine * p_psm); - /** update state for this syntax on incoming semicolon token @p tk, * overall parser state in @p p_psm **/ diff --git a/xo-reader2/include/xo/reader2/DIfElseSsm.hpp b/xo-reader2/include/xo/reader2/DIfElseSsm.hpp new file mode 100644 index 00000000..9b3e5d17 --- /dev/null +++ b/xo-reader2/include/xo/reader2/DIfElseSsm.hpp @@ -0,0 +1,221 @@ +/** @file DIfElseSsm.hpp + * + * @author Roland Conybeare, Jul 2025 + **/ + +#pragma once + +#include +#include "ParserStateMachine.hpp" +#include "syntaxstatetype.hpp" +#include +#include +#include +//#include "exprstate.hpp" +//#include "xo/indentlog/print/ppdetail_atomic.hpp" + +namespace xo { + namespace scm { + /** + * if test-expr then then-expr else else-expr ; + * ^ ^ ^ ^ ^ ^ ^ + * | | | | | | | + * | if_1 if_2 if_3 if_4 if_5 if_6 + * if_0 + * + * if_0 --on_if_token()--> if_1 + * if_1 --on_expr()--> if_2 + * if_2 --on_then_token()--> if_3 + * if_3 --on_expr()--> if_4 + * if_4 --on_else_token()--> if_5 + * --on_semicolon_token()--> (done) + * if_5 --on_expr()-->if_6 + * if_6 --on_semicolon_token()--> (done) + **/ + enum class ifexprstatetype { + invalid = -1, + + if_0, + if_1, + if_2, + if_3, + if_4, + if_5, + if_6, + + N, + }; + + extern const char * ifexprstatetype_descr(ifexprstatetype x); + + std::ostream & + operator<<(std::ostream & os, ifexprstatetype x); + + /** @class DIfElseSsm + * @brief syntax state machine for parsing a conditional expression + **/ + class DIfElseSsm { + public: + using AAllocator = xo::mm::AAllocator; + using DArena = xo::mm::DArena; + using TypeDescr = xo::reflect::TypeDescr; + using ppindentinfo = xo::print::ppindentinfo; + + public: + /** @defgroup scm-ifelsessm-expression-ctors constructors **/ + ///@{ + explicit DIfElseSsm(DIfElseExpr * ifelse_expr); + +#ifdef NOT_YET + /** create instance using memory from @p parser_mm + * with initial scaffold @p ifelse_expr + **/ + static obj make(DArena & parser_mm, + DIfElseExpr * ifelse_expr); +#endif + + /** create instance using memory from @p parser_mm + * with initial scaffold @p ifelse_expr. + **/ + static DIfElseSsm * _make(DArena & parser_mm, + DIfElseExpr * ifelse_expr); + + /** start nested parser for an if-else expression + * on top of parser state machine @p p_psm. + * Use @p parser_mm to allocate syntax state machines + * (i.e. temporary memory needed only during parsing) + * Use @p expr_mm to allocate expressions. + **/ + static void start(DArena & parser_mm, + obj expr_mm, + ParserStateMachine * p_psm); + ///@} + /** @defgroup scm-ifelsessm-expression-methods general methods **/ + ///@{ + + /** operate state machine on if-token input @p tk, + * with overall parser state in @p p_psm + **/ + void on_if_token(const Token & tk, + ParserStateMachine * p_psm); + + /** operate state machine on then-token input @p tk, + * with overall parser state in @p p_psm + **/ + void on_then_token(const Token & tk, + ParserStateMachine * p_psm); + + /** operate state machine on else-token input @p tk, + * with overall parser state in @p p_psm + **/ + void on_else_token(const Token & tk, + ParserStateMachine * p_psm); + + /** victory: report completed @ref if_expr_ to parent ssm, + * after removing this ssm from parser stack + **/ + void finish_and_continue(ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-ifelsessm-expression-facet expression facet methods **/ + ///@{ + + /** identifies this state machine **/ + syntaxstatetype ssm_type() const noexcept; + + /** text describing expected/allowed input to this ssm in current state. + * Intended to drive error messages + **/ + std::string_view get_expect_str() const noexcept; + + /** operate state machine for this syntax on incoming token @p tk + * with overall parser state in @p p_psm + **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm); + + /** operate state machine for this syntax on incoming semicolon token @p tk + * with overall parser state in @p p_psm + **/ + void on_semicolon_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state for this syntax after parsing an expression @p expr, + * overall parser state in @p p_psm. + **/ + void on_parsed_expression(obj expr, + 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); + + /** update state for this syntax after parsing an expression @p expr, + * followed by semicolon, + * with overall parser state in @p p_psm. + **/ + void on_parsed_expression_with_semicolon(obj expr, + ParserStateMachine * p_psm); + + /** update state for this syntax after parsing a symbol @p sym, + * with overall parser state in @p p_psm + **/ + void on_parsed_symbol(std::string_view sym, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-ifelsessm-printable-facet printable facet methods **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + +#ifdef NOT_YET + // ----- inherited from exprstate ----- + + virtual const char * get_expect_str() const override; + + virtual void on_if_token(const token_type & tk, + parserstatemachine * p_psm) override; + virtual void on_then_token(const token_type & tk, + parserstatemachine * p_psm) override; + virtual void on_else_token(const token_type & tk, + parserstatemachine * p_psm) override; + virtual void on_semicolon_token(const token_type & tk, + parserstatemachine * p_psm) override; + virtual void on_rightbrace_token(const token_type & tk, + parserstatemachine * p_psm) override; + + virtual void on_expr(bp expr, + parserstatemachine * p_psm) override; + virtual void on_expr_with_semicolon(bp expr, + parserstatemachine * p_psm) override; + + virtual void print(std::ostream & os) const override; +#endif + + private: +#ifdef NOT_YET + static std::unique_ptr make(); + + /** exit this exprstate, + * and deliver @ref if_expr_ to parent exprstate + **/ + void finish_and_continue(parserstatemachine * p_psm); +#endif + + private: + ifexprstatetype ifstate_ = ifexprstatetype::invalid; + /** scaffold ifelse-expression here. + * This will eventually be the output of this ssm + **/ + obj if_expr_; + + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DIfElseSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/DProgressSsm.hpp b/xo-reader2/include/xo/reader2/DProgressSsm.hpp index 31b3a55d..788c10ca 100644 --- a/xo-reader2/include/xo/reader2/DProgressSsm.hpp +++ b/xo-reader2/include/xo/reader2/DProgressSsm.hpp @@ -126,6 +126,17 @@ namespace xo { **/ obj assemble_expr(ParserStateMachine * p_psm); + /** @defgroup scm-progressssm-methods general methods **/ + ///@{ + + void on_if_token(const Token & tk, + ParserStateMachine * p_psm); + void on_then_token(const Token & tk, + ParserStateMachine * p_psm); + void on_else_token(const Token & tk, + ParserStateMachine * p_psm); + + ///@} /** @defgroup scm-progressssm-ssm-facet syntaxstatemachine facet methods **/ /// @{ @@ -139,8 +150,6 @@ namespace xo { ParserStateMachine * p_psm); void on_def_token(const Token & tk, ParserStateMachine * p_psm); - void on_if_token(const Token & tk, - ParserStateMachine * p_psm); void on_colon_token(const Token & tk, ParserStateMachine * p_psm); void on_singleassign_token(const Token & tk, diff --git a/xo-reader2/include/xo/reader2/ssm/IPrintable_DIfElseSsm.hpp b/xo-reader2/include/xo/reader2/ssm/IPrintable_DIfElseSsm.hpp new file mode 100644 index 00000000..e9a40c75 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/IPrintable_DIfElseSsm.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DIfElseSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DIfElseSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DIfElseSsm.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DIfElseSsm.hpp" + +namespace xo { namespace scm { class IPrintable_DIfElseSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DIfElseSsm + **/ + class IPrintable_DIfElseSsm { + public: + /** @defgroup scm-printable-difelsessm-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-difelsessm-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DIfElseSsm & self, const ppindentinfo & ppii); + + // non-const methods + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DIfElseSsm.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DIfElseSsm.hpp new file mode 100644 index 00000000..2101b8e1 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DIfElseSsm.hpp @@ -0,0 +1,73 @@ +/** @file ISyntaxStateMachine_DIfElseSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DIfElseSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DIfElseSsm.json5] + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "DIfElseSsm.hpp" + +namespace xo { namespace scm { class ISyntaxStateMachine_DIfElseSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISyntaxStateMachine_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISyntaxStateMachine_DIfElseSsm + **/ + class ISyntaxStateMachine_DIfElseSsm { + public: + /** @defgroup scm-syntaxstatemachine-difelsessm-type-traits **/ + ///@{ + using TypeDescr = xo::scm::ASyntaxStateMachine::TypeDescr; + using Copaque = xo::scm::ASyntaxStateMachine::Copaque; + using Opaque = xo::scm::ASyntaxStateMachine::Opaque; + ///@} + /** @defgroup scm-syntaxstatemachine-difelsessm-methods **/ + ///@{ + // const methods + /** identify a type of syntax state machine **/ + static syntaxstatetype ssm_type(const DIfElseSsm & self) noexcept; + /** text describing expected/allowed input to this ssm in current state **/ + static std::string_view get_expect_str(const DIfElseSsm & self) noexcept; + + // non-const methods + /** operate state machine for incoming token @p tk **/ + static void on_token(DIfElseSsm & self, const Token & tk, ParserStateMachine * p_psm); + /** update stat machine for incoming parsed symbol @p sym **/ + static void on_parsed_symbol(DIfElseSsm & self, std::string_view sym, ParserStateMachine * p_psm); + /** operate state machine for incoming type description @p td **/ + static void on_parsed_typedescr(DIfElseSsm & self, TypeDescr td, ParserStateMachine * p_psm); + /** update state machine for incoming parsed expression @p expr **/ + static void on_parsed_expression(DIfElseSsm & self, obj expr, ParserStateMachine * p_psm); + /** update state machine for incoming parsed expression @p expr followed by semicolon **/ + static void on_parsed_expression_with_semicolon(DIfElseSsm & self, obj expr, ParserStateMachine * p_psm); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/syntaxstatetype.hpp b/xo-reader2/include/xo/reader2/syntaxstatetype.hpp index d7340b25..796743d7 100644 --- a/xo-reader2/include/xo/reader2/syntaxstatetype.hpp +++ b/xo-reader2/include/xo/reader2/syntaxstatetype.hpp @@ -33,6 +33,9 @@ namespace xo { /** handle define-expression. See @ref DDefineSsm **/ defexpr, + /** handle ifelse-expression. See @ref DIfElseSsm **/ + ifelseexpr, + /** rhs expression. state exists to achieve 1-token lookahead **/ progress, diff --git a/xo-reader2/src/reader2/CMakeLists.txt b/xo-reader2/src/reader2/CMakeLists.txt index e18cce73..2ab9d917 100644 --- a/xo-reader2/src/reader2/CMakeLists.txt +++ b/xo-reader2/src/reader2/CMakeLists.txt @@ -25,6 +25,10 @@ set(SELF_SRCS ISyntaxStateMachine_DDefineSsm.cpp IPrintable_DDefineSsm.cpp + DIfElseSsm.cpp + ISyntaxStateMachine_DIfElseSsm.cpp + IPrintable_DIfElseSsm.cpp + DExpectSymbolSsm.cpp ISyntaxStateMachine_DExpectSymbolSsm.cpp IPrintable_DExpectSymbolSsm.cpp diff --git a/xo-reader2/src/reader2/DExpectExprSsm.cpp b/xo-reader2/src/reader2/DExpectExprSsm.cpp index 7a82ad1c..4f61df72 100644 --- a/xo-reader2/src/reader2/DExpectExprSsm.cpp +++ b/xo-reader2/src/reader2/DExpectExprSsm.cpp @@ -11,8 +11,14 @@ #include "syntaxstatetype.hpp" #include #include +#include +#include +#include +#include #include #include +#include +#include #include #include @@ -233,12 +239,21 @@ namespace xo { } void - DExpectExprSsm::on_string_token(const Token & tk, - ParserStateMachine * p_psm) + DExpectExprSsm::on_bool_token(const Token & tk, + ParserStateMachine * p_psm) { - p_psm->illegal_input_on_token("DExpectExprSsm::on_string_token", - tk, - this->get_expect_str()); + auto flag = DBoolean::box(p_psm->expr_alloc(), + tk.bool_value()); + + auto expr = DConstant::make(p_psm->expr_alloc(), flag); + + // DProgressSsm responsible for resolving cases like + // true; + // true && false; + + DProgressSsm::start(p_psm->parser_alloc(), + expr, + p_psm); } void @@ -268,18 +283,48 @@ namespace xo { DExpectExprSsm::on_i64_token(const Token & tk, ParserStateMachine * p_psm) { - p_psm->illegal_input_on_token("DExpectExprSsm::on_i64_token", - tk, - this->get_expect_str()); + auto i64o = DInteger::box(p_psm->expr_alloc(), + tk.i64_value()); + + auto expr = DConstant::make(p_psm->expr_alloc(), i64o); + + // DProgressSsm responsible for resolving cases like + // 1, + // 1; + // 1 + 2; + // 1 + 2 .. // could be followed by infix + // 1 + 2 * 3; + // 1 + 2 * 3 .. // could be followed by infix + // 1 * (2 + 3) + + DProgressSsm::start(p_psm->parser_alloc(), + expr, + p_psm); } void - DExpectExprSsm::on_bool_token(const Token & tk, - ParserStateMachine * p_psm) + DExpectExprSsm::on_string_token(const Token & tk, + ParserStateMachine * p_psm) { - p_psm->illegal_input_on_token("DExpectExprSsm::on_bool_token", - tk, - this->get_expect_str()); + auto str = DString::from_str(p_psm->expr_alloc(), + tk.text()); + auto str_o = obj(str); + + auto expr = DConstant::make(p_psm->expr_alloc(), str_o); + + /* e.g. + * def msg = "hello, world"; + * \----tk----/ + * + * DProgressSsm responsible for operators that apply to string + * "foo"; + * "foo" <= "bar" + * "foo" + ", she said"; + */ + + DProgressSsm::start(p_psm->parser_alloc(), + expr, + p_psm); } void @@ -313,9 +358,8 @@ namespace xo { DExpectExprSsm::on_parsed_expression(obj expr, ParserStateMachine * p_psm) { - p_psm->illegal_parsed_expression("DExpectExprSsm::on_parsed_expression", - expr, - this->get_expect_str()); + p_psm->pop_ssm(); + p_psm->on_parsed_expression(expr); } void @@ -464,62 +508,6 @@ namespace xo { 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) diff --git a/xo-reader2/src/reader2/DExprSeqState.cpp b/xo-reader2/src/reader2/DExprSeqState.cpp index e926565d..cfd92683 100644 --- a/xo-reader2/src/reader2/DExprSeqState.cpp +++ b/xo-reader2/src/reader2/DExprSeqState.cpp @@ -7,6 +7,7 @@ #include "DDefineSsm.hpp" #include "ssm/ISyntaxStateMachine_DExprSeqState.hpp" #include +#include #include #include #include @@ -246,20 +247,20 @@ namespace xo { { switch (seqtype_) { case exprseqtype::toplevel_interactive: - p_psm->illegal_input_on_token("DExprSeqState::on_if_token", - tk, - this->get_expect_str()); - //assert(false); // DfElseState::start(p_psm); - break; + DIfElseSsm::start(p_psm->parser_alloc(), + p_psm->expr_alloc(), + p_psm); + return; 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; } + + p_psm->illegal_input_on_token("DExprSeqState::on_if_token", + tk, + this->get_expect_str()); } void diff --git a/xo-reader2/src/reader2/DIfElseSsm.cpp b/xo-reader2/src/reader2/DIfElseSsm.cpp new file mode 100644 index 00000000..eca02910 --- /dev/null +++ b/xo-reader2/src/reader2/DIfElseSsm.cpp @@ -0,0 +1,530 @@ +/** @file DIfElseSsm.cpp + * + * @author Roland Conybeare, Jul 2025 + **/ + +#include "DIfElseSsm.hpp" +#include "ssm/ISyntaxStateMachine_DIfElseSsm.hpp" +#include "ssm/IPrintable_DDefineSsm.hpp" +#include "DExpectExprSsm.hpp" +#include +#include +#include +//#include "exprstatestack.hpp" +//#include "parserstatemachine.hpp" +//#include "expect_expr_xs.hpp" +//#include "xo/indentlog/print/ppdetail_atomic.hpp" + +namespace xo { + using xo::print::APrintable; + using xo::facet::FacetRegistry; + using xo::facet::with_facet; + using xo::reflect::typeseq; + + namespace scm { + // ----- ifexprstatetype ----- + + const char * + ifexprstatetype_descr(ifexprstatetype x) { + switch (x) { + case ifexprstatetype::invalid: return "invalid"; + case ifexprstatetype::if_0: return "if_0"; + case ifexprstatetype::if_1: return "if_1"; + case ifexprstatetype::if_2: return "if_2"; + case ifexprstatetype::if_3: return "if_3"; + case ifexprstatetype::if_4: return "if_4"; + case ifexprstatetype::if_5: return "if_5"; + case ifexprstatetype::if_6: return "if_6"; + case ifexprstatetype::N: break; + } + + return "ifexprstatetype?"; + } + + std::ostream & + operator<<(std::ostream & os, ifexprstatetype x) { + os << ifexprstatetype_descr(x); + return os; + } + + // ----- DIfElseSsm ----- + + DIfElseSsm::DIfElseSsm(DIfElseExpr * ifelse_expr) : ifstate_{ifexprstatetype::if_0}, + if_expr_{ifelse_expr} + {} + + DIfElseSsm * + DIfElseSsm::_make(DArena & mm, + DIfElseExpr * ifelse_expr) + { + void * mem = mm.alloc(typeseq::id(), + sizeof(DIfElseSsm)); + + return new (mem) DIfElseSsm(ifelse_expr); + } + + void + DIfElseSsm::start(DArena & parser_mm, + obj expr_mm, + ParserStateMachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + DIfElseExpr * if_expr = DIfElseExpr::_make_empty(expr_mm); + DIfElseSsm * if_ssm = DIfElseSsm::_make(parser_mm, if_expr); + + obj ssm + = with_facet::mkobj(if_ssm); + + p_psm->push_ssm(ssm); + + // note: triggers poly dispatch + p_psm->on_token(Token::if_token()); + } + + syntaxstatetype + DIfElseSsm::ssm_type() const noexcept + { + return syntaxstatetype::ifelseexpr; + } + + std::string_view + DIfElseSsm::get_expect_str() const noexcept + { + /** + * if test-expr then then-expr else else-expr ; + * ^ ^ ^ ^ ^ ^ ^ + * | | | | | | | + * | if_1 if_2 if_3 if_4 if_5 if_6 + * if_0 + * + * if_0 --on_if_token()--> if_1 + * if_1 --on_expr()--> if_2 + * if_2 --on_then_token()--> if_3 + * if_3 --on_expr()--> if_4 + * if_4 --on_else_token()--> if_5 + * --on_semicolon_token()--> (done) + * if_5 --on_expr()-->if_6 + * if_6 --on_semicolon_token()--> (done) + **/ + switch (this->ifstate_) { + case ifexprstatetype::invalid: + case ifexprstatetype::N: + assert(false); // unreachable + break; + case ifexprstatetype::if_0: + return "if"; + case ifexprstatetype::if_1: + return "expression"; + case ifexprstatetype::if_2: + return "then"; + case ifexprstatetype::if_3: + return "expression"; + case ifexprstatetype::if_4: + return "else|semicolon"; + case ifexprstatetype::if_5: + return "expression"; + case ifexprstatetype::if_6: + return "semicolon"; + } + + return "?expect"; + } + + void + DIfElseSsm::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_symbol: + case tokentype::tk_def: + break; + case tokentype::tk_if: + this->on_if_token(tk, p_psm); + return; + case tokentype::tk_then: + this->on_then_token(tk, p_psm); + return; + case tokentype::tk_else: + this->on_else_token(tk, p_psm); + return; + 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_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_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; + } + + p_psm->illegal_input_on_token("DIfElseSsm::on_token", + tk, + this->get_expect_str()); + } + +#ifdef NOT_YET + // ----- if_else_xs ----- + + if_else_xs::if_else_xs(rp if_expr) + : exprstate(exprstatetype::ifexpr), + ifxs_type_{ifexprstatetype::if_0}, + if_expr_{std::move(if_expr)} + {} +#endif + + void + DIfElseSsm::on_if_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log("ifstate", ifstate_); + + if (ifstate_ == ifexprstatetype::if_0) { + this->ifstate_ = ifexprstatetype::if_1; + + DExpectExprSsm::start(p_psm->parser_alloc(), + p_psm); + return; + } + + p_psm->illegal_input_on_token("DIfElseSsm::on_if_token", + tk, + this->get_expect_str()); + } + + void + DIfElseSsm::on_then_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log("ifstate", ifstate_); + + if (ifstate_ == ifexprstatetype::if_2) { + this->ifstate_ = ifexprstatetype::if_3; + + DExpectExprSsm::start(p_psm->parser_alloc(), p_psm); + return; + } + + p_psm->illegal_input_on_token("DIfElseSsm::on_then_token", + tk, + this->get_expect_str()); + } + +#ifdef NOT_YET + void + if_else_xs::on_else_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log("ifxs_type", ifxs_type_); + + if (this->ifxs_type_ == ifexprstatetype::if_4) { + this->ifxs_type_ = ifexprstatetype::if_5; + + expect_expr_xs::start(p_psm); + return; + } + + constexpr const char * c_self_name = "if_else_xs::on_else_token"; + const char * exp = this->get_expect_str(); + + this->illegal_input_on_token(c_self_name, tk, exp, p_psm); + } +#endif + + void + DIfElseSsm::on_else_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log("ifstate", ifstate_); + + if (ifstate_ == ifexprstatetype::if_4) { + this->ifstate_ = ifexprstatetype::if_5; + + DExpectExprSsm::start(p_psm->parser_alloc(), p_psm); + return; + } + + p_psm->illegal_input_on_token("DIfElseSsm::on_else_token", + tk, + this->get_expect_str()); + } + +#ifdef NOT_YET + void + if_else_xs::finish_and_continue(parserstatemachine * p_psm) + { + rp if_expr = this->if_expr_; + std::unique_ptr self = p_psm->pop_exprstate(); + + if (this->ifxs_type_ == ifexprstatetype::if_4) { + /* if no else-branch, then if-expr can't have valuetype */ + if_expr->assign_valuetype(nullptr); + } + + p_psm->top_exprstate().on_expr(if_expr, p_psm); + } +#endif + + void + DIfElseSsm::finish_and_continue(ParserStateMachine * p_psm) + { + p_psm->pop_ssm(); + + // rp if_expr = this->if_expr_; + // std::unique_ptr self = p_psm->pop_exprstate(); + + p_psm->on_parsed_expression(if_expr_); + } + +#ifdef NOT_YET + void + if_else_xs::on_rightbrace_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + this->finish_and_continue(p_psm); + p_psm->on_rightbrace_token(tk); + } + + void + if_else_xs::on_semicolon_token(const token_type & tk, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log("ifxs_type", ifxs_type_); + + const char * c_self_name = "if_else_xs::on_semicolon_token"; + + switch (this->ifxs_type_) { + case ifexprstatetype::invalid: + case ifexprstatetype::if_0: + case ifexprstatetype::n_ifexprstatetype: + // unreachable + assert(false); + break; + + case ifexprstatetype::if_1: + case ifexprstatetype::if_2: + case ifexprstatetype::if_3: + case ifexprstatetype::if_5: + this->illegal_input_on_token(c_self_name, tk, get_expect_str(), p_psm); + break; + case ifexprstatetype::if_4: + case ifexprstatetype::if_6: { + this->finish_and_continue(p_psm); + break; + } + } + } +#endif + + void + DIfElseSsm::on_semicolon_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log("ifstate", ifstate_); + + switch (ifstate_) { + case ifexprstatetype::invalid: + case ifexprstatetype::N: + // unreachable + assert(false); + break; + + case ifexprstatetype::if_0: + case ifexprstatetype::if_1: + case ifexprstatetype::if_2: + case ifexprstatetype::if_3: + case ifexprstatetype::if_5: + break; + case ifexprstatetype::if_4: + case ifexprstatetype::if_6: + this->finish_and_continue(p_psm); + return; + } + + p_psm->illegal_input_on_token("DIfElseSsm::on_semicolon_token", + tk, this->get_expect_str()); + + } + +#ifdef NOT_YET + void + if_else_xs::on_expr(bp expr, + parserstatemachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + log && log(xtag("ifxs_type", ifxs_type_)); + + switch (this->ifxs_type_) { + case ifexprstatetype::invalid: + case ifexprstatetype::if_0: + case ifexprstatetype::n_ifexprstatetype: + assert(false); // unreachable + return; + case ifexprstatetype::if_1: + if_expr_->assign_test(expr.promote()); + ifxs_type_ = ifexprstatetype::if_2; + return; + case ifexprstatetype::if_2: + /** error: expecting 'then' **/ + break; + case ifexprstatetype::if_3: + if_expr_->assign_when_true(expr.promote()); + ifxs_type_ = ifexprstatetype::if_4; + return; + case ifexprstatetype::if_4: + /** error: expecting 'else' or ';' **/ + break; + case ifexprstatetype::if_5: + if_expr_->assign_when_false(expr.promote()); + ifxs_type_ = ifexprstatetype::if_6; + return; + case ifexprstatetype::if_6: + /** error: expecting ';' **/ + break; + } + + constexpr const char* c_self_name = "if_else_xs::on_expr"; + const char * exp = get_expect_str(); + + this->illegal_input_on_expr(c_self_name, expr, exp, p_psm); + } + +#endif + + void + DIfElseSsm::on_parsed_expression(obj expr, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + log && log(xtag("ifstate", ifstate_)); + + // if (ifstate_ == ...) { .... return; } + + switch (ifstate_) { + case ifexprstatetype::invalid: + case ifexprstatetype::N: + assert(false); + break; + case ifexprstatetype::if_0: + // should be unreachable + break; + case ifexprstatetype::if_1: + if_expr_.data()->assign_test(expr); + this->ifstate_ = ifexprstatetype::if_2; + return; + case ifexprstatetype::if_2: + // error: expecting "then" token here + break; + case ifexprstatetype::if_3: + if_expr_.data()->assign_when_true(expr); + this->ifstate_ = ifexprstatetype::if_4; + return; + case ifexprstatetype::if_4: + // error: expecting "else" or ";" + break; + case ifexprstatetype::if_5: + if_expr_.data()->assign_when_false(expr); + this->ifstate_ = ifexprstatetype::if_6; + return; + case ifexprstatetype::if_6: + // error: expecting ";" + break; + } + + p_psm->illegal_parsed_expression("DIfElseSsm::on_parsed_expression", + expr, + this->get_expect_str()); + } + + void + DIfElseSsm::on_parsed_expression_with_semicolon(obj expr, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + this->on_parsed_expression(expr, p_psm); + this->on_semicolon_token(Token::semicolon_token(), p_psm); + } + + void + DIfElseSsm::on_parsed_symbol(std::string_view sym, + ParserStateMachine * p_psm) + { + p_psm->illegal_input_on_symbol("DIfElseSsm::on_parsed_symbol", + sym, + this->get_expect_str()); + } + + void + DIfElseSsm::on_parsed_typedescr(TypeDescr td, + ParserStateMachine * p_psm) + { + p_psm->illegal_input_on_typedescr("DIfElseSsm::on_parsed_typedescr", + td, + this->get_expect_str()); + } + + bool + DIfElseSsm::pretty(const ppindentinfo & ppii) const + { + auto expr + = FacetRegistry::instance().variant(if_expr_); + assert(expr.data()); + (void)expr; + + return ppii.pps()->pretty_struct + (ppii, + "DIfElseSsm", + refrtag("ifstate", ifstate_), + refrtag("if_expr", expr)); + } + + } /*namespace scm*/ +} /*namespace xo*/ diff --git a/xo-reader2/src/reader2/DProgressSsm.cpp b/xo-reader2/src/reader2/DProgressSsm.cpp index 76574c7b..e773f9a7 100644 --- a/xo-reader2/src/reader2/DProgressSsm.cpp +++ b/xo-reader2/src/reader2/DProgressSsm.cpp @@ -230,6 +230,14 @@ namespace xo { this->on_if_token(tk, p_psm); return; + case tokentype::tk_then: + this->on_then_token(tk, p_psm); + return; + + case tokentype::tk_else: + this->on_else_token(tk, p_psm); + return; + case tokentype::tk_colon: this->on_colon_token(tk, p_psm); return; @@ -288,8 +296,7 @@ namespace xo { case tokentype::tk_cmpne: case tokentype::tk_type: case tokentype::tk_lambda: - case tokentype::tk_then: - case tokentype::tk_else: + break; case tokentype::tk_let: case tokentype::tk_in: case tokentype::tk_end: @@ -329,6 +336,42 @@ namespace xo { this->get_expect_str()); } + void + DProgressSsm::on_then_token(const Token & tk, + ParserStateMachine * p_psm) + { + scope log(XO_DEBUG(p_psm->debug_flag())); + + (void)tk; + + obj expr = this->assemble_expr(p_psm); + + p_psm->pop_ssm(); // completes self + + // TODO: perhaps need to generalize on_parsed_expression_with_semicolon() ..? + p_psm->on_parsed_expression(expr); + p_psm->on_token(tk); + } + + void + DProgressSsm::on_else_token(const Token & tk, + ParserStateMachine * p_psm) + { + // note: common with .on_then_token() + + scope log(XO_DEBUG(p_psm->debug_flag())); + + (void)tk; + + obj expr = this->assemble_expr(p_psm); + + p_psm->pop_ssm(); // completes self + + // TODO: perhaps need to generalize on_parsed_expression_with_semicolon() ..? + p_psm->on_parsed_expression(expr); + p_psm->on_token(tk); + } + void DProgressSsm::on_colon_token(const Token & tk, ParserStateMachine * p_psm) @@ -466,9 +509,7 @@ namespace xo { { obj expr_pr = FacetRegistry::instance().variant(expr); - assert(expr_pr); - log && log(xtag("expr", expr_pr)); } @@ -979,28 +1020,6 @@ namespace xo { p_psm->top_exprstate().on_rightparen_token(tk, p_psm); } - void - progress_xs::on_then_token(const token_type & tk, - parserstatemachine * p_psm) - { - scope log(XO_DEBUG(p_psm->debug_flag())); - - rp expr = this->assemble_expr(p_psm); - - log && log(xtag("assembled-expr", expr)); - - std::unique_ptr self = p_psm->pop_exprstate(); - - p_psm->on_expr(expr); - p_psm->on_then_token(tk); - - /* control here on input like: - * - * if a > b then.. - * - */ - } - void progress_xs::on_else_token(const token_type & tk, parserstatemachine * p_psm) @@ -1120,7 +1139,7 @@ namespace xo { bool DProgressSsm::pretty(const xo::print::ppindentinfo & ppii) const { - scope log(XO_DEBUG(true)); + scope log(XO_DEBUG(false)); log && log(xtag("lhs_.tseq", lhs_._typeseq())); log && log(xtag("rhs_.tseq", rhs_._typeseq())); diff --git a/xo-reader2/src/reader2/IPrintable_DIfElseSsm.cpp b/xo-reader2/src/reader2/IPrintable_DIfElseSsm.cpp new file mode 100644 index 00000000..f2aebf7c --- /dev/null +++ b/xo-reader2/src/reader2/IPrintable_DIfElseSsm.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DIfElseSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DIfElseSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DIfElseSsm.json5] +**/ + +#include "ssm/IPrintable_DIfElseSsm.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DIfElseSsm::pretty(const DIfElseSsm & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DIfElseSsm.cpp */ \ No newline at end of file diff --git a/xo-reader2/src/reader2/ISyntaxStateMachine_DIfElseSsm.cpp b/xo-reader2/src/reader2/ISyntaxStateMachine_DIfElseSsm.cpp new file mode 100644 index 00000000..66633e88 --- /dev/null +++ b/xo-reader2/src/reader2/ISyntaxStateMachine_DIfElseSsm.cpp @@ -0,0 +1,59 @@ +/** @file ISyntaxStateMachine_DIfElseSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [/home/roland/proj/xo-umbrella2-claude1/xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DIfElseSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DIfElseSsm.json5] +**/ + +#include "ssm/ISyntaxStateMachine_DIfElseSsm.hpp" + +namespace xo { + namespace scm { + auto + ISyntaxStateMachine_DIfElseSsm::ssm_type(const DIfElseSsm & self) noexcept -> syntaxstatetype + { + return self.ssm_type(); + } + + auto + ISyntaxStateMachine_DIfElseSsm::get_expect_str(const DIfElseSsm & self) noexcept -> std::string_view + { + return self.get_expect_str(); + } + + auto + ISyntaxStateMachine_DIfElseSsm::on_token(DIfElseSsm & self, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_token(tk, p_psm); + } + auto + ISyntaxStateMachine_DIfElseSsm::on_parsed_symbol(DIfElseSsm & self, std::string_view sym, ParserStateMachine * p_psm) -> void + { + self.on_parsed_symbol(sym, p_psm); + } + auto + ISyntaxStateMachine_DIfElseSsm::on_parsed_typedescr(DIfElseSsm & self, TypeDescr td, ParserStateMachine * p_psm) -> void + { + self.on_parsed_typedescr(td, p_psm); + } + auto + ISyntaxStateMachine_DIfElseSsm::on_parsed_expression(DIfElseSsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression(expr, p_psm); + } + auto + ISyntaxStateMachine_DIfElseSsm::on_parsed_expression_with_semicolon(DIfElseSsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression_with_semicolon(expr, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_DIfElseSsm.cpp */ \ No newline at end of file diff --git a/xo-reader2/src/reader2/reader2_register_facets.cpp b/xo-reader2/src/reader2/reader2_register_facets.cpp index ab0ebe43..712f5998 100644 --- a/xo-reader2/src/reader2/reader2_register_facets.cpp +++ b/xo-reader2/src/reader2/reader2_register_facets.cpp @@ -11,6 +11,9 @@ #include #include +#include +#include + #include #include @@ -45,6 +48,9 @@ namespace xo { FacetRegistry::register_impl(); FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); FacetRegistry::register_impl(); @@ -59,6 +65,7 @@ namespace xo { log && log(xtag("DExprSeqState.tseq", typeseq::id())); log && log(xtag("DDefineSsm.tseq", typeseq::id())); + log && log(xtag("DIfElseSsm.tseq", typeseq::id())); log && log(xtag("DExpectSymbolSsm.tseq", typeseq::id())); log && log(xtag("DExpectTypeSsm.tseq", typeseq::id())); log && log(xtag("DExpectExprSsm.tseq", typeseq::id())); diff --git a/xo-reader2/src/reader2/syntaxstatetype.cpp b/xo-reader2/src/reader2/syntaxstatetype.cpp index 716c3d7d..1100bdb3 100644 --- a/xo-reader2/src/reader2/syntaxstatetype.cpp +++ b/xo-reader2/src/reader2/syntaxstatetype.cpp @@ -23,6 +23,8 @@ namespace xo { return "expect-rhs-expression"; case syntaxstatetype::defexpr: return "defexpr"; + case syntaxstatetype::ifelseexpr: + return "ifelseexpr"; case syntaxstatetype::progress: return "progress"; case syntaxstatetype::N: diff --git a/xo-reader2/utest/SchematikaParser.test.cpp b/xo-reader2/utest/SchematikaParser.test.cpp index 895aed10..0f8c1a19 100644 --- a/xo-reader2/utest/SchematikaParser.test.cpp +++ b/xo-reader2/utest/SchematikaParser.test.cpp @@ -84,7 +84,7 @@ namespace xo { TEST_CASE("SchematikaParser-batch-def", "[reader2][SchematikaParser]") { - constexpr bool c_debug_flag = true; + constexpr bool c_debug_flag = false; scope log(XO_DEBUG(c_debug_flag)); ArenaConfig config; @@ -98,6 +98,12 @@ namespace xo { parser.begin_batch_session(); + /** Walkthrough parsing input equivalent to: + * + * def foo : f64 = 3.141593 ; + * + **/ + { auto & result = parser.on_token(Token::def_token()); @@ -193,6 +199,9 @@ namespace xo { TEST_CASE("SchematikaParser-interactive-if", "[reader2][SchematikaParser]") { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + ArenaConfig config; config.name_ = "test-arena"; config.size_ = 16 * 1024; @@ -204,16 +213,99 @@ namespace xo { parser.begin_interactive_session(); - auto & result = parser.on_token(Token::if_token()); + /** Walkthrough parsing input equivalent to: + * + * if true then 777 else "fooey" ; + * + **/ - // after begin_interactive_session, parser has toplevel exprseq - // but is still "at toplevel" in the sense of ready for input - REQUIRE(parser.has_incomplete_expr() == false); + { + auto & result = parser.on_token(Token::if_token()); - REQUIRE(result.is_error()); + log && log("after if token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); - // illegal input on token - REQUIRE(result.error_description()); + REQUIRE(parser.has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } + + { + auto & result = parser.on_token(Token::bool_token("true")); + + log && log("after true token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } + + { + auto & result = parser.on_token(Token::then_token()); + + log && log("after then token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } + + { + auto & result = parser.on_token(Token::i64_token("777")); + + log && log("after i64 token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } + + { + auto & result = parser.on_token(Token::else_token()); + + log && log("after else token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } + + { + auto & result = parser.on_token(Token::string_token("fooey")); + + log && log("after string token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } + + { + auto & result = parser.on_token(Token::semicolon_token()); + + log && log("after semicolon token:"); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + REQUIRE(parser.has_incomplete_expr() == false); + REQUIRE(!result.is_error()); + REQUIRE(!result.is_incomplete()); + } + + //REQUIRE(result.is_error()); + //// illegal input on token + //REQUIRE(result.error_description()); } } /*namespace ut*/ diff --git a/xo-tokenizer2/include/xo/tokenizer2/Token.hpp b/xo-tokenizer2/include/xo/tokenizer2/Token.hpp index cc6e13d9..38e73902 100644 --- a/xo-tokenizer2/include/xo/tokenizer2/Token.hpp +++ b/xo-tokenizer2/include/xo/tokenizer2/Token.hpp @@ -137,6 +137,8 @@ namespace xo { static Token lambda() { return Token(tokentype::tk_lambda); } /** token representing keyword @c if **/ static Token if_token() { return Token(tokentype::tk_if); } + /** token representing keyword @c then **/ + static Token then_token() { return Token(tokentype::tk_then); } /** token representing keyword @c else **/ static Token else_token() { return Token(tokentype::tk_else); } /** token representing keyword @c let **/