From 818127a44652ea83bdd127c4dea96882e1a77eef Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sun, 18 Aug 2024 23:29:36 -0400 Subject: [PATCH] xo-reader: refactor: simplify define_xs behavior --- include/xo/reader/define_xs.hpp | 61 ++++++---- src/reader/define_xs.cpp | 207 ++++++++++---------------------- src/reader/exprseq_xs.cpp | 7 +- utest/parser.test.cpp | 20 +-- 4 files changed, 112 insertions(+), 183 deletions(-) diff --git a/include/xo/reader/define_xs.hpp b/include/xo/reader/define_xs.hpp index 59b55d83..58846f33 100644 --- a/include/xo/reader/define_xs.hpp +++ b/include/xo/reader/define_xs.hpp @@ -12,6 +12,36 @@ namespace xo { namespace scm { + /** + * def foo : f64 = 1 ; + * ^ ^ ^ ^ ^ ^ ^ ^ + * | | | | | | | (done) + * | | | | | | def_6:expect_rhs_expression:expr_progress + * | | | | | def_5:expect_rhs_expression + * | | | | def_4 + * | | | def_3:expect_type + * | | def_2 + * | def_1:expect_symbol + * def_0 + * expect_toplevel_expression_sequence + * + * def_0 --on_def_token()--> def_1 + * def_1 --on_symbol()--> def_2 + * def_2 --on_colon_token()--> def_3 + * --on_singleassign_token()--> def_5 + * def_3 --on_typedescr()--> def_4 + * def_4 --on_singleassign_token()--> def_5 + * def_5 --on_expr()--> def_6 + * def_6 --on_semicolon_token()--> (done) + * + * def_1:expect_symbol: got 'def' keyword, symbol to follow + * def_1: got symbol name + * def_3:expect_symbol got (optional) colon, type name to follow + * def_4: got symbol type + * def_6:expect_rhs_expression got (optional) equal sign, value to follow + * (done): definition complete, pop exprstate from stack + * + **/ enum class defexprstatetype { invalid = -1, @@ -21,6 +51,7 @@ namespace xo { def_3, def_4, def_5, + def_6, n_defexprstatetype, }; @@ -38,12 +69,13 @@ namespace xo { virtual ~define_xs() = default; static const define_xs * from(const exprstate * x) { return dynamic_cast(x); } - static std::unique_ptr def_0(); + + static void start(exprstatestack * p_stack); defexprstatetype defxs_type() const { return defxs_type_; } bool admits_rightparen() const; - bool admits_colon() const; + //bool admits_colon() const; bool admits_semicolon() const; //bool admits_symbol() const; @@ -58,6 +90,8 @@ namespace xo { virtual void on_typedescr(TypeDescr td, exprstatestack * p_stack, rp * p_emit_expr) override; + virtual void on_def_token(const token_type & tk, + exprstatestack * p_stack) override; virtual void on_colon_token(const token_type & tk, exprstatestack * p_stack) override; virtual void on_semicolon_token(const token_type & tk, @@ -75,26 +109,9 @@ namespace xo { virtual void print(std::ostream & os) const override; private: - /** - * def foo : f64 = 1 ; - * ^ ^ ^ ^ ^ ^ ^ ^ - * | | | | | | | (done) - * | | | | | | def_4:expect_rhs_expression:expr_progress - * | | | | | def_4:expect_rhs_expression - * | | | | def_3 - * | | | def_2:expect_type - * | | def_1 - * | def_0:expect_symbol - * expect_toplevel_expression_sequence - * - * def_0:expect_symbol: got 'def' keyword, symbol to follow - * def_1: got symbol name - * def_2:expect_symbol got (optional) colon, type name to follow - * def_3: got symbol type - * def_4:expect_rhs_expression got (optional) equal sign, value to follow - * (done): definition complete, pop exprstate from stack - * - **/ + static std::unique_ptr make(); + + private: defexprstatetype defxs_type_; /** scaffold a define-expression here **/ rp def_expr_; diff --git a/src/reader/define_xs.cpp b/src/reader/define_xs.cpp index d3c2d5c2..c3b977a2 100644 --- a/src/reader/define_xs.cpp +++ b/src/reader/define_xs.cpp @@ -1,48 +1,30 @@ /* @file define_xs.cpp */ #include "define_xs.hpp" +#include "expect_symbol_xs.hpp" #include "expect_expr_xs.hpp" #include "expect_type_xs.hpp" namespace xo { namespace scm { std::unique_ptr - define_xs::def_0() { + define_xs::make() { return std::make_unique(define_xs(DefineExprAccess::make_empty())); } + void + define_xs::start(exprstatestack * p_stack) + { + p_stack->push_exprstate(define_xs::make()); + p_stack->top_exprstate().on_def_token(token_type::def(), p_stack); + } + define_xs::define_xs(rp def_expr) : exprstate(exprstatetype::defexpr), defxs_type_{defexprstatetype::def_0}, def_expr_{std::move(def_expr)} {} - bool - define_xs::admits_colon() const { - switch (defxs_type_) { - - case defexprstatetype::def_0: - return false; - - case defexprstatetype::def_1: - return true; - - case defexprstatetype::def_2: - case defexprstatetype::def_3: - case defexprstatetype::def_4: - case defexprstatetype::def_5: - return false; - - case defexprstatetype::invalid: - case defexprstatetype::n_defexprstatetype: - /* unreachable */ - assert(false); - return false; - } - - return false; - } - bool define_xs::admits_semicolon() const { switch (defxs_type_) { @@ -52,8 +34,9 @@ namespace xo { case defexprstatetype::def_2: case defexprstatetype::def_3: case defexprstatetype::def_4: - return false; case defexprstatetype::def_5: + return false; + case defexprstatetype::def_6: return true; case defexprstatetype::invalid: @@ -66,73 +49,6 @@ namespace xo { return false; } -#ifdef OBSOLETE - bool - define_xs::admits_singleassign() const { - switch (defxs_type_) { - - case defexprstatetype::def_0: - return false; - - case defexprstatetype::def_1: - return true; - - case defexprstatetype::def_2: - return false; - - case defexprstatetype::def_3: - return true; - - case defexprstatetype::def_4: - case defexprstatetype::def_5: - return false; - - case defexprstatetype::invalid: - case defexprstatetype::n_defexprstatetype: - /* unreachable */ - assert(false); - return false; - } - - return false; - } -#endif - -#ifdef OBSOLETE - bool - define_xs::admits_leftparen() const { - switch (defxs_type_) { - - case defexprstatetype::def_0: - case defexprstatetype::def_1: - case defexprstatetype::def_2: - case defexprstatetype::def_3: - case defexprstatetype::def_4: - case defexprstatetype::def_5: - /* input like - * def foo : f64 = ( - * ^ ^ ^ ^ ^ - * | | | | def_4 - * | | | def_3 - * | | def_2 - * | def_1 - * def_0 - * - * not allowed or relies on pushing another state - */ - return false; - - case defexprstatetype::invalid: - case defexprstatetype::n_defexprstatetype: - /* unreachable */ - assert(false); - return false; - } - - return false; - } -#endif - bool define_xs::admits_rightparen() const { switch (defxs_type_) { @@ -143,6 +59,7 @@ namespace xo { case defexprstatetype::def_3: case defexprstatetype::def_4: case defexprstatetype::def_5: + case defexprstatetype::def_6: return false; case defexprstatetype::invalid: @@ -166,10 +83,11 @@ namespace xo { case defexprstatetype::def_1: case defexprstatetype::def_2: case defexprstatetype::def_3: + case defexprstatetype::def_4: /* NOT IMPLEMENTED */ assert(false); return; - case defexprstatetype::def_4: { + case defexprstatetype::def_5: { /* have all the ingredients to create an expression * representing a definition * @@ -186,11 +104,11 @@ namespace xo { rp def_expr = this->def_expr_; - this->defxs_type_ = defexprstatetype::def_5; + this->defxs_type_ = defexprstatetype::def_6; return; } - case defexprstatetype::def_5: + case defexprstatetype::def_6: assert(false); return; @@ -209,16 +127,20 @@ namespace xo { { switch (this->defxs_type_) { case defexprstatetype::def_0: - this->defxs_type_ = defexprstatetype::def_1; + assert(false); + return; + + case defexprstatetype::def_1: + this->defxs_type_ = defexprstatetype::def_2; this->def_expr_->assign_lhs_name(symbol_name); //this->def_lhs_symbol_ = symbol_name; return; - case defexprstatetype::def_1: case defexprstatetype::def_2: case defexprstatetype::def_3: case defexprstatetype::def_4: case defexprstatetype::def_5: + case defexprstatetype::def_6: /* NOT IMPLEMENTED */ assert(false); return; @@ -240,12 +162,13 @@ namespace xo { case defexprstatetype::def_0: case defexprstatetype::def_1: + case defexprstatetype::def_2: /* NOT IMPLEMENTED (ill-formed program) */ assert(false); return; - case defexprstatetype::def_2: - this->defxs_type_ = defexprstatetype::def_3; + case defexprstatetype::def_3: + this->defxs_type_ = defexprstatetype::def_4; this->cvt_expr_ = ConvertExprAccess::make(td /*dest_type*/, nullptr /*source_expr*/); this->def_expr_->assign_rhs(this->cvt_expr_); @@ -253,9 +176,9 @@ namespace xo { return; - case defexprstatetype::def_3: case defexprstatetype::def_4: case defexprstatetype::def_5: + case defexprstatetype::def_6: /* NOT IMPLEMENTED */ assert(false); return; @@ -269,28 +192,38 @@ namespace xo { } void - define_xs::on_colon_token(const token_type & /*tk*/, + define_xs::on_def_token(const token_type & tk, + exprstatestack * p_stack) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + //constexpr const char * self_name = "define_xs::on_def_token"; + + if (this->defxs_type_ == defexprstatetype::def_0) { + this->defxs_type_ = defexprstatetype::def_1; + + p_stack->push_exprstate(expect_symbol_xs::expect_symbol_expression()); + } else { + exprstate::on_def_token(tk, p_stack); + } + } + + void + define_xs::on_colon_token(const token_type & tk, exprstatestack * p_stack) { constexpr bool c_debug_flag = true; scope log(XO_DEBUG(c_debug_flag)); - constexpr const char * self_name = "exprstate::on_colon"; + //constexpr const char * self_name = "define_xs::on_colon_token"; - /* lots of illegal states */ - if (!this->admits_colon()) - { - throw std::runtime_error(tostr(self_name, - ": unexpected colon for parsing state", - xtag("state", *this))); - } - - if (this->defxs_type_ == defexprstatetype::def_1) { - this->defxs_type_ = defexprstatetype::def_2; + if (this->defxs_type_ == defexprstatetype::def_2) { + this->defxs_type_ = defexprstatetype::def_3; p_stack->push_exprstate(expect_type_xs::make()); } else { - assert(false); + exprstate::on_colon_token(tk, p_stack); } } @@ -311,7 +244,7 @@ namespace xo { xtag("state", *this))); } - if (this->defxs_type_ == defexprstatetype::def_5) { + if (this->defxs_type_ == defexprstatetype::def_6) { rp expr = this->def_expr_; std::unique_ptr self = p_stack->pop_exprstate(); @@ -336,21 +269,22 @@ namespace xo { /* * def foo = 1 ; * def foo : f64 = 1 ; - * ^ ^ ^ ^ ^ ^ ^ - * | | | | | | (done) - * | | | | | def_4:expect_rhs_expression - * | | | | def_3 - * | | | def_2:expect_type - * | | def_1 - * | def_0:expect_symbol + * ^ ^ ^ ^ ^ ^ ^ ^ + * | | | | | | | (done) + * | | | | | | def_6 + * | | | | | def_5:expect_rhs_expression + * | | | | def_4 + * | | | def_3:expect_type + * | | def_2 + * | def_1:expect_symbol * expect_toplevel_expression_sequence * - * note that we skip from def_1 -> def_4 if '=' instead of ':' + * note that we skip from def_2 -> def_5 if '=' instead of ':' */ - if ((this->defxs_type_ == defexprstatetype::def_1) - || (this->defxs_type_ == defexprstatetype::def_3)) + if ((this->defxs_type_ == defexprstatetype::def_2) + || (this->defxs_type_ == defexprstatetype::def_4)) { - this->defxs_type_ = defexprstatetype::def_4; + this->defxs_type_ = defexprstatetype::def_5; p_stack->push_exprstate(expect_expr_xs::expect_rhs_expression()); } else { @@ -358,23 +292,6 @@ namespace xo { } } -#ifdef OBSOLETE - void - define_xs::on_leftparen_token(const token_type & tk, - exprstatestack * /*p_stack*/, - rp * /*p_emit_expr*/) - { - constexpr bool c_debug_flag = true; - scope log(XO_DEBUG(c_debug_flag)); - - constexpr const char * self_name = "exprstate::on_leftparen"; - - this->illegal_input_error(self_name, tk); - - assert(false); /* inserting this during refactor...? */ - } -#endif - void define_xs::on_rightparen_token(const token_type & tk, exprstatestack * /*p_stack*/, diff --git a/src/reader/exprseq_xs.cpp b/src/reader/exprseq_xs.cpp index 042c5eb3..ed613dd2 100644 --- a/src/reader/exprseq_xs.cpp +++ b/src/reader/exprseq_xs.cpp @@ -26,12 +26,7 @@ namespace xo { //constexpr const char * c_self_name = "exprseq_xs::on_def_token"; - p_stack->push_exprstate(define_xs::def_0()); - - /* todo: replace: - * expect_symbol_or_function_signature() - */ - p_stack->push_exprstate(expect_symbol_xs::expect_symbol_expression()); + define_xs::start(p_stack); /* keyword 'def' introduces a definition: * def pi : f64 = 3.14159265 diff --git a/utest/parser.test.cpp b/utest/parser.test.cpp index 8611a40a..e2190f91 100644 --- a/utest/parser.test.cpp +++ b/utest/parser.test.cpp @@ -42,7 +42,7 @@ namespace xo { /* stack should be: * * expect_toplevel_expression_sequence - * def_0 + * def_1 * expect_symbol */ CHECK(parser.stack_size() == 3); @@ -51,7 +51,7 @@ namespace xo { if (parser.stack_size() > 1) { CHECK(parser.i_exstype(1) == exprstatetype::defexpr); REQUIRE(define_xs::from(parser.i_exstate(1)) != nullptr); - CHECK(define_xs::from(parser.i_exstate(1))->defxs_type() == defexprstatetype::def_0); + CHECK(define_xs::from(parser.i_exstate(1))->defxs_type() == defexprstatetype::def_1); } if (parser.stack_size() > 2) CHECK(parser.i_exstype(2) @@ -80,7 +80,7 @@ namespace xo { if (parser.stack_size() > 0) { CHECK(parser.i_exstype(0) == exprstatetype::defexpr); REQUIRE(define_xs::from(parser.i_exstate(0)) != nullptr); - CHECK(define_xs::from(parser.i_exstate(0))->defxs_type() == defexprstatetype::def_1); + CHECK(define_xs::from(parser.i_exstate(0))->defxs_type() == defexprstatetype::def_2); } if (parser.stack_size() > 1) CHECK(parser.i_exstype(1) @@ -107,7 +107,7 @@ namespace xo { /* stack should be: * * expect_toplevel_expression_sequence - * def_2 + * def_3 * expect_symbol */ CHECK(parser.stack_size() == 3); @@ -116,7 +116,7 @@ namespace xo { if (parser.stack_size() > 1) { CHECK(parser.i_exstype(1) == exprstatetype::defexpr); REQUIRE(define_xs::from(parser.i_exstate(1)) != nullptr); - CHECK(define_xs::from(parser.i_exstate(1))->defxs_type() == defexprstatetype::def_2); + CHECK(define_xs::from(parser.i_exstate(1))->defxs_type() == defexprstatetype::def_3); } if (parser.stack_size() > 2) CHECK(parser.i_exstype(2) @@ -141,13 +141,13 @@ namespace xo { /* stack should be: * * expect_toplevel_expression_sequence - * def_3 + * def_4 */ CHECK(parser.stack_size() == 2); if (parser.stack_size() > 0) { CHECK(parser.i_exstype(0) == exprstatetype::defexpr); REQUIRE(define_xs::from(parser.i_exstate(0)) != nullptr); - CHECK(define_xs::from(parser.i_exstate(0))->defxs_type() == defexprstatetype::def_3); + CHECK(define_xs::from(parser.i_exstate(0))->defxs_type() == defexprstatetype::def_4); } if (parser.stack_size() > 1) CHECK(parser.i_exstype(1) @@ -185,7 +185,7 @@ namespace xo { /* stack should be * * expect_toplevel_expression_sequence - * def_4 + * def_5 * expect_expression */ CHECK(parser.stack_size() == 3); @@ -194,7 +194,7 @@ namespace xo { if (parser.stack_size() > 1) { CHECK(parser.i_exstype(1) == exprstatetype::defexpr); REQUIRE(define_xs::from(parser.i_exstate(1)) != nullptr); - CHECK(define_xs::from(parser.i_exstate(1))->defxs_type() == defexprstatetype::def_4); + CHECK(define_xs::from(parser.i_exstate(1))->defxs_type() == defexprstatetype::def_5); } if (parser.stack_size() > 2) CHECK(parser.i_exstype(2) @@ -233,7 +233,7 @@ namespace xo { if (parser.stack_size() > 2) { CHECK(parser.i_exstype(2) == exprstatetype::defexpr); REQUIRE(define_xs::from(parser.i_exstate(2)) != nullptr); - CHECK(define_xs::from(parser.i_exstate(2))->defxs_type() == defexprstatetype::def_4); + CHECK(define_xs::from(parser.i_exstate(2))->defxs_type() == defexprstatetype::def_5); } if (parser.stack_size() > 3) CHECK(parser.i_exstype(3)