diff --git a/include/xo/reader2/DProgressSsm.hpp b/include/xo/reader2/DProgressSsm.hpp index 1a0e7186..c43caacd 100644 --- a/include/xo/reader2/DProgressSsm.hpp +++ b/include/xo/reader2/DProgressSsm.hpp @@ -142,6 +142,8 @@ namespace xo { void on_symbol_token(const Token & tk, ParserStateMachine * p_psm); + void on_comma_token(const Token & tk, + ParserStateMachine * p_psm); void on_colon_token(const Token & tk, ParserStateMachine * p_psm); void on_singleassign_token(const Token & tk, diff --git a/src/reader2/DApplySsm.cpp b/src/reader2/DApplySsm.cpp index ad2f7fd6..4cd3aaec 100644 --- a/src/reader2/DApplySsm.cpp +++ b/src/reader2/DApplySsm.cpp @@ -253,8 +253,8 @@ namespace xo { // 1. want to remain in state apply_2 // 2. expr from nested ssm already incorporated // into .args_expr_v_ - // -> so updated state already achieved. + DExpectExprSsm::start(p_psm); return; } } diff --git a/src/reader2/DProgressSsm.cpp b/src/reader2/DProgressSsm.cpp index d3b8c3c3..20bfb998 100644 --- a/src/reader2/DProgressSsm.cpp +++ b/src/reader2/DProgressSsm.cpp @@ -224,6 +224,7 @@ namespace xo { switch (tk.tk_type()) { case tokentype::tk_then: case tokentype::tk_else: + case tokentype::tk_comma: this->on_completing_token(tk, p_psm); return; @@ -283,7 +284,6 @@ namespace xo { 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: @@ -911,7 +911,7 @@ namespace xo { // input: /// <--- F1 ---> // (..........)(.. ).. - // <------ A1 -----> + // <------ A1 -----> // <------- X1 ------> // // F1: expression evaluating to a function, @@ -933,7 +933,7 @@ namespace xo { // 1. keep ProgressSsm on the stack in case input continues like: // fn_expr(args..) + .. // i.e. to allow for infix operator following apply - // + // obj fn_expr(this->lhs_); diff --git a/utest/SchematikaParser.test.cpp b/utest/SchematikaParser.test.cpp index 54896a3f..0ecaff37 100644 --- a/utest/SchematikaParser.test.cpp +++ b/utest/SchematikaParser.test.cpp @@ -1242,6 +1242,90 @@ namespace xo { REQUIRE(result.result_expr()); } } + + TEST_CASE("SchematikaParser-interactive-apply2", "[reader2][SchematikaParser]") + { + // top-level apply, with multiple arguments + + constexpr bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag)); + + ArenaConfig config; + config.name_ = "test-arena"; + config.size_ = 16 * 1024; + + DArena expr_arena = DArena::map(config); + obj expr_alloc = with_facet::mkobj(&expr_arena); + + SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + + parser.begin_interactive_session(); + + /** Walkthrough parsing input equivalent to: + * + * (lambda (x : i64, y : i64) { x * y })(13, 15); + * + **/ + + std::vector tk_v{ + Token::leftparen_token(), + + /**/ Token::lambda_token(), + /* */ Token::leftparen_token(), + /* */ Token::symbol_token("x"), + /* */ Token::colon_token(), + /* */ Token::symbol_token("i64"), + /* */ Token::comma_token(), + /* */ Token::symbol_token("y"), + /* */ Token::colon_token(), + /* */ Token::symbol_token("i64"), + /* */ Token::rightparen_token(), + + /**/ Token::leftbrace_token(), + /* */ Token::symbol_token("x"), + /* */ Token::star_token(), + /* */ Token::symbol_token("y"), + /**/ Token::rightbrace_token(), + + Token::rightparen_token(), + + Token::leftparen_token(), + /**/ Token::i64_token("13"), + /**/ Token::comma_token(), + /**/ Token::i64_token("15"), + Token::rightparen_token(), + + Token::semicolon_token(), + }; + + size_t i_tk = 0; + size_t n_tk = tk_v.size(); + for (const auto & tk : tk_v) { + INFO(tostr(xtag("i_tk", i_tk), xtag("tk", tk))); + + auto & result = parser.on_token(tk); + + log && log("after token", xtag("i_tk", i_tk), xtag("tk", tk)); + log && log(xtag("parser", &parser)); + log && log(xtag("result", result)); + + if (i_tk + 1 < n_tk) { + REQUIRE(parser.has_incomplete_expr() == true); + REQUIRE(!result.is_error()); + REQUIRE(result.is_incomplete()); + } else { + /* last token in tk_v[] */ + + REQUIRE(parser.has_incomplete_expr() == false); + REQUIRE(!result.is_error()); + REQUIRE(result.is_expression()); + REQUIRE(result.result_expr()); + } + + ++i_tk; + } + + } } /*namespace ut*/ } /*namespace xo*/