From dad6b2562c5d485851094287289c4b844ced7359 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Tue, 20 Aug 2024 13:32:08 -0400 Subject: [PATCH] xo-reader: + sequence expression (aka beginexpr or block) --- include/xo/reader/expect_expr_xs.hpp | 29 ++++++++++- include/xo/reader/exprstate.hpp | 13 +++++ include/xo/reader/sequence_xs.hpp | 34 ++++++++++++ src/reader/CMakeLists.txt | 1 + src/reader/expect_expr_xs.cpp | 69 +++++++++++++++++++++--- src/reader/exprstate.cpp | 26 ++++++++++ src/reader/sequence_xs.cpp | 78 ++++++++++++++++++++++++++++ 7 files changed, 241 insertions(+), 9 deletions(-) create mode 100644 include/xo/reader/sequence_xs.hpp create mode 100644 src/reader/sequence_xs.cpp diff --git a/include/xo/reader/expect_expr_xs.hpp b/include/xo/reader/expect_expr_xs.hpp index 650a3195..c3e8a513 100644 --- a/include/xo/reader/expect_expr_xs.hpp +++ b/include/xo/reader/expect_expr_xs.hpp @@ -15,16 +15,29 @@ namespace xo { **/ class expect_expr_xs : public exprstate { public: - expect_expr_xs(); + explicit expect_expr_xs(bool allow_defs, + bool cxl_on_rightbrace); static void start(parserstatemachine * p_psm); + static void start(bool allow_defs, + bool cxl_on_rightbrace, + parserstatemachine * p_psm); virtual void on_lambda_token(const token_type & tk, parserstatemachine * p_psm) override; + virtual void on_def_token(const token_type & tk, + parserstatemachine * p_psm) override; + virtual void on_leftparen_token(const token_type & tk, parserstatemachine * p_psm) override; + virtual void on_leftbrace_token(const token_type & tk, + parserstatemachine * p_psm) override; + + virtual void on_rightbrace_token(const token_type & tk, + parserstatemachine * p_psm) override; + virtual void on_symbol_token(const token_type & tk, parserstatemachine * p_psm) override; @@ -36,7 +49,19 @@ namespace xo { parserstatemachine * p_psm) override; private: - static std::unique_ptr make(); + static std::unique_ptr make(bool allow_defs, + bool cxl_on_rightbrace); + + private: + /* if true: allow a define-expression here */ + bool allow_defs_ = false; + /* if true: expecting either: + * - expression + * - right brace '}', in which case no expression + * if false: expecting + * - expression + */ + bool cxl_on_rightbrace_ = false; }; } /*namespace scm*/ diff --git a/include/xo/reader/exprstate.hpp b/include/xo/reader/exprstate.hpp index 3e79dee4..b22bf85f 100644 --- a/include/xo/reader/exprstate.hpp +++ b/include/xo/reader/exprstate.hpp @@ -33,6 +33,11 @@ namespace xo { **/ parenexpr, + /** handle sequence expression (aka block) + * see @ref sequence_xs + **/ + sequenceexpr, + expect_rhs_expression, expect_symbol, expect_type, @@ -146,6 +151,14 @@ namespace xo { virtual void on_rightparen_token(const token_type & tk, parserstatemachine * p_psm); + /** handle incoming '{' token **/ + virtual void on_leftbrace_token(const token_type & tk, + parserstatemachine * p_psm); + + /** handle incoming '}' token **/ + virtual void on_rightbrace_token(const token_type & tk, + parserstatemachine * p_psm); + /** handle incoming operator token **/ virtual void on_operator_token(const token_type & tk, parserstatemachine * p_psm); diff --git a/include/xo/reader/sequence_xs.hpp b/include/xo/reader/sequence_xs.hpp new file mode 100644 index 00000000..a33cf3e1 --- /dev/null +++ b/include/xo/reader/sequence_xs.hpp @@ -0,0 +1,34 @@ +/** @file sequence_xs.hpp + * + * Author: Roland Conybeare + **/ + +#pragma once + +#include "exprstate.hpp" + +namespace xo { + namespace scm { + class sequence_xs : public exprstate { + public: + sequence_xs(); + + static void start(parserstatemachine * p_psm); + + virtual void on_expr(ref::brw expr, + parserstatemachine * p_psm) override; + + virtual void on_rightbrace_token(const token_type & tk, + parserstatemachine * p_psm) override; + + private: + static std::unique_ptr make(); + + private: + std::vector> expr_v_; + }; + } /*namespace scm*/ +} /*namespace xo*/ + + +/** end sequence_xs.hpp **/ diff --git a/src/reader/CMakeLists.txt b/src/reader/CMakeLists.txt index 83dc675d..5db87d7a 100644 --- a/src/reader/CMakeLists.txt +++ b/src/reader/CMakeLists.txt @@ -10,6 +10,7 @@ set(SELF_SRCS define_xs.cpp progress_xs.cpp paren_xs.cpp + sequence_xs.cpp exprseq_xs.cpp expect_expr_xs.cpp expect_symbol_xs.cpp diff --git a/src/reader/expect_expr_xs.cpp b/src/reader/expect_expr_xs.cpp index 9896421e..c07c5d42 100644 --- a/src/reader/expect_expr_xs.cpp +++ b/src/reader/expect_expr_xs.cpp @@ -7,7 +7,9 @@ #include "parserstatemachine.hpp" #include "exprstatestack.hpp" #include "lambda_xs.hpp" +#include "define_xs.hpp" #include "paren_xs.hpp" +#include "sequence_xs.hpp" #include "progress_xs.hpp" #include "xo/expression/Lambda.hpp" #include "xo/expression/Constant.hpp" @@ -18,20 +20,46 @@ namespace xo { namespace scm { std::unique_ptr - expect_expr_xs::make() { - return std::make_unique(expect_expr_xs()); + expect_expr_xs::make(bool allow_defs, + bool cxl_on_rightbrace) + { + return std::make_unique(expect_expr_xs(allow_defs, + cxl_on_rightbrace)); } void - expect_expr_xs::start(parserstatemachine * p_psm) { - p_psm->push_exprstate(expect_expr_xs::make()); + expect_expr_xs::start(bool allow_defs, + bool cxl_on_rightbrace, + parserstatemachine * p_psm) { + p_psm->push_exprstate(expect_expr_xs::make(allow_defs, + cxl_on_rightbrace)); } - expect_expr_xs::expect_expr_xs() - : exprstate(exprstatetype::expect_rhs_expression) + void + expect_expr_xs::start(parserstatemachine * p_psm) { + start(false /*!allow_defs*/, + false /*!cxl_on_rightbrace*/, + p_psm); + } + + expect_expr_xs::expect_expr_xs(bool allow_defs, + bool cxl_on_rightbrace) + : exprstate(exprstatetype::expect_rhs_expression), + allow_defs_{allow_defs}, + cxl_on_rightbrace_{cxl_on_rightbrace} {} + void + expect_expr_xs::on_def_token(const token_type & tk, + parserstatemachine * p_psm) + { + if (allow_defs_) + define_xs::start(p_psm); + else + exprstate::on_def_token(tk, p_psm); + } + void expect_expr_xs::on_lambda_token(const token_type & /*tk*/, parserstatemachine * p_psm) @@ -41,7 +69,6 @@ namespace xo { //constexpr const char * self_name = "exprstate::on_leftparen"; - /* push lparen_0 to remember to look for subsequent rightparen. */ lambda_xs::start(p_psm); } @@ -58,6 +85,34 @@ namespace xo { paren_xs::start(p_psm); } + void + expect_expr_xs::on_leftbrace_token(const token_type & /*tk*/, + parserstatemachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + //constexpr const char * self_name = "exprstate::on_leftparen"; + + /* push lparen_0 to remember to look for subsequent rightparen. */ + sequence_xs::start(p_psm); + } + + void + expect_expr_xs::on_rightbrace_token(const token_type & tk, + parserstatemachine * p_psm) + { + if (cxl_on_rightbrace_) { + auto self = p_psm->pop_exprstate(); + + /* do not call .on_expr(), since '}' cancelled */ + + p_psm->top_exprstate().on_rightbrace_token(tk, p_psm); + } else { + exprstate::on_rightbrace_token(tk, p_psm); + } + } + void expect_expr_xs::on_symbol_token(const token_type & tk, parserstatemachine * p_psm) diff --git a/src/reader/exprstate.cpp b/src/reader/exprstate.cpp index 9721ede2..dfb490ea 100644 --- a/src/reader/exprstate.cpp +++ b/src/reader/exprstate.cpp @@ -33,6 +33,8 @@ namespace xo { return "lambdaexpr"; case exprstatetype::parenexpr: return "parenexpr"; + case exprstatetype::sequenceexpr: + return "sequenceexpr"; case exprstatetype::expect_rhs_expression: return "expect_rhs_expression"; case exprstatetype::expect_symbol: @@ -211,6 +213,30 @@ namespace xo { this->illegal_input_error(self_name, tk); } + void + exprstate::on_leftbrace_token(const token_type & tk, + parserstatemachine * /*p_psm*/) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + constexpr const char * self_name = "exprstate::on_leftbrace_token"; + + this->illegal_input_error(self_name, tk); + } + + void + exprstate::on_rightbrace_token(const token_type & tk, + parserstatemachine * /*p_psm*/) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + constexpr const char * self_name = "exprstate::on_rightbrace_token"; + + this->illegal_input_error(self_name, tk); + } + void exprstate::on_operator_token(const token_type & tk, parserstatemachine * /*p_psm*/) diff --git a/src/reader/sequence_xs.cpp b/src/reader/sequence_xs.cpp new file mode 100644 index 00000000..68694e53 --- /dev/null +++ b/src/reader/sequence_xs.cpp @@ -0,0 +1,78 @@ +/* @file sequence_xs.cpp */ + +#include "sequence_xs.hpp" +#include "parserstatemachine.hpp" +#include "expect_expr_xs.hpp" +#include "xo/expression/Sequence.hpp" + +namespace xo { + using xo::ast::Sequence; + + namespace scm { + std::unique_ptr + sequence_xs::make() { + return std::make_unique(sequence_xs()); + } + + void + sequence_xs::start(parserstatemachine * p_psm) { + p_psm->push_exprstate(sequence_xs::make()); + /* want to accept anything that starts an expression, + * except that } ends it + */ + expect_expr_xs::start(true /*allow_defs*/, + true /*cxl_on_rightbrace*/, + p_psm); + } + + sequence_xs::sequence_xs() + : exprstate(exprstatetype::sequenceexpr) + {} + + void + sequence_xs::on_expr(ref::brw expr, + parserstatemachine * p_psm) + { + /* TODO: if expr is a DefineExpr, + * then need to rewrite... + * + * ...prefix + * DefineExpr(lhs_name, rhs) + * rest... + * + * becomes: + * + * Sequence( + * ...prefix, + * Apply(Lambda(gen999, [Variable(lhs_name, type(rhs))], sequencify(rest...)), + * rhs)) + * + * so amongst other things, + * helpful to have nested seequence_xs that propagates '}' instead of swallowing it. + */ + + this->expr_v_.push_back(expr.promote()); + expect_expr_xs::start(true /*allow_defs*/, + true /*cxl_on_rightbrace*/, + p_psm); + } + + void + sequence_xs::on_rightbrace_token(const token_type & /*tk*/, + parserstatemachine * p_psm) + { + auto self = p_psm->pop_exprstate(); + + /* make sequence from expressions seen at this level, + * and report it to parent + */ + auto expr = Sequence::make(this->expr_v_); + + p_psm->top_exprstate().on_expr(expr, p_psm); + } + + } /*namespace scm*/ +} /*namespace xo*/ + + +/* end sequence_xs.cpp */