From 184fed0ccdd4e5df43481dec902d0c7d030dc821 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 11 Mar 2026 14:13:48 -0500 Subject: [PATCH] xo-reader2: parse list types + utest --- xo-reader2/CMakeLists.txt | 16 ++ .../idl/IPrintable_DExpectListTypeSsm.json5 | 16 ++ ...yntaxStateMachine_DExpectListTypeSsm.json5 | 16 ++ .../include/xo/reader2/DExpectQArraySsm.hpp | 10 +- .../include/xo/reader2/DExpectTypeSsm.hpp | 21 +- .../include/xo/reader2/ExpectListTypeSsm.hpp | 12 + .../expect_listtype/DExpectListTypeSsm.hpp | 149 +++++++++++++ .../IPrintable_DExpectListTypeSsm.hpp | 62 ++++++ ...ISyntaxStateMachine_DExpectListTypeSsm.hpp | 84 +++++++ .../include/xo/reader2/ifelse/DIfElseSsm.hpp | 13 +- .../include/xo/reader2/syntaxstatetype.hpp | 3 + xo-reader2/src/reader2/CMakeLists.txt | 4 + xo-reader2/src/reader2/DExpectListTypeSsm.cpp | 207 ++++++++++++++++++ xo-reader2/src/reader2/DExpectTypeSsm.cpp | 45 ++-- .../facet/IPrintable_DExpectListTypeSsm.cpp | 28 +++ ...ISyntaxStateMachine_DExpectListTypeSsm.cpp | 84 +++++++ .../src/reader2/reader2_register_facets.cpp | 5 + xo-reader2/src/reader2/syntaxstatetype.cpp | 2 + xo-reader2/utest/SchematikaParser.test.cpp | 42 ++++ xo-tokenizer2/include/xo/tokenizer2/Token.hpp | 4 +- xo-type/include/xo/type/DListType.hpp | 5 +- xo-type/src/type/DListType.cpp | 7 + 22 files changed, 799 insertions(+), 36 deletions(-) create mode 100644 xo-reader2/idl/IPrintable_DExpectListTypeSsm.json5 create mode 100644 xo-reader2/idl/ISyntaxStateMachine_DExpectListTypeSsm.json5 create mode 100644 xo-reader2/include/xo/reader2/ExpectListTypeSsm.hpp create mode 100644 xo-reader2/include/xo/reader2/expect_listtype/DExpectListTypeSsm.hpp create mode 100644 xo-reader2/include/xo/reader2/expect_listtype/IPrintable_DExpectListTypeSsm.hpp create mode 100644 xo-reader2/include/xo/reader2/expect_listtype/ISyntaxStateMachine_DExpectListTypeSsm.hpp create mode 100644 xo-reader2/src/reader2/DExpectListTypeSsm.cpp create mode 100644 xo-reader2/src/reader2/facet/IPrintable_DExpectListTypeSsm.cpp create mode 100644 xo-reader2/src/reader2/facet/ISyntaxStateMachine_DExpectListTypeSsm.cpp diff --git a/xo-reader2/CMakeLists.txt b/xo-reader2/CMakeLists.txt index 42869a58..faf792a9 100644 --- a/xo-reader2/CMakeLists.txt +++ b/xo-reader2/CMakeLists.txt @@ -225,6 +225,22 @@ xo_add_genfacetimpl( # ---------------------------------------------------------------- +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-syntaxstatemachine-expectlisttypessm + FACET_PKG xo_reader2 + INPUT idl/ISyntaxStateMachine_DExpectListTypeSsm.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-expectlisttypessm + FACET_PKG xo_printable2 + INPUT idl/IPrintable_DExpectListTypeSsm.json5 +) + +# ---------------------------------------------------------------- + # note: manual target; generated code committed to git xo_add_genfacetimpl( TARGET xo-reader2-facetimpl-syntaxstatemachine-expectexprssm diff --git a/xo-reader2/idl/IPrintable_DExpectListTypeSsm.json5 b/xo-reader2/idl/IPrintable_DExpectListTypeSsm.json5 new file mode 100644 index 00000000..2403eb59 --- /dev/null +++ b/xo-reader2/idl/IPrintable_DExpectListTypeSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2/facet", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "expect_listtype", + includes: [ "", + "" ], + local_types: [], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DExpectListTypeSsm", + using_doxygen: true, + repr: "DExpectListTypeSsm", + doc: [ "implement APrintable for DExpectListTypeSsm" ], +} diff --git a/xo-reader2/idl/ISyntaxStateMachine_DExpectListTypeSsm.json5 b/xo-reader2/idl/ISyntaxStateMachine_DExpectListTypeSsm.json5 new file mode 100644 index 00000000..9a616675 --- /dev/null +++ b/xo-reader2/idl/ISyntaxStateMachine_DExpectListTypeSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2/facet", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "expect_listtype", + includes: [ "\"SyntaxStateMachine.hpp\"", + "\"ssm/ISyntaxStateMachine_Xfer.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SyntaxStateMachine.json5", + brief: "provide ASyntaxStateMachine interface for DExpectListTypeSsm", + using_doxygen: true, + repr: "DExpectListTypeSsm", + doc: [ "implement ASyntaxStateMachine for DExpectListTypeSsm" ], +} \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/DExpectQArraySsm.hpp b/xo-reader2/include/xo/reader2/DExpectQArraySsm.hpp index 5316ee34..929460dc 100644 --- a/xo-reader2/include/xo/reader2/DExpectQArraySsm.hpp +++ b/xo-reader2/include/xo/reader2/DExpectQArraySsm.hpp @@ -16,13 +16,13 @@ namespace xo { * Already in quoted-literal context * * [ quote-expr ... ] - * ^ ^ ^ - * | qarray_1a qarray_2(done) - * qarray_0 + * ^ ^ ^ ^ + * | qarray_1a | qarray_2(done) + * qarray_0 qarray_1a * - * qarray_0 --on_leftbrace_token()--> qarray_1a [push ExpectQLiteralSsm] + * qarray_0 --on_leftbracket_token()--> qarray_1a [push ExpectQLiteralSsm] * qarray_1a --on_quoted_literal()--> qarray_1a [append literal] - * qarray_1a --on_rightbrace_token()--> qarray_2(done) [report quoted array] + * qarray_1a --on_rightbracket_token()--> qarray_2(done) [report quoted array] **/ class QArrayXst { public: diff --git a/xo-reader2/include/xo/reader2/DExpectTypeSsm.hpp b/xo-reader2/include/xo/reader2/DExpectTypeSsm.hpp index aba12f8d..2901c95a 100644 --- a/xo-reader2/include/xo/reader2/DExpectTypeSsm.hpp +++ b/xo-reader2/include/xo/reader2/DExpectTypeSsm.hpp @@ -14,12 +14,14 @@ namespace xo { /** @class DExpectTypeSsm * @brief syntax state-machine for accepting a Schemtika typename-expression * - * Jan 2026 - * Placeholder implementation at present. - * Only types are a handful of baked-in values - * * @pre - * + * any universal polymorphic type + * unit empty type (like c/c++ void) + * f64 64-bit float + * i32 32-bit signed integer + * list parameterized list (polymorphic if T is any) + * array parameterized array (polymorphic if T is any) + * function function (U x ...) -> T * @endpre **/ class DExpectTypeSsm : public DSyntaxStateMachine { @@ -30,17 +32,26 @@ namespace xo { using ppindentinfo = xo::print::ppindentinfo; public: + /** @defgroup scm-expecttype-ctors constructors **/ + ///@{ + explicit DExpectTypeSsm(bool corrected); + /** create instance **/ static DExpectTypeSsm * _make(DArena & parser_mm, bool corrected); /** create fop referring to new DExpectTypeSsm **/ static obj make(DArena & parser_mm, bool corrected); + ///@} + /** @defgroup scm-expecttype-general-methods general methods **/ + ///@{ + static void start(bool corrected, ParserStateMachine * p_psm); static const char * ssm_classname() { return "DExpectTypeSsm"; } + ///@} /** @defgroup scm-expecttype-ssm-facet syntaxstatemachine facet methods **/ ///@{ diff --git a/xo-reader2/include/xo/reader2/ExpectListTypeSsm.hpp b/xo-reader2/include/xo/reader2/ExpectListTypeSsm.hpp new file mode 100644 index 00000000..63f388a3 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ExpectListTypeSsm.hpp @@ -0,0 +1,12 @@ +/** @file ExpectListTypeSsm.hpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#pragma once + +#include "expect_listtype/DExpectListTypeSsm.hpp" +#include "expect_listtype/ISyntaxStateMachine_DExpectListTypeSsm.hpp" +#include "expect_listtype/IPrintable_DExpectListTypeSsm.hpp" + +/* end ExpectListTypeSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/expect_listtype/DExpectListTypeSsm.hpp b/xo-reader2/include/xo/reader2/expect_listtype/DExpectListTypeSsm.hpp new file mode 100644 index 00000000..38f04ca1 --- /dev/null +++ b/xo-reader2/include/xo/reader2/expect_listtype/DExpectListTypeSsm.hpp @@ -0,0 +1,149 @@ +/** @file DExpectListTypeSsm.hpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#pragma once + +#include "DSyntaxStateMachine.hpp" + +namespace xo { + namespace scm { + + /** + * list < type-expr > + * ^ ^ ^ ^ ^ + * | | | | (done) + * | | | type_3 --on_rightangle_token() --> (done) [pop + report listtype] + * | | type_2 --on_parsed_type()--> type_3 + * | type_1 --on_leftangle_token() --> type_2 [push ExpectTypeSsm] + * type_0 --on_symbol_token()--> type_1 + * + **/ + class ListTypeXst { + public: + enum class code { + invalid = -1, + + type_0, + type_1, + type_2, + type_3, + + N, + }; + + explicit ListTypeXst(code x) : code_{x} {} + + /** @return string representation for enum @p x **/ + static const char * _descr(code x); + + code code() const noexcept { return code_; } + + enum code code_; + }; + + inline std::ostream & + operator<<(std::ostream & os, ListTypeXst x) { + os << ListTypeXst::_descr(x.code_); + return os; + } + + /** @class DExpectListTypeSsm + * @brief parser state-machine for a list type + * + * Examples: + * @pre + * list + * list> + * @endpre + **/ + class DExpectListTypeSsm : public DSyntaxStateMachine { + public: + using Super = DSyntaxStateMachine; + using TypeDescr = xo::reflect::TypeDescr; + using DArena = xo::mm::DArena; + using ppindentinfo = xo::print::ppindentinfo; + + public: + /** default ctor **/ + explicit DExpectListTypeSsm(); + + /** create instance. Get memory from @p parser_mm **/ + static DExpectListTypeSsm * _make(DArena & parser_mm); + + /** create instance as fop. Get memory from @p parser_mm **/ + static obj make(DArena & parser_mm); + + /** start nested state machine to parse a list type **/ + static void start(ParserStateMachine * p_psm); + + /** @defgroup scm-expectlisttypessm-expression-methods general methods **/ + ///@{ + + static const char * ssm_classname() { return "DExpectListTypeSsm"; } + + syntaxstatetype ssm_type() const noexcept; + + std::string_view get_expect_str() const noexcept; + + /** update ssm for symbol token @p tk, with overall parsing state in @p p_psm. + * in state type_0: advance to type_1. + * otherwise error + **/ + void on_symbol_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update ssm for leftangle (<) token @p tk, with overall parser state in @p p_psm. + * in state type_1: advance to type_2, pushing nested ExpectTypeSsm. + * otherwise error. + **/ + void on_leftangle_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update ssm for rightangle (>) token @p tk, with overall parser state in @p p_psm. + * in state type_3: aseemble list type, report completed syntax to parent ssm + **/ + void on_rightangle_token(const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-expectlisttypessm-expression-facet expression facet methods **/ + ///@{ + + /** update ssm for token @p tk, with overall state in @p p_psm **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update ssm for type @p type produced by nested ssm, with overall parser + * state in @p p_psm. + * in state type_2: @p type is element type for target list type. + * otherwise error. + **/ + void on_parsed_type(obj type, ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-expectlisttypessm-printable-facet printable facet methods **/ + ///@{ + + /** pretty-printing support **/ + bool pretty(const ppindentinfo & ppii) const; + + ///@} + private: + /** @defgroup scm-expectlisttypessm-instance-vars instance variables **/ + ///@{ + + /** local parsing state **/ + ListTypeXst state_{ListTypeXst::code::type_0}; + + /** element type for target list type **/ + obj elt_type_; + + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DExpectListTypeSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/expect_listtype/IPrintable_DExpectListTypeSsm.hpp b/xo-reader2/include/xo/reader2/expect_listtype/IPrintable_DExpectListTypeSsm.hpp new file mode 100644 index 00000000..b799d6ca --- /dev/null +++ b/xo-reader2/include/xo/reader2/expect_listtype/IPrintable_DExpectListTypeSsm.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DExpectListTypeSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DExpectListTypeSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DExpectListTypeSsm.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DExpectListTypeSsm.hpp" + +namespace xo { namespace scm { class IPrintable_DExpectListTypeSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DExpectListTypeSsm + **/ + class IPrintable_DExpectListTypeSsm { + public: + /** @defgroup scm-printable-dexpectlisttypessm-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dexpectlisttypessm-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DExpectListTypeSsm & 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/expect_listtype/ISyntaxStateMachine_DExpectListTypeSsm.hpp b/xo-reader2/include/xo/reader2/expect_listtype/ISyntaxStateMachine_DExpectListTypeSsm.hpp new file mode 100644 index 00000000..37a653f9 --- /dev/null +++ b/xo-reader2/include/xo/reader2/expect_listtype/ISyntaxStateMachine_DExpectListTypeSsm.hpp @@ -0,0 +1,84 @@ +/** @file ISyntaxStateMachine_DExpectListTypeSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DExpectListTypeSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DExpectListTypeSsm.json5] + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "DExpectListTypeSsm.hpp" + +namespace xo { namespace scm { class ISyntaxStateMachine_DExpectListTypeSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISyntaxStateMachine_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISyntaxStateMachine_DExpectListTypeSsm + **/ + class ISyntaxStateMachine_DExpectListTypeSsm { + public: + /** @defgroup scm-syntaxstatemachine-dexpectlisttypessm-type-traits **/ + ///@{ + using TypeDescr = xo::scm::ASyntaxStateMachine::TypeDescr; + using AGCObject = xo::scm::ASyntaxStateMachine::AGCObject; + using Copaque = xo::scm::ASyntaxStateMachine::Copaque; + using Opaque = xo::scm::ASyntaxStateMachine::Opaque; + ///@} + /** @defgroup scm-syntaxstatemachine-dexpectlisttypessm-methods **/ + ///@{ + // const methods + /** identify a type of syntax state machine **/ + static syntaxstatetype ssm_type(const DExpectListTypeSsm & self) noexcept; + /** text describing expected/allowed input to this ssm in current state **/ + static std::string_view get_expect_str(const DExpectListTypeSsm & self) noexcept; + + // non-const methods + /** operate state machine for incoming token @p tk **/ + static void on_token(DExpectListTypeSsm & self, const Token & tk, ParserStateMachine * p_psm); + /** update stat machine for incoming parsed symbol @p sym **/ + static void on_parsed_symbol(DExpectListTypeSsm & self, std::string_view sym, ParserStateMachine * p_psm); + /** operate state machine for incoming type description @p td **/ + static void on_parsed_typedescr(DExpectListTypeSsm & self, TypeDescr td, ParserStateMachine * p_psm); + /** update state machine for type emitted by nested ssm **/ + static void on_parsed_type(DExpectListTypeSsm & self, obj type, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal(DExpectListTypeSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal_with_token(DExpectListTypeSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm); + /** consume formal arglist emitted by nested ssm **/ + static void on_parsed_formal_arglist(DExpectListTypeSsm & self, DArray * arglist, ParserStateMachine * p_psm); + /** update state machine for nested parsed expression @p expr **/ + static void on_parsed_expression(DExpectListTypeSsm & self, obj expr, ParserStateMachine * p_psm); + /** update state machine @p p_psm for incoming parsed expression @p expr followed by token @p tk **/ + static void on_parsed_expression_with_token(DExpectListTypeSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm); + /** update state machine for nested quoted literal @p lit **/ + static void on_quoted_literal(DExpectListTypeSsm & self, obj lit, ParserStateMachine * p_psm); + ///@} + }; + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end */ \ No newline at end of file diff --git a/xo-reader2/include/xo/reader2/ifelse/DIfElseSsm.hpp b/xo-reader2/include/xo/reader2/ifelse/DIfElseSsm.hpp index 345f3fa5..cded3e6f 100644 --- a/xo-reader2/include/xo/reader2/ifelse/DIfElseSsm.hpp +++ b/xo-reader2/include/xo/reader2/ifelse/DIfElseSsm.hpp @@ -85,14 +85,14 @@ namespace xo { obj expr_mm, ParserStateMachine * p_psm); - static const char * ssm_classname() { return "DIfElseSsm"; } - - DSyntaxStateMachine * super() { return this; } - ///@} /** @defgroup scm-ifelsessm-expression-methods general methods **/ ///@{ + static const char * ssm_classname() { return "DIfElseSsm"; } + + DSyntaxStateMachine * super() { return this; } + /** operate state machine on if-token input @p tk, * with overall parser state in @p p_psm **/ @@ -178,6 +178,9 @@ namespace xo { #endif private: + /** @defgroup scm-expectlisttypessm-instance-vars instance variables **/ + ///@{ + ifexprstatetype ifstate_ = ifexprstatetype::invalid; /** scaffold ifelse-expression here. * This will eventually be the output of this ssm @@ -186,6 +189,8 @@ namespace xo { **/ obj if_expr_; + ///@} + }; } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-reader2/include/xo/reader2/syntaxstatetype.hpp b/xo-reader2/include/xo/reader2/syntaxstatetype.hpp index a01dcb62..dd34054a 100644 --- a/xo-reader2/include/xo/reader2/syntaxstatetype.hpp +++ b/xo-reader2/include/xo/reader2/syntaxstatetype.hpp @@ -60,6 +60,9 @@ namespace xo { /** expecting a type. See @ref DExpectTypeSsm **/ expect_type, + /** expecting a list type. See @ref DExpectListTypeSsm **/ + expect_listtype, + /** expecting a rhs expression. See @ref DExpectExprSsm **/ expect_rhs_expression, diff --git a/xo-reader2/src/reader2/CMakeLists.txt b/xo-reader2/src/reader2/CMakeLists.txt index 455fadee..af8bf4af 100644 --- a/xo-reader2/src/reader2/CMakeLists.txt +++ b/xo-reader2/src/reader2/CMakeLists.txt @@ -65,6 +65,10 @@ set(SELF_SRCS ISyntaxStateMachine_DExpectTypeSsm.cpp IPrintable_DExpectTypeSsm.cpp + DExpectListTypeSsm.cpp + facet/ISyntaxStateMachine_DExpectListTypeSsm.cpp + facet/IPrintable_DExpectListTypeSsm.cpp + DExpectExprSsm.cpp ISyntaxStateMachine_DExpectExprSsm.cpp IPrintable_DExpectExprSsm.cpp diff --git a/xo-reader2/src/reader2/DExpectListTypeSsm.cpp b/xo-reader2/src/reader2/DExpectListTypeSsm.cpp new file mode 100644 index 00000000..3b040962 --- /dev/null +++ b/xo-reader2/src/reader2/DExpectListTypeSsm.cpp @@ -0,0 +1,207 @@ +/** @file DExpectListTypeSsm.cpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#include "ExpectListTypeSsm.hpp" +#include "ExpectTypeSsm.hpp" +#include "syntaxstatetype.hpp" +#include +#include + +namespace xo { + namespace scm { + + const char * + ListTypeXst::_descr(enum code x) + { + switch (x) { + case code::invalid: return "?invalid"; + case code::type_0: return "type_0"; + case code::type_1: return "type_1"; + case code::type_2: return "type_2"; + case code::type_3: return "type_3"; + case code::N: break; + } + + return "?ListTypeXst"; + } + + DExpectListTypeSsm::DExpectListTypeSsm() = default; + + DExpectListTypeSsm * + DExpectListTypeSsm::_make(DArena & parser_mm) + { + void * mem = parser_mm.alloc_for(); + + return new (mem) DExpectListTypeSsm(); + } + + obj + DExpectListTypeSsm::make(DArena & parser_mm) + { + return obj(_make(parser_mm)); + } + + void + DExpectListTypeSsm::start(ParserStateMachine * p_psm) + { + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + + p_psm->push_ssm(ckp, DExpectListTypeSsm::make(p_psm->parser_alloc())); + } + + syntaxstatetype + DExpectListTypeSsm::ssm_type() const noexcept + { + return syntaxstatetype::expect_listtype; + } + + std::string_view + DExpectListTypeSsm::get_expect_str() const noexcept + { + switch(state_.code()) { + case ListTypeXst::code::invalid: + case ListTypeXst::code::N: + break; + case ListTypeXst::code::type_0: + return "list"; + case ListTypeXst::code::type_1: + return "leftangle"; + case ListTypeXst::code::type_2: + return "type"; + case ListTypeXst::code::type_3: + return "rightangle"; + } + + return "?ExpectListTypeSsm"; + } + + void + DExpectListTypeSsm::on_token(const Token & tk, + ParserStateMachine * p_psm) + { + switch (tk.tk_type()) { + + case tokentype::tk_symbol: + this->on_symbol_token(tk, p_psm); + return; + + case tokentype::tk_leftangle: + this->on_leftangle_token(tk, p_psm); + return; + + case tokentype::tk_rightangle: + this->on_rightangle_token(tk, p_psm); + return; + + // all the {not-yet-handled, illegal} cases + case tokentype::tk_leftbrace: + case tokentype::tk_rightbrace: + case tokentype::tk_quote: + case tokentype::tk_def: + case tokentype::tk_deftype: + case tokentype::tk_colon: + case tokentype::tk_singleassign: + case tokentype::tk_semicolon: + case tokentype::tk_invalid: + case tokentype::tk_string: + case tokentype::tk_f64: + case tokentype::tk_i64: + case tokentype::tk_bool: + case tokentype::tk_if: + case tokentype::tk_leftparen: + case tokentype::tk_rightparen: + case tokentype::tk_leftbracket: + case tokentype::tk_rightbracket: + 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_then: + case tokentype::tk_else: + case tokentype::tk_let: + case tokentype::tk_in: + case tokentype::tk_end: + case tokentype::N: + break; + } + + Super::illegal_token(tk, p_psm); + } + + void + DExpectListTypeSsm::on_symbol_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (state_.code() == ListTypeXst::code::type_0) { + this->state_ = ListTypeXst(ListTypeXst::code::type_1); + return; + } + + Super::illegal_token(tk, p_psm); + } + + void + DExpectListTypeSsm::on_leftangle_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (state_.code() == ListTypeXst::code::type_1) { + this->state_ = ListTypeXst(ListTypeXst::code::type_2); + DExpectTypeSsm::start(true /*corrected*/, p_psm); + return; + } + + Super::illegal_token(tk, p_psm); + } + + void + DExpectListTypeSsm::on_parsed_type(obj type, ParserStateMachine * p_psm) + { + if (state_.code() == ListTypeXst::code::type_2) { + this->state_ = ListTypeXst(ListTypeXst::code::type_3); + this->elt_type_ = type; + return; + } + + Super::illegal_type(type, p_psm); + } + + void + DExpectListTypeSsm::on_rightangle_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (state_.code() == ListTypeXst::code::type_3) { + obj result = DListType::make(p_psm->expr_alloc(), + elt_type_); + p_psm->pop_ssm(); + p_psm->on_parsed_type(result); + return; + } + + Super::illegal_token(tk, p_psm); + } + + bool + DExpectListTypeSsm::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct + (ppii, + "DExpectListTypeSsm"); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DExpectListTypeSsm.cpp */ diff --git a/xo-reader2/src/reader2/DExpectTypeSsm.cpp b/xo-reader2/src/reader2/DExpectTypeSsm.cpp index edd71d66..600b7650 100644 --- a/xo-reader2/src/reader2/DExpectTypeSsm.cpp +++ b/xo-reader2/src/reader2/DExpectTypeSsm.cpp @@ -4,7 +4,7 @@ **/ #include "ExpectTypeSsm.hpp" -//#include "ssm/ISyntaxStateMachine_DExpectTypeSsm.hpp" +#include "ExpectListTypeSsm.hpp" #include "SyntaxStateMachine.hpp" #include #include @@ -132,25 +132,32 @@ namespace xo { obj type; obj mm = p_psm->expr_alloc(); - if (tk.text() == "unit") - type = DAtomicType::make(mm, Metatype::t_unit()); - if (tk.text() == "bool") - type = DAtomicType::make(mm, Metatype::t_bool()); - else if (tk.text() == "str") - type = DAtomicType::make(mm, Metatype::t_str()); - else if (tk.text() == "f64") - type = DAtomicType::make(mm, Metatype::t_f64()); - else if(tk.text() == "f32") - type = DAtomicType::make(mm, Metatype::t_f32()); - else if(tk.text() == "i16") - type = DAtomicType::make(mm, Metatype::t_i16()); - else if(tk.text() == "i32") - type = DAtomicType::make(mm, Metatype::t_i32()); - else if(tk.text() == "i64") - type = DAtomicType::make(mm, Metatype::t_i64()); + if (tk.text() == "list") { + /* replace top ssm with specialized list-type ssm parser */ + p_psm->pop_ssm(); + DExpectListTypeSsm::start(p_psm); + p_psm->on_token(tk); + } else { + if (tk.text() == "unit") + type = DAtomicType::make(mm, Metatype::t_unit()); + if (tk.text() == "bool") + type = DAtomicType::make(mm, Metatype::t_bool()); + else if (tk.text() == "str") + type = DAtomicType::make(mm, Metatype::t_str()); + else if (tk.text() == "f64") + type = DAtomicType::make(mm, Metatype::t_f64()); + else if(tk.text() == "f32") + type = DAtomicType::make(mm, Metatype::t_f32()); + else if(tk.text() == "i16") + type = DAtomicType::make(mm, Metatype::t_i16()); + else if(tk.text() == "i32") + type = DAtomicType::make(mm, Metatype::t_i32()); + else if(tk.text() == "i64") + type = DAtomicType::make(mm, Metatype::t_i64()); - p_psm->pop_ssm(); - p_psm->on_parsed_type(type); + p_psm->pop_ssm(); + p_psm->on_parsed_type(type); + } } else { TypeDescr td = nullptr; diff --git a/xo-reader2/src/reader2/facet/IPrintable_DExpectListTypeSsm.cpp b/xo-reader2/src/reader2/facet/IPrintable_DExpectListTypeSsm.cpp new file mode 100644 index 00000000..8f90fad5 --- /dev/null +++ b/xo-reader2/src/reader2/facet/IPrintable_DExpectListTypeSsm.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DExpectListTypeSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DExpectListTypeSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DExpectListTypeSsm.json5] +**/ + +#include "expect_listtype/IPrintable_DExpectListTypeSsm.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DExpectListTypeSsm::pretty(const DExpectListTypeSsm & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DExpectListTypeSsm.cpp */ diff --git a/xo-reader2/src/reader2/facet/ISyntaxStateMachine_DExpectListTypeSsm.cpp b/xo-reader2/src/reader2/facet/ISyntaxStateMachine_DExpectListTypeSsm.cpp new file mode 100644 index 00000000..bd8ac996 --- /dev/null +++ b/xo-reader2/src/reader2/facet/ISyntaxStateMachine_DExpectListTypeSsm.cpp @@ -0,0 +1,84 @@ +/** @file ISyntaxStateMachine_DExpectListTypeSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DExpectListTypeSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DExpectListTypeSsm.json5] +**/ + +#include "expect_listtype/ISyntaxStateMachine_DExpectListTypeSsm.hpp" + +namespace xo { + namespace scm { + auto + ISyntaxStateMachine_DExpectListTypeSsm::ssm_type(const DExpectListTypeSsm & self) noexcept -> syntaxstatetype + { + return self.ssm_type(); + } + + auto + ISyntaxStateMachine_DExpectListTypeSsm::get_expect_str(const DExpectListTypeSsm & self) noexcept -> std::string_view + { + return self.get_expect_str(); + } + + auto + ISyntaxStateMachine_DExpectListTypeSsm::on_token(DExpectListTypeSsm & self, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_token(tk, p_psm); + } + auto + ISyntaxStateMachine_DExpectListTypeSsm::on_parsed_symbol(DExpectListTypeSsm & self, std::string_view sym, ParserStateMachine * p_psm) -> void + { + self.on_parsed_symbol(sym, p_psm); + } + auto + ISyntaxStateMachine_DExpectListTypeSsm::on_parsed_typedescr(DExpectListTypeSsm & self, TypeDescr td, ParserStateMachine * p_psm) -> void + { + self.on_parsed_typedescr(td, p_psm); + } + auto + ISyntaxStateMachine_DExpectListTypeSsm::on_parsed_type(DExpectListTypeSsm & self, obj type, ParserStateMachine * p_psm) -> void + { + self.on_parsed_type(type, p_psm); + } + auto + ISyntaxStateMachine_DExpectListTypeSsm::on_parsed_formal(DExpectListTypeSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal(param_name, param_type, p_psm); + } + auto + ISyntaxStateMachine_DExpectListTypeSsm::on_parsed_formal_with_token(DExpectListTypeSsm & self, const DUniqueString * param_name, TypeDescr param_type, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_with_token(param_name, param_type, tk, p_psm); + } + auto + ISyntaxStateMachine_DExpectListTypeSsm::on_parsed_formal_arglist(DExpectListTypeSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_arglist(arglist, p_psm); + } + auto + ISyntaxStateMachine_DExpectListTypeSsm::on_parsed_expression(DExpectListTypeSsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression(expr, p_psm); + } + auto + ISyntaxStateMachine_DExpectListTypeSsm::on_parsed_expression_with_token(DExpectListTypeSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression_with_token(expr, tk, p_psm); + } + auto + ISyntaxStateMachine_DExpectListTypeSsm::on_quoted_literal(DExpectListTypeSsm & self, obj lit, ParserStateMachine * p_psm) -> void + { + self.on_quoted_literal(lit, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_DExpectListTypeSsm.cpp */ diff --git a/xo-reader2/src/reader2/reader2_register_facets.cpp b/xo-reader2/src/reader2/reader2_register_facets.cpp index 5262c1e9..dc9915ef 100644 --- a/xo-reader2/src/reader2/reader2_register_facets.cpp +++ b/xo-reader2/src/reader2/reader2_register_facets.cpp @@ -21,6 +21,7 @@ #include "ExpectFormalArgSsm.hpp" #include "ExpectSymbolSsm.hpp" #include "ExpectTypeSsm.hpp" +#include "ExpectListTypeSsm.hpp" #include "ExpectExprSsm.hpp" #include "ExpectQLiteralSsm.hpp" #include "ExpectQListSsm.hpp" @@ -57,6 +58,7 @@ namespace xo { FacetRegistry::register_impl(); FacetRegistry::register_impl(); + FacetRegistry::register_impl(); FacetRegistry::register_impl(); FacetRegistry::register_impl(); @@ -74,6 +76,9 @@ namespace xo { FacetRegistry::register_impl(); FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); FacetRegistry::register_impl(); diff --git a/xo-reader2/src/reader2/syntaxstatetype.cpp b/xo-reader2/src/reader2/syntaxstatetype.cpp index 4aa21b0c..5968b1bb 100644 --- a/xo-reader2/src/reader2/syntaxstatetype.cpp +++ b/xo-reader2/src/reader2/syntaxstatetype.cpp @@ -41,6 +41,8 @@ namespace xo { return "expect-symbol"; case syntaxstatetype::expect_type: return "expect-type"; + case syntaxstatetype::expect_listtype: + return "expect-listtype"; case syntaxstatetype::expect_rhs_expression: return "expect-rhs-expression"; case syntaxstatetype::expect_qliteral: diff --git a/xo-reader2/utest/SchematikaParser.test.cpp b/xo-reader2/utest/SchematikaParser.test.cpp index c2591815..3921148d 100644 --- a/xo-reader2/utest/SchematikaParser.test.cpp +++ b/xo-reader2/utest/SchematikaParser.test.cpp @@ -312,6 +312,48 @@ namespace xo { log && fixture.log_memory_layout(&log); } + TEST_CASE("SchematikaParser-batch-deftype-2", "[reader2][SchematikaParser]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + ParserFixture fixture(testname, c_debug_flag); + auto & parser = *(fixture.parser_); + + parser.begin_batch_session(); + + /** Walkthrough parsing input equivalent to: + * + * deftype foo :: list; + **/ + + std::vector tk_v{ + Token::deftype_token(), + Token::symbol_token("foo"), + Token::doublecolon_token(), + Token::symbol_token("list"), + Token::leftangle_token(), + Token::symbol_token("f64"), + Token::rightangle_token(), + Token::semicolon_token(), + }; + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + + const auto & result = parser.result(); + { + // placeholder for form's sake. + // deftype doesn't actuallly produce any executable content + + auto expr = obj::from(result.result_expr()); + REQUIRE(expr); + } + + log && fixture.log_memory_layout(&log); + } + TEST_CASE("SchematikaParser-interactive-def2", "[reader2][SchematikaParser]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); diff --git a/xo-tokenizer2/include/xo/tokenizer2/Token.hpp b/xo-tokenizer2/include/xo/tokenizer2/Token.hpp index c7c43287..7537a2b0 100644 --- a/xo-tokenizer2/include/xo/tokenizer2/Token.hpp +++ b/xo-tokenizer2/include/xo/tokenizer2/Token.hpp @@ -90,9 +90,9 @@ namespace xo { /** token representing quote @c "'" **/ static Token quote_token() { return Token(tokentype::tk_quote); } /** token representing left angle bracket @c "<" **/ - static Token leftangle() { return Token(tokentype::tk_leftangle); } + static Token leftangle_token() { return Token(tokentype::tk_leftangle); } /** token representing right angle bracket @c ">" **/ - static Token rightangle() { return Token(tokentype::tk_rightangle); } + static Token rightangle_token() { return Token(tokentype::tk_rightangle); } /** token representing left parenthesis @c "(" **/ static Token leftparen_token() { return Token(tokentype::tk_leftparen); } /** Token representing right parenthesis @c ")" **/ diff --git a/xo-type/include/xo/type/DListType.hpp b/xo-type/include/xo/type/DListType.hpp index 51db9414..e19e48b2 100644 --- a/xo-type/include/xo/type/DListType.hpp +++ b/xo-type/include/xo/type/DListType.hpp @@ -32,9 +32,12 @@ namespace xo { explicit DListType(obj elt); - /** create instance using memory from @p mm with metatype @p mtype **/ + /** create instance using memory from @p mm with element type @p elt_type **/ static DListType * _make(obj mm, obj elt_type); + /** create fop to new instance using memory from @p mm with element type @p elt_type **/ + static obj make(obj mm, + obj elt_type); ///@} /** @defgroup xo-scm-listtype-type-facet **/ diff --git a/xo-type/src/type/DListType.cpp b/xo-type/src/type/DListType.cpp index 35b29235..47c8ea1f 100644 --- a/xo-type/src/type/DListType.cpp +++ b/xo-type/src/type/DListType.cpp @@ -31,6 +31,13 @@ namespace xo { return new (mem) DListType(elt_type); } + obj + DListType::make(obj mm, + obj elt_type) + { + return obj(_make(mm, elt_type)); + } + // ----- type facet ----- TypeDescr