From 03e42817b72cbb9d09765ecc3901a80148d58b1a Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 2 Mar 2026 11:05:12 +1100 Subject: [PATCH] xo-interpreter2 stack: handle operator expressions w/ qliterals --- .../utest/VirtualSchematikaMachine.test.cpp | 38 +++ xo-reader2/CMakeLists.txt | 20 ++ .../idl/IPrintable_DExpectQLiteralSsm.json5 | 16 ++ ...yntaxStateMachine_DExpectQLiteralSsm.json5 | 16 ++ .../include/xo/reader2/DExpectExprSsm.hpp | 17 ++ .../include/xo/reader2/DExpectQLiteralSsm.hpp | 143 ++++++++++ xo-reader2/include/xo/reader2/DQuoteSsm.hpp | 17 +- .../include/xo/reader2/DToplevelSeqSsm.hpp | 5 + .../include/xo/reader2/ExpectQLiteralSsm.hpp | 12 + .../include/xo/reader2/ParserStateMachine.hpp | 3 + .../ssm/IPrintable_DExpectQLiteralSsm.hpp | 62 +++++ ...ISyntaxStateMachine_DExpectQLiteralSsm.hpp | 82 ++++++ .../include/xo/reader2/syntaxstatetype.hpp | 3 + xo-reader2/src/reader2/CMakeLists.txt | 5 + xo-reader2/src/reader2/DExpectExprSsm.cpp | 38 ++- xo-reader2/src/reader2/DExpectQLiteralSsm.cpp | 256 ++++++++++++++++++ xo-reader2/src/reader2/DProgressSsm.cpp | 4 +- xo-reader2/src/reader2/DQuoteSsm.cpp | 55 ++-- xo-reader2/src/reader2/DToplevelSeqSsm.cpp | 33 ++- .../reader2/IPrintable_DExpectQLiteralSsm.cpp | 28 ++ ...ISyntaxStateMachine_DExpectQLiteralSsm.cpp | 79 ++++++ xo-reader2/src/reader2/ParserStateMachine.cpp | 6 + .../src/reader2/reader2_register_facets.cpp | 9 + xo-reader2/src/reader2/syntaxstatetype.cpp | 2 + xo-reader2/utest/SchematikaParser.test.cpp | 82 +++++- xo-tokenizer2/include/xo/tokenizer2/Token.hpp | 2 +- xo-tokenizer2/src/tokenizer2/Tokenizer.cpp | 1 + 27 files changed, 982 insertions(+), 52 deletions(-) create mode 100644 xo-reader2/idl/IPrintable_DExpectQLiteralSsm.json5 create mode 100644 xo-reader2/idl/ISyntaxStateMachine_DExpectQLiteralSsm.json5 create mode 100644 xo-reader2/include/xo/reader2/DExpectQLiteralSsm.hpp create mode 100644 xo-reader2/include/xo/reader2/ExpectQLiteralSsm.hpp create mode 100644 xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectQLiteralSsm.hpp create mode 100644 xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectQLiteralSsm.hpp create mode 100644 xo-reader2/src/reader2/DExpectQLiteralSsm.cpp create mode 100644 xo-reader2/src/reader2/IPrintable_DExpectQLiteralSsm.cpp create mode 100644 xo-reader2/src/reader2/ISyntaxStateMachine_DExpectQLiteralSsm.cpp diff --git a/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp b/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp index 4e5d6355..649fc00e 100644 --- a/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp +++ b/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp @@ -584,6 +584,44 @@ namespace xo { log && vsm_fixture.log_memory_layout(&log); } + TEST_CASE("VirtualSchematikaMachine-qliteral1", "[interpreter2][VSM]") + { + const auto & testname = Catch::getResultCapture().getCurrentTestName(); + + bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); + + VsmFixture vsm_fixture(testname, c_debug_flag, + VsmConfig().with_parser_debug_flag(c_debug_flag)); + auto & vsm = vsm_fixture.vsm_; + + bool eof_flag = true; + + vsm.begin_interactive_session(); + + span_type input = span_type::from_cstr("#q{ 4.5 };"); + + log && log(xtag("input", input)); + + VsmResultExt res + = vsm.read_eval_print(input, eof_flag); + + REQUIRE(res.is_value()); + REQUIRE(res.value()); + + log && log(xtag("res.tseq", res.value()->_typeseq()), + xtag("res.type", TypeRegistry::id2name(res.value()->_typeseq()))); + + auto x = obj::from(*res.value()); + REQUIRE(x); + REQUIRE(x->value() == 4.5); + + REQUIRE(res.remaining_.size() == 1); + REQUIRE(*res.remaining_.lo() == '\n'); + + //log && vsm_fixture.log_memory_layout(&log); + } + TEST_CASE("VirtualSchematikaMachine-report_memory_use", "[interpreter2][VSM]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); diff --git a/xo-reader2/CMakeLists.txt b/xo-reader2/CMakeLists.txt index c70ad114..eef3fddb 100644 --- a/xo-reader2/CMakeLists.txt +++ b/xo-reader2/CMakeLists.txt @@ -313,6 +313,26 @@ xo_add_genfacetimpl( # ---------------------------------------------------------------- +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-syntaxstatemachine-expectqliteralssm + FACET_PKG xo_reader2 + FACET SyntaxStateMachine + REPR ExpectQLiteralSsm + INPUT idl/ISyntaxStateMachine_DExpectQLiteralSsm.json5 +) + +# note: manual target; generated code committed to git +xo_add_genfacetimpl( + TARGET xo-reader2-facetimpl-printable-expectqliteralssm + FACET_PKG xo_printable2 + FACET Printable + REPR ExpectQLiteralSsm + INPUT idl/IPrintable_DExpectQLiteralSsm.json5 +) + +# ---------------------------------------------------------------- + xo_add_genfacet_all(xo-reader2-genfacet-all) # ---------------------------------------------------------------- diff --git a/xo-reader2/idl/IPrintable_DExpectQLiteralSsm.json5 b/xo-reader2/idl/IPrintable_DExpectQLiteralSsm.json5 new file mode 100644 index 00000000..ae3f9dd6 --- /dev/null +++ b/xo-reader2/idl/IPrintable_DExpectQLiteralSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "", + "" ], + local_types: [], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/Printable.json5", + brief: "provide APrintable interface for DExpectQLiteralSsm", + using_doxygen: true, + repr: "DExpectQLiteralSsm", + doc: [ "implement APrintable for DExpectQLiteralSsm" ], +} diff --git a/xo-reader2/idl/ISyntaxStateMachine_DExpectQLiteralSsm.json5 b/xo-reader2/idl/ISyntaxStateMachine_DExpectQLiteralSsm.json5 new file mode 100644 index 00000000..58310939 --- /dev/null +++ b/xo-reader2/idl/ISyntaxStateMachine_DExpectQLiteralSsm.json5 @@ -0,0 +1,16 @@ +{ + mode: "implementation", + output_cpp_dir: "src/reader2", + output_hpp_dir: "include/xo/reader2", + output_impl_subdir: "ssm", + includes: [ "\"SyntaxStateMachine.hpp\"", + "\"ssm/ISyntaxStateMachine_Xfer.hpp\"" ], + local_types: [ ], + namespace1: "xo", + namespace2: "scm", + facet_idl: "idl/SyntaxStateMachine.json5", + brief: "provide ASyntaxStateMachine interface for DExpectQLiteralSsm", + using_doxygen: true, + repr: "DExpectQLiteralSsm", + doc: [ "implement ASyntaxStateMachine for DExpectQLiteralSsm" ], +} diff --git a/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp b/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp index 16739006..539fbb39 100644 --- a/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp +++ b/xo-reader2/include/xo/reader2/DExpectExprSsm.hpp @@ -76,6 +76,14 @@ namespace xo { void on_leftbrace_token(const Token & tk, ParserStateMachine * p_psm); + /** update state for this syntax on quote token @p tk, + * with overall parser state in @p p_psm. + * + * Starts nested {progress-ssm, quote-ssm} combination. + **/ + void on_quote_token(const Token & tk, + ParserStateMachine * p_psm); + /** step state machine for this syntax on incoming boolean literal token @p tkk * with overall parser state in @p p_psm **/ @@ -160,6 +168,15 @@ namespace xo { const Token & tk, ParserStateMachine * p_psm); +#ifdef NOT_YET + /** update state for literal @p lit with overall state in @p p_psm. + * wraps literal as constant-expr + starts progress-ssm for possible + * operator expression. + **/ + void on_quoted_literal(obj lit, + ParserStateMachine * p_psm); +#endif + ///@} /** @defgroup scm-define-printable-facet printable facet methods **/ ///@{ diff --git a/xo-reader2/include/xo/reader2/DExpectQLiteralSsm.hpp b/xo-reader2/include/xo/reader2/DExpectQLiteralSsm.hpp new file mode 100644 index 00000000..407146a5 --- /dev/null +++ b/xo-reader2/include/xo/reader2/DExpectQLiteralSsm.hpp @@ -0,0 +1,143 @@ +/** @file DExpectQLiteralSsm.hpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#pragma once + +#include "DSyntaxStateMachine.hpp" +//#include +//#include + +namespace xo { + namespace scm { +#ifdef NOT_USING + /** + * Already in quoted-literal context + * + * #q{ } + * ^ + * qliteral_0 + * + * qliteral_0 --on_leftparen_token()--> push QuotedListSsm + **/ + enum class formalarglstatetype { + invalid = -1, + + argl_0, + argl_1a, + argl_1b, + + n_formalarglstatetype, + }; + + extern const char * + formalarglstatetype_descr(formalarglstatetype x); + + inline std::ostream & + operator<< (std::ostream & os, formalarglstatetype x) { + os << formalarglstatetype_descr(x); + return os; + } +#endif + + /** @class expect_formal_arglist + * @brief parser state-machine for a formal parameter list + **/ + class DExpectQLiteralSsm : public DSyntaxStateMachine { + public: + using Super = DSyntaxStateMachine; + using AAllocator = xo::mm::AAllocator; + using DArena = xo::mm::DArena; + using TypeDescr = xo::reflect::TypeDescr; + using ppindentinfo = xo::print::ppindentinfo; + using size_type = std::uint32_t; + + public: + DExpectQLiteralSsm(); + + /** create instance, using memory from @parser_mm **/ + static obj make(DArena & parser_mm); + static DExpectQLiteralSsm * _make(DArena & parser_mm); + + /** start nested syntax for a quoted literal **/ + static void start(ParserStateMachine * p_psm); + + /** @defgroup scm-expectformalarglistssm-methods general methods **/ + ///@{ + + static const char * ssm_classname() { return "DExpectQLiteralSsm"; } + + /** update state for f64 token @p tk, with overall parser state in @p p_psm. + * delegates to parent ssm via @ref on_quoted_literal + **/ + void on_f64_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state on incoming token @p tk, with overall parser state in @p p_psm **/ + void on_leftparen_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state on incoming token @p tk, with overall parser state in @p p_psm **/ + void on_comma_token(const Token & tk, + ParserStateMachine * p_psm); + + /** update state on incoming rightparen token @p tk, with overall parser state in @p p_psm **/ + void on_rightparen_token(const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-expectformalarglistssm-ssm-facet syntaxstatemachine facet methods **/ + ///@{ + + /** identifies the ssm implemented here **/ + syntaxstatetype ssm_type() const noexcept; + + /** mnemonic for expected input (for this ssm) in current state **/ + std::string_view get_expect_str() const; + + /** update state on incoming token @p tk, + * with overall parser state in @p p_psm + **/ + void on_token(const Token & tk, + ParserStateMachine * p_psm); + + ///@} + /** @defgroup scm-expectformalarglistssm-printable-facet printable facet methods **/ + ///@{ + + bool pretty(const ppindentinfo & ppii) const; + + ///@} + + private: + /** @defgroup scm-expectformalarglistssm-impl-methods **/ + ///@{ + + /** update local state to include parsed formal (param_name, param_type). + * If stack memory needed, get from @p parser_alloc. + * Lifetime until formal arglist completely parsed + **/ + void _accept_formal(obj expr_alloc, + DArena & parser_alloc, + const DUniqueString * param_name, + TypeDescr param_type); + + ///@} + + private: +#ifdef NOT_USING + /** parsing state-machine state **/ + formalarglstatetype fastate_ = formalarglstatetype::argl_0; + /** populate with (parameter-name, parameter-type) list + * as they're encountered. + * + * Not using flexible array here since we don't know size at construction time + **/ + DArray * argl_ = nullptr; +#endif + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end DExpectQLiteralSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/DQuoteSsm.hpp b/xo-reader2/include/xo/reader2/DQuoteSsm.hpp index 5252e941..6cbfac79 100644 --- a/xo-reader2/include/xo/reader2/DQuoteSsm.hpp +++ b/xo-reader2/include/xo/reader2/DQuoteSsm.hpp @@ -100,6 +100,13 @@ namespace xo { /** @defgroup scm-parenssm-admin-methods admin methods **/ ///@{ + /** update ssm for incoming quote token @p tk. + * with overall parser state in @p p_psm. + * advances from quote_0 -> quote_1. Otherwise error + **/ + void on_quote_token(const Token & tk, + ParserStateMachine * p_psm); + /** update ssm state for incoming leftparen token @p tk, * with overall parser state in @p p_psm **/ @@ -129,17 +136,9 @@ namespace xo { /** update ssm for expression @p expr (emitted by nested ssm), * with overall parser state in @p p_psm **/ - void on_parsed_expression(obj expr, + void on_quoted_literal(obj literal, ParserStateMachine * p_psm); - /** update ssm for expression @p expr (emitted by nested ssm) - * that's immediately followed by token @p tk - * with overall parser state in @p p_psm - **/ - void on_parsed_expression_with_token(obj expr, - const Token & tk, - ParserStateMachine * p_psmn); - ///@} /** @defgroup scm-parenssm-printable-facet printable facet methods **/ ///@{ diff --git a/xo-reader2/include/xo/reader2/DToplevelSeqSsm.hpp b/xo-reader2/include/xo/reader2/DToplevelSeqSsm.hpp index 743d2133..d20e751a 100644 --- a/xo-reader2/include/xo/reader2/DToplevelSeqSsm.hpp +++ b/xo-reader2/include/xo/reader2/DToplevelSeqSsm.hpp @@ -119,6 +119,11 @@ namespace xo { **/ void on_leftparen_token(const Token & tk, ParserStateMachine * p_psm); + /** update ssm for incoming quote token @p tk, overall parser state in @p p_psm + * starts nested syntax for quoted literal + **/ + void on_quote_token(const Token & tk, ParserStateMachine * p_psm); + /** update state for this syntax on parsed expression @p expr * from nested ssm. * overall parser state in @p p_psm diff --git a/xo-reader2/include/xo/reader2/ExpectQLiteralSsm.hpp b/xo-reader2/include/xo/reader2/ExpectQLiteralSsm.hpp new file mode 100644 index 00000000..562387dc --- /dev/null +++ b/xo-reader2/include/xo/reader2/ExpectQLiteralSsm.hpp @@ -0,0 +1,12 @@ +/** @file ExpectQLiteralSsm.hpp + * + * @author Roland Conybeare, Mar 2026 + **/ + +#pragma once + +#include "DExpectQLiteralSsm.hpp" +#include "ssm/ISyntaxStateMachine_DExpectQLiteralSsm.hpp" +#include "ssm/IPrintable_DExpectQLiteralSsm.hpp" + +/* end ExpectQLiteralSsm.hpp */ diff --git a/xo-reader2/include/xo/reader2/ParserStateMachine.hpp b/xo-reader2/include/xo/reader2/ParserStateMachine.hpp index f8214a39..0c01e452 100644 --- a/xo-reader2/include/xo/reader2/ParserStateMachine.hpp +++ b/xo-reader2/include/xo/reader2/ParserStateMachine.hpp @@ -186,6 +186,9 @@ namespace xo { void on_parsed_expression_with_token(obj expr, const Token & tk); + /** update state to consume quoted literal @p lit **/ + void on_quoted_literal(obj lit); + /** update state to respond to input token @p tk. * record output (if any) in @ref result_ **/ diff --git a/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectQLiteralSsm.hpp b/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectQLiteralSsm.hpp new file mode 100644 index 00000000..ec20bbc4 --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/IPrintable_DExpectQLiteralSsm.hpp @@ -0,0 +1,62 @@ +/** @file IPrintable_DExpectQLiteralSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DExpectQLiteralSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DExpectQLiteralSsm.json5] + **/ + +#pragma once + +#include "Printable.hpp" +#include +#include +#include "DExpectQLiteralSsm.hpp" + +namespace xo { namespace scm { class IPrintable_DExpectQLiteralSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::print::IPrintable_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class IPrintable_DExpectQLiteralSsm + **/ + class IPrintable_DExpectQLiteralSsm { + public: + /** @defgroup scm-printable-dexpectqliteralssm-type-traits **/ + ///@{ + using ppindentinfo = xo::print::APrintable::ppindentinfo; + using Copaque = xo::print::APrintable::Copaque; + using Opaque = xo::print::APrintable::Opaque; + ///@} + /** @defgroup scm-printable-dexpectqliteralssm-methods **/ + ///@{ + // const methods + /** Pretty-printing support for this object. +See [xo-indentlog/xo/indentlog/pretty.hpp] **/ + static bool pretty(const DExpectQLiteralSsm & 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_DExpectQLiteralSsm.hpp b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectQLiteralSsm.hpp new file mode 100644 index 00000000..303d137e --- /dev/null +++ b/xo-reader2/include/xo/reader2/ssm/ISyntaxStateMachine_DExpectQLiteralSsm.hpp @@ -0,0 +1,82 @@ +/** @file ISyntaxStateMachine_DExpectQLiteralSsm.hpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DExpectQLiteralSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_repr.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DExpectQLiteralSsm.json5] + **/ + +#pragma once + +#include "SyntaxStateMachine.hpp" +#include "SyntaxStateMachine.hpp" +#include "ssm/ISyntaxStateMachine_Xfer.hpp" +#include "DExpectQLiteralSsm.hpp" + +namespace xo { namespace scm { class ISyntaxStateMachine_DExpectQLiteralSsm; } } + +namespace xo { + namespace facet { + template <> + struct FacetImplementation + { + using ImplType = xo::scm::ISyntaxStateMachine_Xfer + ; + }; + } +} + +namespace xo { + namespace scm { + /** @class ISyntaxStateMachine_DExpectQLiteralSsm + **/ + class ISyntaxStateMachine_DExpectQLiteralSsm { + public: + /** @defgroup scm-syntaxstatemachine-dexpectqliteralssm-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-dexpectqliteralssm-methods **/ + ///@{ + // const methods + /** identify a type of syntax state machine **/ + static syntaxstatetype ssm_type(const DExpectQLiteralSsm & self) noexcept; + /** text describing expected/allowed input to this ssm in current state **/ + static std::string_view get_expect_str(const DExpectQLiteralSsm & self) noexcept; + + // non-const methods + /** operate state machine for incoming token @p tk **/ + static void on_token(DExpectQLiteralSsm & self, const Token & tk, ParserStateMachine * p_psm); + /** update stat machine for incoming parsed symbol @p sym **/ + static void on_parsed_symbol(DExpectQLiteralSsm & self, std::string_view sym, ParserStateMachine * p_psm); + /** operate state machine for incoming type description @p td **/ + static void on_parsed_typedescr(DExpectQLiteralSsm & self, TypeDescr td, ParserStateMachine * p_psm); + /** operate state machine for formal emitted by nested ssm **/ + static void on_parsed_formal(DExpectQLiteralSsm & 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(DExpectQLiteralSsm & 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(DExpectQLiteralSsm & self, DArray * arglist, ParserStateMachine * p_psm); + /** update state machine for nested parsed expression @p expr **/ + static void on_parsed_expression(DExpectQLiteralSsm & 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(DExpectQLiteralSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm); + /** update state machine for nested quoted literal @p lit **/ + static void on_quoted_literal(DExpectQLiteralSsm & 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/syntaxstatetype.hpp b/xo-reader2/include/xo/reader2/syntaxstatetype.hpp index 6c6849dc..68656581 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 rhs expression. See @ref DExpectExprSsm **/ expect_rhs_expression, + /** expecting a quoted literal. See @ref DExpectQLiteralSsm **/ + expect_qliteral, + /** comes lasts, counts number of valid enums **/ N }; diff --git a/xo-reader2/src/reader2/CMakeLists.txt b/xo-reader2/src/reader2/CMakeLists.txt index 862ca0e6..b00c4d04 100644 --- a/xo-reader2/src/reader2/CMakeLists.txt +++ b/xo-reader2/src/reader2/CMakeLists.txt @@ -65,6 +65,10 @@ set(SELF_SRCS ISyntaxStateMachine_DExpectExprSsm.cpp IPrintable_DExpectExprSsm.cpp + DExpectQLiteralSsm.cpp + ISyntaxStateMachine_DExpectQLiteralSsm.cpp + IPrintable_DExpectQLiteralSsm.cpp + DProgressSsm.cpp ISyntaxStateMachine_DProgressSsm.cpp IPrintable_DProgressSsm.cpp @@ -72,6 +76,7 @@ set(SELF_SRCS DQuoteSsm.cpp ISyntaxStateMachine_DQuoteSsm.cpp IPrintable_DQuoteSsm.cpp + ) xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) diff --git a/xo-reader2/src/reader2/DExpectExprSsm.cpp b/xo-reader2/src/reader2/DExpectExprSsm.cpp index 1248947c..57cf3836 100644 --- a/xo-reader2/src/reader2/DExpectExprSsm.cpp +++ b/xo-reader2/src/reader2/DExpectExprSsm.cpp @@ -7,10 +7,11 @@ #include "ParserStateMachine.hpp" #include "ParserStack.hpp" #include "SyntaxStateMachine.hpp" -#include "ssm/ISyntaxStateMachine_DProgressSsm.hpp" +#include "ProgressSsm.hpp" #include "DSequenceSsm.hpp" #include "IfElseSsm.hpp" #include "LambdaSsm.hpp" +#include "QuoteSsm.hpp" #include "syntaxstatetype.hpp" #include #include @@ -22,14 +23,10 @@ #include #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/pretty_expression.hpp" #endif namespace xo { @@ -140,6 +137,10 @@ namespace xo { this->on_def_token(tk, p_psm); return; + case tokentype::tk_quote: + this->on_quote_token(tk, p_psm); + return; + case tokentype::tk_string: this->on_string_token(tk, p_psm); return; @@ -169,7 +170,6 @@ namespace xo { case tokentype::tk_singleassign: case tokentype::tk_colon: case tokentype::tk_semicolon: - case tokentype::tk_quote: case tokentype::tk_leftbracket: case tokentype::tk_rightbracket: case tokentype::tk_rightbrace: @@ -344,6 +344,17 @@ namespace xo { Super::on_token(tk, p_psm); } + void + DExpectExprSsm::on_quote_token(const Token & tk, + ParserStateMachine * p_psm) + { + (void)tk; + + DProgressSsm::start(p_psm->parser_alloc(), p_psm); + DQuoteSsm::start(p_psm); + p_psm->on_token(Token::quote_token()); + } + void DExpectExprSsm::on_bool_token(const Token & tk, ParserStateMachine * p_psm) @@ -500,6 +511,21 @@ namespace xo { p_psm->on_parsed_expression_with_token(expr, tk); } +#ifdef NOT_YET + void + DExpectExprSsm::on_quoted_literal(obj lit, + ParserStateMachine * p_psm) + { + // note: impl here parallels .on_f64_token() .on_i64_token() etc. + + auto expr = DConstant::make(p_psm->expr_alloc(), lit); + + DProgressSsm::start(p_psm->parser_alloc(), + expr, + p_psm); + } +#endif + bool DExpectExprSsm::pretty(const ppindentinfo & ppii) const { diff --git a/xo-reader2/src/reader2/DExpectQLiteralSsm.cpp b/xo-reader2/src/reader2/DExpectQLiteralSsm.cpp new file mode 100644 index 00000000..78c62430 --- /dev/null +++ b/xo-reader2/src/reader2/DExpectQLiteralSsm.cpp @@ -0,0 +1,256 @@ +/* @file DExpectQLiteralSsm.cpp + * + * @author Roland Conybeare, Mar 2026 + */ + +#include "ExpectQLiteralSsm.hpp" +#include +//#include "DExpectFormalArgSsm.hpp" +//#include "ssm/ISyntaxStateMachine_DExpectFormalArgSsm.hpp" +//#include +//#include +//#include +//#include +//#include +#include + +namespace xo { +// using xo::print::APrintable; +// using xo::print::ppstate; +// using xo::print::ppindentinfo; + using xo::mm::AGCObject; +// using xo::mm::AAllocator; +// using xo::facet::FacetRegistry; +// using xo::reflect::typeseq; + + namespace scm { +#ifdef NOT_USING + const char * + formalarglstatetype_descr(formalarglstatetype x) { + switch (x) { + case formalarglstatetype::invalid: + return "invalid"; + case formalarglstatetype::argl_0: + return "argl_0"; + case formalarglstatetype::argl_1a: + return "argl_1a"; + case formalarglstatetype::argl_1b: + return "argl_1b"; + case formalarglstatetype::n_formalarglstatetype: + break; + } + + return "?formalarglstatetype"; + } +#endif + + DExpectQLiteralSsm::DExpectQLiteralSsm() + {} + + DExpectQLiteralSsm * + DExpectQLiteralSsm::_make(DArena & arena) + { + /* out-of-order so argl follows ssm in arena, + * consistent with any subsequent arglist realloc. + * Not a load-bearing choice however + */ + + void * mem = arena.alloc_for(); + + return new (mem) DExpectQLiteralSsm(); + } + + obj + DExpectQLiteralSsm::make(DArena & arena) + { + obj retval(_make(arena)); + + return retval; + } + + void + DExpectQLiteralSsm::start(ParserStateMachine * p_psm) + { + DArena::Checkpoint ckp = p_psm->parser_alloc().checkpoint(); + + p_psm->push_ssm(ckp, DExpectQLiteralSsm::make(p_psm->parser_alloc())); + } + + syntaxstatetype + DExpectQLiteralSsm::ssm_type() const noexcept { + return syntaxstatetype::expect_qliteral; + } + + std::string_view + DExpectQLiteralSsm::get_expect_str() const + { + return "leftparen|leftbracket|leftbrace|string|f64|i64|bool"; + } + + void + DExpectQLiteralSsm::on_token(const Token & tk, + ParserStateMachine * p_psm) + { + switch (tk.tk_type()) { + case tokentype::tk_f64: + this->on_f64_token(tk, p_psm); + return; + + case tokentype::tk_leftparen: + case tokentype::tk_comma: + case tokentype::tk_rightparen: + case tokentype::tk_lambda: + case tokentype::tk_def: + case tokentype::tk_if: + case tokentype::tk_symbol: + case tokentype::tk_colon: + case tokentype::tk_singleassign: + case tokentype::tk_string: + case tokentype::tk_i64: + case tokentype::tk_bool: + case tokentype::tk_semicolon: + case tokentype::tk_invalid: + case tokentype::tk_quote: + 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_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_then: + case tokentype::tk_else: + case tokentype::tk_let: + case tokentype::tk_in: + case tokentype::tk_end: + case tokentype::N: + break; + } + + Super::on_token(tk, p_psm); + } + + void + DExpectQLiteralSsm::on_f64_token(const Token & tk, + ParserStateMachine * p_psm) + { + auto literal = DFloat::box(p_psm->expr_alloc(), + tk.f64_value()); + + p_psm->pop_ssm(); + p_psm->on_quoted_literal(literal); + } + +#ifdef NOT_YET + void + DExpectQLiteralSsm::_accept_formal(obj expr_alloc, + DArena & parser_alloc, + const DUniqueString * param_name, + TypeDescr param_type) + { + /* note: param_type can be nullptr */ + TypeRef typeref + = TypeRef::dwim(TypeRef::prefix_type::from_chars("formal"), param_type); + + DVariable * var = DVariable::make(expr_alloc, + param_name, + typeref); + + // need AGCObject facet to use DArray here. + // May want to have gc feature that allows it to use + // FacetRegistry on memory that stores obj + // + // In this case doesn't matter since DExpectQLiteralSsm not actually collected! + + obj var_o(var); + + if (argl_->size() == argl_->capacity()) { + // need to expand argl_ capacity. + // If DArena were to allow it (i.e. offer a realloc() feature, + // could do this in place since this SSM is at the top of the parser stack. + + obj mm(&parser_alloc); + DArray * argl_2x = DArray::empty(mm, 2 * argl_->capacity()); + + for (DArray::size_type i = 0, n = argl_->size(); i < n; ++i) { + // TODO: prefer non-bounds-checked access here + argl_2x->push_back(argl_->at(i)); + } + + // update in place + this->argl_ = argl_2x; + } + + this->argl_->push_back(var_o); + } +#endif + +#ifdef NOT_YET + void + DExpectQLiteralSsm::on_leftparen_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (fastate_ == formalarglstatetype::argl_0) { + this->fastate_ = formalarglstatetype::argl_1a; + + DExpectFormalArgSsm::start(p_psm); + return; + } + + Super::on_token(tk, p_psm); + } + + void + DExpectQLiteralSsm::on_comma_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (fastate_ == formalarglstatetype::argl_1b) { + this->fastate_ = formalarglstatetype::argl_1a; + + DExpectFormalArgSsm::start(p_psm); + return; + } + + Super::on_token(tk, p_psm); + } + + void + DExpectQLiteralSsm::on_rightparen_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (fastate_ == formalarglstatetype::argl_1b) { + DArray * args = argl_; + + p_psm->pop_ssm(); + p_psm->on_parsed_formal_arglist(args); + return; + } + + Super::on_token(tk, p_psm); + } +#endif + + bool + DExpectQLiteralSsm::pretty(const ppindentinfo & ppii) const + { + return ppii.pps()->pretty_struct(ppii, + "DExpectQLiteralSsm", + refrtag("expect", this->get_expect_str())); + } + } /*namespace scm*/ +} /*namespace xo*/ + + +/* end DExpectQLiteralSsm.cpp */ diff --git a/xo-reader2/src/reader2/DProgressSsm.cpp b/xo-reader2/src/reader2/DProgressSsm.cpp index d2032f39..02d09e8a 100644 --- a/xo-reader2/src/reader2/DProgressSsm.cpp +++ b/xo-reader2/src/reader2/DProgressSsm.cpp @@ -3,8 +3,7 @@ * @author Roland Conybeare, Jan 2026 **/ -#include "DProgressSsm.hpp" -#include "ssm/ISyntaxStateMachine_DProgressSsm.hpp" +#include "ProgressSsm.hpp" #include "DExpectExprSsm.hpp" #include "ssm/ISyntaxStateMachine_DExpectExprSsm.hpp" @@ -189,6 +188,7 @@ namespace xo { start(parser_mm, lhs, optype::invalid, p_psm); } + void DProgressSsm::start(DArena & parser_mm, ParserStateMachine * p_psm) diff --git a/xo-reader2/src/reader2/DQuoteSsm.cpp b/xo-reader2/src/reader2/DQuoteSsm.cpp index b7f33456..1ca8a8a2 100644 --- a/xo-reader2/src/reader2/DQuoteSsm.cpp +++ b/xo-reader2/src/reader2/DQuoteSsm.cpp @@ -4,8 +4,9 @@ **/ #include "QuoteSsm.hpp" -#include "ExpectExprSsm.hpp" +#include "ExpectQLiteralSsm.hpp" #include "syntaxstatetype.hpp" +#include //#include namespace xo { @@ -88,6 +89,10 @@ namespace xo { { switch (tk.tk_type()) { + case tokentype::tk_quote: + this->on_quote_token(tk, p_psm); + return; + case tokentype::tk_leftbrace: this->on_leftbrace_token(tk, p_psm); return; @@ -108,7 +113,6 @@ namespace xo { case tokentype::tk_i64: case tokentype::tk_bool: case tokentype::tk_if: - case tokentype::tk_quote: case tokentype::tk_leftparen: case tokentype::tk_rightparen: case tokentype::tk_leftbracket: @@ -143,15 +147,25 @@ namespace xo { } void - DQuoteSsm::on_leftbrace_token(const Token & tk, - ParserStateMachine * p_psm) + DQuoteSsm::on_quote_token(const Token & tk, + ParserStateMachine * p_psm) { if (quote_xst_.code() == QuoteXst::code::quote_0) { this->quote_xst_ = QuoteXst(QuoteXst::code::quote_1); + return; + } - assert(false); - //DExpectQLiteralSsm::start(p_psm); - //return; + Super::on_token(tk, p_psm); + } + + void + DQuoteSsm::on_leftbrace_token(const Token & tk, + ParserStateMachine * p_psm) + { + if (quote_xst_.code() == QuoteXst::code::quote_1) { + this->quote_xst_ = QuoteXst(QuoteXst::code::quote_2); + DExpectQLiteralSsm::start(p_psm); + return; } Super::on_token(tk, p_psm); @@ -173,41 +187,24 @@ namespace xo { } void - DQuoteSsm::on_parsed_expression(obj expr, - ParserStateMachine * p_psm) + DQuoteSsm::on_quoted_literal(obj literal, + ParserStateMachine * p_psm) { if (quote_xst_.code() == QuoteXst::code::quote_2) { this->quote_xst_ = QuoteXst(QuoteXst::code::quote_3); - this->expr_ = expr; + this->expr_ = DConstant::make(p_psm->expr_alloc(), literal); return; } - Super::on_parsed_expression(expr, p_psm); - } - - void - DQuoteSsm::on_parsed_expression_with_token(obj expr, - const Token & tk, - ParserStateMachine * p_psm) - { - if (quote_xst_.code() == QuoteXst::code::quote_2) { - this->quote_xst_ = QuoteXst(QuoteXst::code::quote_3); - this->expr_ = expr; - - this->on_token(tk, p_psm); - - return; - } - - Super::on_parsed_expression(expr, p_psm); + Super::illegal_quoted_literal(literal, p_psm); } bool DQuoteSsm::pretty(const ppindentinfo & ppii) const { return ppii.pps()->pretty_struct(ppii, - "DParenSsm", + "DQuoteSsm", refrtag("quote_xst", quote_xst_), refrtag("expect", this->get_expect_str())); } diff --git a/xo-reader2/src/reader2/DToplevelSeqSsm.cpp b/xo-reader2/src/reader2/DToplevelSeqSsm.cpp index d7520e87..0473660f 100644 --- a/xo-reader2/src/reader2/DToplevelSeqSsm.cpp +++ b/xo-reader2/src/reader2/DToplevelSeqSsm.cpp @@ -9,12 +9,13 @@ #include "DLambdaSsm.hpp" #include "ProgressSsm.hpp" #include "DIfElseSsm.hpp" +#include "QuoteSsm.hpp" #include "ParenSsm.hpp" #include "ExpectExprSsm.hpp" #include "VarRef.hpp" -#include -#include +#include +//#include #include #include @@ -160,9 +161,12 @@ namespace xo { this->on_leftparen_token(tk, p_psm); return; + case tokentype::tk_quote: + this->on_quote_token(tk, p_psm); + return; + // all the not-yet handled cases case tokentype::tk_invalid: - case tokentype::tk_quote: case tokentype::tk_rightparen: case tokentype::tk_leftbracket: case tokentype::tk_rightbracket: @@ -424,6 +428,29 @@ namespace xo { Super::on_token(tk, p_psm); } + void + DToplevelSeqSsm::on_quote_token(const Token & tk, + ParserStateMachine * p_psm) + { + switch (seqtype_) { + case exprseqtype::toplevel_interactive: { + DProgressSsm::start(p_psm->parser_alloc(), + p_psm); + DQuoteSsm::start(p_psm); + p_psm->on_token(Token::quote_token()); + + return; + } + case exprseqtype::toplevel_batch: + break; + case exprseqtype::N: + assert(false); // unreachable + break; + } + + Super::on_token(tk, p_psm); + } + void DToplevelSeqSsm::on_parsed_expression(obj expr, ParserStateMachine * p_psm) diff --git a/xo-reader2/src/reader2/IPrintable_DExpectQLiteralSsm.cpp b/xo-reader2/src/reader2/IPrintable_DExpectQLiteralSsm.cpp new file mode 100644 index 00000000..24c33902 --- /dev/null +++ b/xo-reader2/src/reader2/IPrintable_DExpectQLiteralSsm.cpp @@ -0,0 +1,28 @@ +/** @file IPrintable_DExpectQLiteralSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/IPrintable_DExpectQLiteralSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/IPrintable_DExpectQLiteralSsm.json5] +**/ + +#include "ssm/IPrintable_DExpectQLiteralSsm.hpp" + +namespace xo { + namespace scm { + auto + IPrintable_DExpectQLiteralSsm::pretty(const DExpectQLiteralSsm & self, const ppindentinfo & ppii) -> bool + { + return self.pretty(ppii); + } + + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end IPrintable_DExpectQLiteralSsm.cpp */ diff --git a/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectQLiteralSsm.cpp b/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectQLiteralSsm.cpp new file mode 100644 index 00000000..977b1194 --- /dev/null +++ b/xo-reader2/src/reader2/ISyntaxStateMachine_DExpectQLiteralSsm.cpp @@ -0,0 +1,79 @@ +/** @file ISyntaxStateMachine_DExpectQLiteralSsm.cpp + * + * Generated automagically from ingredients: + * 1. code generator: + * [xo-facet/codegen/genfacet] + * arguments: + * --input [idl/ISyntaxStateMachine_DExpectQLiteralSsm.json5] + * 2. jinja2 template for abstract facet .hpp file: + * [iface_facet_any.hpp.j2] + * 3. idl for facet methods + * [idl/ISyntaxStateMachine_DExpectQLiteralSsm.json5] +**/ + +#include "ssm/ISyntaxStateMachine_DExpectQLiteralSsm.hpp" + +namespace xo { + namespace scm { + auto + ISyntaxStateMachine_DExpectQLiteralSsm::ssm_type(const DExpectQLiteralSsm & self) noexcept -> syntaxstatetype + { + return self.ssm_type(); + } + + auto + ISyntaxStateMachine_DExpectQLiteralSsm::get_expect_str(const DExpectQLiteralSsm & self) noexcept -> std::string_view + { + return self.get_expect_str(); + } + + auto + ISyntaxStateMachine_DExpectQLiteralSsm::on_token(DExpectQLiteralSsm & self, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_token(tk, p_psm); + } + auto + ISyntaxStateMachine_DExpectQLiteralSsm::on_parsed_symbol(DExpectQLiteralSsm & self, std::string_view sym, ParserStateMachine * p_psm) -> void + { + self.on_parsed_symbol(sym, p_psm); + } + auto + ISyntaxStateMachine_DExpectQLiteralSsm::on_parsed_typedescr(DExpectQLiteralSsm & self, TypeDescr td, ParserStateMachine * p_psm) -> void + { + self.on_parsed_typedescr(td, p_psm); + } + auto + ISyntaxStateMachine_DExpectQLiteralSsm::on_parsed_formal(DExpectQLiteralSsm & self, const DUniqueString * param_name, TypeDescr param_type, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal(param_name, param_type, p_psm); + } + auto + ISyntaxStateMachine_DExpectQLiteralSsm::on_parsed_formal_with_token(DExpectQLiteralSsm & 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_DExpectQLiteralSsm::on_parsed_formal_arglist(DExpectQLiteralSsm & self, DArray * arglist, ParserStateMachine * p_psm) -> void + { + self.on_parsed_formal_arglist(arglist, p_psm); + } + auto + ISyntaxStateMachine_DExpectQLiteralSsm::on_parsed_expression(DExpectQLiteralSsm & self, obj expr, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression(expr, p_psm); + } + auto + ISyntaxStateMachine_DExpectQLiteralSsm::on_parsed_expression_with_token(DExpectQLiteralSsm & self, obj expr, const Token & tk, ParserStateMachine * p_psm) -> void + { + self.on_parsed_expression_with_token(expr, tk, p_psm); + } + auto + ISyntaxStateMachine_DExpectQLiteralSsm::on_quoted_literal(DExpectQLiteralSsm & self, obj lit, ParserStateMachine * p_psm) -> void + { + self.on_quoted_literal(lit, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + +/* end ISyntaxStateMachine_DExpectQLiteralSsm.cpp */ diff --git a/xo-reader2/src/reader2/ParserStateMachine.cpp b/xo-reader2/src/reader2/ParserStateMachine.cpp index bade16dc..125ca1dd 100644 --- a/xo-reader2/src/reader2/ParserStateMachine.cpp +++ b/xo-reader2/src/reader2/ParserStateMachine.cpp @@ -330,6 +330,12 @@ namespace xo { this->top_ssm().on_parsed_expression_with_token(expr, tk, this); } + void + ParserStateMachine::on_quoted_literal(obj lit) + { + this->top_ssm().on_quoted_literal(lit, this); + } + void ParserStateMachine::on_token(const Token & tk) { diff --git a/xo-reader2/src/reader2/reader2_register_facets.cpp b/xo-reader2/src/reader2/reader2_register_facets.cpp index 59d91907..b3fe47be 100644 --- a/xo-reader2/src/reader2/reader2_register_facets.cpp +++ b/xo-reader2/src/reader2/reader2_register_facets.cpp @@ -13,11 +13,13 @@ #include "ApplySsm.hpp" #include "SequenceSsm.hpp" #include "ParenSsm.hpp" +#include "QuoteSsm.hpp" #include "ExpectFormalArglistSsm.hpp" #include "ExpectFormalArgSsm.hpp" #include "ExpectSymbolSsm.hpp" #include "ExpectTypeSsm.hpp" #include "ExpectExprSsm.hpp" +#include "ExpectQLiteralSsm.hpp" #include "ProgressSsm.hpp" #include "SyntaxStateMachine.hpp" @@ -75,6 +77,12 @@ namespace xo { FacetRegistry::register_impl(); FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + + FacetRegistry::register_impl(); + FacetRegistry::register_impl(); + // misc types showing up in aux arena TypeRegistry::register_type(); // misc types showing up in parser stack arena @@ -91,6 +99,7 @@ namespace xo { log && log(xtag("DExpectExprSsm.tseq", typeseq::id())); log && log(xtag("DProgressSsm.tseq", typeseq::id())); log && log(xtag("DParenSsm.tseq", typeseq::id())); + log && log(xtag("DQuoteSsm.tseq", typeseq::id())); log && log(xtag("ASyntaxStateMachine.tseq", typeseq::id())); return true; diff --git a/xo-reader2/src/reader2/syntaxstatetype.cpp b/xo-reader2/src/reader2/syntaxstatetype.cpp index 0d7dd7e2..c4eb3667 100644 --- a/xo-reader2/src/reader2/syntaxstatetype.cpp +++ b/xo-reader2/src/reader2/syntaxstatetype.cpp @@ -41,6 +41,8 @@ namespace xo { return "expect-type"; case syntaxstatetype::expect_rhs_expression: return "expect-rhs-expression"; + case syntaxstatetype::expect_qliteral: + return "expect-qliteral"; case syntaxstatetype::N: break; } diff --git a/xo-reader2/utest/SchematikaParser.test.cpp b/xo-reader2/utest/SchematikaParser.test.cpp index 274cca2f..6637ad9a 100644 --- a/xo-reader2/utest/SchematikaParser.test.cpp +++ b/xo-reader2/utest/SchematikaParser.test.cpp @@ -849,7 +849,7 @@ namespace xo { { const auto & testname = Catch::getResultCapture().getCurrentTestName(); - constexpr bool c_debug_flag = true; + constexpr bool c_debug_flag = false; scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); @@ -1151,7 +1151,7 @@ namespace xo { const auto & testname = Catch::getResultCapture().getCurrentTestName(); - constexpr bool c_debug_flag = true; + constexpr bool c_debug_flag = false; scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); ParserFixture fixture(testname, c_debug_flag); @@ -1203,6 +1203,84 @@ namespace xo { log && fixture.log_memory_layout(&log); } + TEST_CASE("SchematikaParser-batch-qliteral1", "[reader2][SchematikaParser]") + { + // top-level recursive function definition + + 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_interactive_session(); + + /** Walkthrough parsing input equivalent to: + * + * #q{ 4.5 } ; + * ^ ^ ^ ^ ^ + * 0 1 2 3 4 + **/ + + std::vector tk_v{ + /* [ 0] */ Token::quote_token(), + + /* [ 1] */ Token::leftbrace_token(), + /* [ 2] */ Token::f64_token("4.5"), + /* [ 3] */ Token::rightbrace_token(), + /* [ 4] */ Token::semicolon_token(), + }; + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + + log && fixture.log_memory_layout(&log); + } + + TEST_CASE("SchematikaParser-batch-qliteral2", "[reader2][SchematikaParser]") + { + // top-level recursive function definition + + 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_interactive_session(); + + /** Walkthrough parsing input equivalent to: + * + * #q{ 4.5 } + #q { 7.2 }; + * ^ ^ ^ ^ ^ ^ ^ ^ ^^ + * 0 1 2 3 4 5 6 7 8| + * 9 + **/ + + std::vector tk_v{ + /* [ 0] */ Token::quote_token(), + /* [ 1] */ Token::leftbrace_token(), + /* [ 2] */ Token::f64_token("4.5"), + /* [ 3] */ Token::rightbrace_token(), + + /* [ 4] */ Token::plus_token(), + + /* [ 5] */ Token::quote_token(), + /* [ 6] */ Token::leftbrace_token(), + /* [ 7] */ Token::f64_token("7.2"), + /* [ 8] */ Token::rightbrace_token(), + + /* [ 9] */ Token::semicolon_token(), + }; + + utest_tokenizer_loop(&parser, tk_v, c_debug_flag); + + log && fixture.log_memory_layout(&log); + } + } /*namespace ut*/ } /*namespace xo*/ diff --git a/xo-tokenizer2/include/xo/tokenizer2/Token.hpp b/xo-tokenizer2/include/xo/tokenizer2/Token.hpp index 9ddd0181..9c748933 100644 --- a/xo-tokenizer2/include/xo/tokenizer2/Token.hpp +++ b/xo-tokenizer2/include/xo/tokenizer2/Token.hpp @@ -88,7 +88,7 @@ namespace xo { return Token(tokentype::tk_symbol, txt); } /** token representing quote @c "'" **/ - static Token quote() { return Token(tokentype::tk_quote); } + static Token quote_token() { return Token(tokentype::tk_quote); } /** token representing left angle bracket @c "<" **/ static Token leftangle() { return Token(tokentype::tk_leftangle); } /** token representing right angle bracket @c ">" **/ diff --git a/xo-tokenizer2/src/tokenizer2/Tokenizer.cpp b/xo-tokenizer2/src/tokenizer2/Tokenizer.cpp index 8821cd65..323c2d8d 100644 --- a/xo-tokenizer2/src/tokenizer2/Tokenizer.cpp +++ b/xo-tokenizer2/src/tokenizer2/Tokenizer.cpp @@ -429,6 +429,7 @@ namespace xo { break; } + case '#': case 'a': case 'A': case 'b': case 'B': case 'c': case 'C':