diff --git a/xo-reader/include/xo/reader/define_xs.hpp b/xo-reader/include/xo/reader/define_xs.hpp index 880dd309..4f2eb66a 100644 --- a/xo-reader/include/xo/reader/define_xs.hpp +++ b/xo-reader/include/xo/reader/define_xs.hpp @@ -97,6 +97,8 @@ namespace xo { parserstatemachine * p_psm) override; virtual void on_rightparen_token(const token_type & tk, parserstatemachine * p_psm) override; + virtual void on_i64_token(const token_type & tk, + parserstatemachine * p_psm) override; virtual void on_f64_token(const token_type & tk, parserstatemachine * p_psm) override; diff --git a/xo-reader/include/xo/reader/expect_expr_xs.hpp b/xo-reader/include/xo/reader/expect_expr_xs.hpp index 646a803a..900ee1de 100644 --- a/xo-reader/include/xo/reader/expect_expr_xs.hpp +++ b/xo-reader/include/xo/reader/expect_expr_xs.hpp @@ -41,6 +41,9 @@ namespace xo { virtual void on_symbol_token(const token_type & tk, parserstatemachine * p_psm) override; + virtual void on_i64_token(const token_type & tk, + parserstatemachine * p_psm) override; + virtual void on_f64_token(const token_type & tk, parserstatemachine * p_psm) override; diff --git a/xo-reader/include/xo/reader/exprseq_xs.hpp b/xo-reader/include/xo/reader/exprseq_xs.hpp index 05d0a6e3..52ec315c 100644 --- a/xo-reader/include/xo/reader/exprseq_xs.hpp +++ b/xo-reader/include/xo/reader/exprseq_xs.hpp @@ -10,15 +10,37 @@ namespace xo { namespace scm { + enum class exprseqtype { + /** toplevel interactive sequence. Most permissive **/ + toplevel_interactive, + /** toplevel non-interactive sequence. + * This used for top-level expressions in a translation unit. + **/ + toplevel_batch, + /** nested sequence, for example in function body **/ + nested, + }; + /** @class exprseq_xs * @brief parsing state-machine for top-level expression sequence * + * expression sequences come in several types: + * 1. top-level interactive + * 2. top-level batch + * 3. nested + * + * 1 2 3 + * +-------- + * def | y y y + * symbol | y n n 1: evaluate as variable + * i64 | y n n 1: evaluate as constant + * **/ class exprseq_xs : public exprstate { public: - exprseq_xs(); + explicit exprseq_xs(exprseqtype seqtype); - static void start(parserstatemachine * p_psm); + static void start(exprseqtype seqtype, parserstatemachine * p_psm); public: // ----- token input methods ----- @@ -27,6 +49,8 @@ namespace xo { parserstatemachine * p_psm) override; virtual void on_symbol_token(const token_type & tk, parserstatemachine * p_psm) override; + virtual void on_i64_token(const token_type & tk, + parserstatemachine * p_psm) override; // ----- victory methods ----- @@ -34,9 +58,14 @@ namespace xo { parserstatemachine * p_psm) override; virtual void on_expr(ref::brw expr, parserstatemachine * p_psm) override; + virtual void on_expr_with_semicolon(ref::brw expr, + parserstatemachine * p_psm) override; private: - static std::unique_ptr make(); + static std::unique_ptr make(exprseqtype seqtype); + + /** context for this expression sequence **/ + exprseqtype xseqtype_; }; } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-reader/include/xo/reader/exprstate.hpp b/xo-reader/include/xo/reader/exprstate.hpp index a6acad1f..467348df 100644 --- a/xo-reader/include/xo/reader/exprstate.hpp +++ b/xo-reader/include/xo/reader/exprstate.hpp @@ -12,6 +12,8 @@ namespace xo { namespace scm { + /** Identify current state in an expression state machine + **/ enum class exprstatetype { invalid = -1, @@ -172,6 +174,10 @@ namespace xo { virtual void on_operator_token(const token_type & tk, parserstatemachine * p_psm); + /** handle incoming integer-literal token **/ + virtual void on_i64_token(const token_type & tk, + parserstatemachine * p_psm); + /** handle incoming floating-point-literal token **/ virtual void on_f64_token(const token_type & tk, parserstatemachine * p_psm); diff --git a/xo-reader/include/xo/reader/paren_xs.hpp b/xo-reader/include/xo/reader/paren_xs.hpp index 514074d1..0d251a76 100644 --- a/xo-reader/include/xo/reader/paren_xs.hpp +++ b/xo-reader/include/xo/reader/paren_xs.hpp @@ -64,6 +64,8 @@ namespace xo { parserstatemachine * p_psm) override; virtual void on_rightparen_token(const token_type & tk, parserstatemachine * p_psm) override; + virtual void on_i64_token(const token_type & tk, + parserstatemachine * p_psm) override; virtual void on_f64_token(const token_type & tk, parserstatemachine * p_psm) override; diff --git a/xo-reader/include/xo/reader/parser.hpp b/xo-reader/include/xo/reader/parser.hpp index 30dd94ea..01a3b9b9 100644 --- a/xo-reader/include/xo/reader/parser.hpp +++ b/xo-reader/include/xo/reader/parser.hpp @@ -59,10 +59,16 @@ namespace xo { * } * * Grammar: - * toplevel-program = $expression(1); ..; $expression(n) + * toplevel-program = $toplevel-expression(1); ..; $toplevel-expression(n) + * + * if interactive: + * toplevel-expression = expression + * else + * toplevel-expression = type-decl | define-expr * * type-decl = decltype $typename [<$tp1 .. $tpn>] - * expression = define-expr + * expression = type-decl + * | define-expr * | literal-expr * | variable-expr * | apply-expr @@ -185,6 +191,10 @@ namespace xo { **/ bool has_incomplete_expr() const; + /** put parser into state for beginning an interactive session. + **/ + void begin_interactive_session(); + /** put parser into state for beginning of a translation unit * (i.e. input stream) **/ diff --git a/xo-reader/include/xo/reader/progress_xs.hpp b/xo-reader/include/xo/reader/progress_xs.hpp index 6e9db243..03bd933e 100644 --- a/xo-reader/include/xo/reader/progress_xs.hpp +++ b/xo-reader/include/xo/reader/progress_xs.hpp @@ -89,6 +89,9 @@ namespace xo { virtual void on_operator_token(const token_type & tk, parserstatemachine * p_psm) override; + virtual void on_i64_token(const token_type & tk, + parserstatemachine * p_psm) override; + virtual void on_f64_token(const token_type & tk, parserstatemachine * p_psm) override; diff --git a/xo-reader/include/xo/reader/reader.hpp b/xo-reader/include/xo/reader/reader.hpp index 28e0b3a6..59e600c1 100644 --- a/xo-reader/include/xo/reader/reader.hpp +++ b/xo-reader/include/xo/reader/reader.hpp @@ -67,6 +67,15 @@ namespace xo { public: reader() = default; + /** call once before calling .read_expr() + * for a new interactive session + **/ + void begin_interactive_session(); + + /** counterpart to .begin_interactive_session() + **/ + reader_result end_interactive_session(); + /** call once before calling .read_expr(): * 1. with new reader * 2. if last read_expr() call had eof=true diff --git a/xo-reader/src/reader/define_xs.cpp b/xo-reader/src/reader/define_xs.cpp index 19f6d83d..fdd3c410 100644 --- a/xo-reader/src/reader/define_xs.cpp +++ b/xo-reader/src/reader/define_xs.cpp @@ -245,6 +245,18 @@ namespace xo { this->illegal_input_error(self_name, tk); } + void + define_xs::on_i64_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 = "define_xs::on_i64"; + + this->illegal_input_error(self_name, tk); + } + void define_xs::on_f64_token(const token_type & tk, parserstatemachine * /*p_psm*/) diff --git a/xo-reader/src/reader/expect_expr_xs.cpp b/xo-reader/src/reader/expect_expr_xs.cpp index 1f07d131..c4a56f30 100644 --- a/xo-reader/src/reader/expect_expr_xs.cpp +++ b/xo-reader/src/reader/expect_expr_xs.cpp @@ -172,6 +172,17 @@ namespace xo { return; } + void + expect_expr_xs::on_i64_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + progress_xs::start + (Constant::make(tk.i64_value()), + p_psm); + } void expect_expr_xs::on_f64_token(const token_type & tk, diff --git a/xo-reader/src/reader/exprseq_xs.cpp b/xo-reader/src/reader/exprseq_xs.cpp index 421b037c..e650e238 100644 --- a/xo-reader/src/reader/exprseq_xs.cpp +++ b/xo-reader/src/reader/exprseq_xs.cpp @@ -3,25 +3,28 @@ #include "exprseq_xs.hpp" #include "parserstatemachine.hpp" #include "exprstatestack.hpp" +#include "exprseq_xs.hpp" +#include "expect_expr_xs.hpp" #include "define_xs.hpp" #include "expect_symbol_xs.hpp" namespace xo { namespace scm { std::unique_ptr - exprseq_xs::make() + exprseq_xs::make(exprseqtype seqtype) { - return std::make_unique(exprseq_xs()); + return std::make_unique(exprseq_xs(seqtype)); } void - exprseq_xs::start(parserstatemachine * p_psm) + exprseq_xs::start(exprseqtype seqtype, parserstatemachine * p_psm) { - p_psm->push_exprstate(exprseq_xs::make()); + p_psm->push_exprstate(exprseq_xs::make(seqtype)); } - exprseq_xs::exprseq_xs() - : exprstate(exprstatetype::expect_toplevel_expression_sequence) + exprseq_xs::exprseq_xs(exprseqtype x) + : exprstate(exprstatetype::expect_toplevel_expression_sequence), + xseqtype_{x} { } @@ -51,6 +54,24 @@ namespace xo { this->illegal_input_error(c_self_name, tk); } + void + exprseq_xs::on_i64_token(const token_type & tk, + parserstatemachine * p_psm) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + constexpr const char * c_self_name = "exprseq_xs::on_i64_token"; + + if (xseqtype_ == exprseqtype::toplevel_interactive) + { + expect_expr_xs::start(p_psm); + p_psm->top_exprstate().on_i64_token(tk, p_psm); + } else { + this->illegal_input_error(c_self_name, tk); + } + } + void exprseq_xs::on_typedescr(TypeDescr /*td*/, parserstatemachine * /*p_psm*/) @@ -73,6 +94,21 @@ namespace xo { *p_emit_expr = expr.promote(); } /*on_expr*/ + void + exprseq_xs::on_expr_with_semicolon(ref::brw expr, + parserstatemachine * p_psm) + { + /* toplevel expression sequence accepts an + * arbitrary number of expressions. + * + * semicolons are sometimes mandatory to avoid ambiguity. + */ + + auto p_emit_expr = p_psm->p_emit_expr_; + + *p_emit_expr = expr.promote(); + } + } /*namespace scm*/ } /*namespace xo*/ diff --git a/xo-reader/src/reader/exprstate.cpp b/xo-reader/src/reader/exprstate.cpp index 77480dcb..8145c550 100644 --- a/xo-reader/src/reader/exprstate.cpp +++ b/xo-reader/src/reader/exprstate.cpp @@ -251,6 +251,18 @@ namespace xo { this->illegal_input_error(self_name, tk); } + void + exprstate::on_i64_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_i64"; + + this->illegal_input_error(self_name, tk); + } + void exprstate::on_f64_token(const token_type & tk, parserstatemachine * /*p_psm*/) @@ -284,7 +296,7 @@ namespace xo { return; case tokentype::tk_i64: - assert(false); + this->on_i64_token(tk, p_psm); return; case tokentype::tk_f64: diff --git a/xo-reader/src/reader/paren_xs.cpp b/xo-reader/src/reader/paren_xs.cpp index 2c4ca484..357d377a 100644 --- a/xo-reader/src/reader/paren_xs.cpp +++ b/xo-reader/src/reader/paren_xs.cpp @@ -170,6 +170,18 @@ namespace xo { } } + void + paren_xs::on_i64_token(const token_type & tk, + parserstatemachine * /*p_psm*/) + { + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + constexpr const char * c_self_name = "paren_xs::on_i64"; + + this->illegal_input_error(c_self_name, tk); + } + void paren_xs::on_f64_token(const token_type & tk, parserstatemachine * /*p_psm*/) diff --git a/xo-reader/src/reader/parser.cpp b/xo-reader/src/reader/parser.cpp index e71deb40..4250e028 100644 --- a/xo-reader/src/reader/parser.cpp +++ b/xo-reader/src/reader/parser.cpp @@ -29,6 +29,16 @@ namespace xo { return !xs_stack_.empty(); } + void + parser::begin_interactive_session() { + /* note: not using emit expr here */ + parserstatemachine psm(&xs_stack_, + &env_stack_, + nullptr /*p_emit_expr*/); + + exprseq_xs::start(exprseqtype::toplevel_interactive, &psm); + } + void parser::begin_translation_unit() { /* note: not using emit expr here */ @@ -36,7 +46,7 @@ namespace xo { &env_stack_, nullptr /*p_emit_expr*/); - exprseq_xs::start(&psm); + exprseq_xs::start(exprseqtype::toplevel_batch, &psm); } rp diff --git a/xo-reader/src/reader/progress_xs.cpp b/xo-reader/src/reader/progress_xs.cpp index 40d857b6..44938fca 100644 --- a/xo-reader/src/reader/progress_xs.cpp +++ b/xo-reader/src/reader/progress_xs.cpp @@ -401,6 +401,22 @@ namespace xo { } } + void + progress_xs::on_i64_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 = "progress_xs::on_i64"; + + if (this->op_type_ == optype::invalid) { + this->illegal_input_error(self_name, tk); + } else { + exprstate::on_i64_token(tk, p_psm); + } + } + void progress_xs::on_f64_token(const token_type & tk, parserstatemachine * p_psm) diff --git a/xo-reader/src/reader/reader.cpp b/xo-reader/src/reader/reader.cpp index eb012541..bc9de1ce 100644 --- a/xo-reader/src/reader/reader.cpp +++ b/xo-reader/src/reader/reader.cpp @@ -4,6 +4,16 @@ namespace xo { namespace scm { + void + reader::begin_interactive_session() { + parser_.begin_interactive_session(); + } + + reader_result + reader::end_interactive_session() { + return this->read_expr(span_type(nullptr, nullptr), true /*eof*/); + } + void reader::begin_translation_unit() { parser_.begin_translation_unit();