From c68e11bc6d7631185749aaf0c8d89147b3ac9cc9 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Wed, 10 Feb 2021 14:34:08 +0800 Subject: update backcall operator syntax, fix issue #31. --- src/MoonP/moon_ast.h | 8 +++- src/MoonP/moon_compiler.cpp | 104 ++++++++++++++++++++++++++++++++++++++++---- src/MoonP/moon_parser.cpp | 8 ++-- src/MoonP/moon_parser.h | 1 + 4 files changed, 109 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/MoonP/moon_ast.h b/src/MoonP/moon_ast.h index d00d855..2f5123b 100644 --- a/src/MoonP/moon_ast.h +++ b/src/MoonP/moon_ast.h @@ -701,6 +701,12 @@ AST_END(unless_line) AST_LEAF(BreakLoop) AST_END(BreakLoop) +AST_NODE(BackcallBody) + ast_ptr sep; + ast_list values; + AST_MEMBER(BackcallBody, &sep, &values) +AST_END(BackcallBody) + AST_NODE(statement_appendix) ast_sel item; AST_MEMBER(statement_appendix, &item) @@ -712,7 +718,7 @@ AST_END(statement_sep) AST_NODE(Statement) ast_sel content; + Label_t, Goto_t, Backcall_t, LocalAttrib_t, BackcallBody_t, ExpListAssign_t> content; ast_ptr appendix; ast_ptr needSep; AST_MEMBER(Statement, &content, &appendix, &needSep) diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index 73bbd60..11d4ed8 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp @@ -53,7 +53,7 @@ inline std::string s(std::string_view sv) { return std::string(sv); } -const std::string_view version = "0.5.2"sv; +const std::string_view version = "0.6.0"sv; const std::string_view extension = "mp"sv; class MoonCompilerImpl { @@ -429,7 +429,7 @@ private: return result; } - Value_t* singleValueFrom(ast_node* item) const { + unary_exp_t* singleUnaryExpFrom(ast_node* item) const { Exp_t* exp = nullptr; switch (item->getId()) { case id(): @@ -451,8 +451,8 @@ private: } case id(): { auto unary = static_cast(item); - if (unary->ops.empty() && unary->expos.size() == 1) { - return static_cast(unary->expos.back()); + if (unary->expos.size() == 1) { + return unary; } return nullptr; } @@ -463,13 +463,21 @@ private: BREAK_IF(!exp->opValues.empty()); BREAK_IF(exp->backcalls.size() != 1); auto unary = static_cast(exp->backcalls.back()); - BREAK_IF(!unary->ops.empty()); BREAK_IF(unary->expos.size() != 1); - return static_cast(unary->expos.back()); + return unary; BLOCK_END return nullptr; } + Value_t* singleValueFrom(ast_node* item) const { + if (auto unary = singleUnaryExpFrom(item)) { + if (unary->ops.empty()) { + return static_cast(unary->expos.back()); + } + } + return nullptr; + } + ast_ptr newExp(Value_t* value, ast_node* x) { auto unary = x->new_ptr(); unary->expos.push_back(value); @@ -522,6 +530,60 @@ private: return stmts.empty() ? nullptr : static_cast(stmts.back()); } + Exp_t* lastExpFromAssign(ast_node* action) { + switch (action->getId()) { + case id(): { + auto update = static_cast(action); + return update->value; + } + case id(): { + auto assign = static_cast(action); + return ast_cast(assign->values.back()); + } + } + return nullptr; + } + + Exp_t* lastExpFromStatement(Statement_t* stmt) { + if (!stmt->content) return nullptr; + switch (stmt->content->getId()) { + case id(): { + auto expListAssign = static_cast(stmt->content.get()); + if (auto action = expListAssign->action.get()) { + return lastExpFromAssign(action); + } else { + return static_cast(expListAssign->expList->exprs.back()); + } + } + case id(): { + auto exportNode = static_cast(stmt->content.get()); + if (auto action = exportNode->assign.get()) { + return lastExpFromAssign(action); + } else { + switch (exportNode->target->getId()) { + case id(): return exportNode->target.to(); + case id(): return static_cast(exportNode->target.to()->exprs.back()); + } + } + } + case id(): { + if (auto localValues = static_cast(stmt->content.get())->item.as()) { + if (auto expList = localValues->valueList.as()) { + return static_cast(expList->exprs.back()); + } + } + } + case id(): { + if (auto globalValues = static_cast(stmt->content.get())->item.as()) { + if (auto expList = globalValues->valueList.as()) { + return static_cast(expList->exprs.back()); + } + } + } + } + return nullptr; + } + template ast_ptr toAst(std::string_view codes, ast_node* parent) { auto res = _parser.parse(s(codes)); @@ -812,6 +874,7 @@ private: case id(): transformLabel(static_cast(content), out); break; case id(): transformGoto(static_cast(content), out); break; case id(): transformLocalAttrib(static_cast(content), out); break; + case id(): throw std::logic_error(_info.errorMessage("backcall chain must be following a value"sv, x)); break; case id(): { auto expListAssign = static_cast(content); if (expListAssign->action) { @@ -1692,7 +1755,10 @@ private: auto begin = values.begin(); begin++; for (auto it = begin; it != values.end(); ++it) { auto unary = static_cast(*it); - auto value = singleValueFrom(unary); + auto value = static_cast(singleUnaryExpFrom(unary) ? unary->expos.back() : nullptr); + if (values.back() == *it && !unary->ops.empty() && usage == ExpUsage::Common) { + throw std::logic_error(_info.errorMessage("expression list is not supported here"sv, x)); + } if (!value) throw std::logic_error(_info.errorMessage("backcall operator must be followed by chain value"sv, *it)); if (auto chainValue = value->item.as()) { if (isChainValueCall(chainValue)) { @@ -1936,7 +2002,29 @@ private: for (auto it = nodes.begin(); it != nodes.end(); ++it) { auto node = *it; auto stmt = static_cast(node); - if (auto backcall = stmt->content.as()) { + if (auto backcallBody = stmt->content.as()) { + auto x = stmt; + bool cond = false; + BLOCK_START + BREAK_IF(it == nodes.begin()); + auto last = it; --last; + auto lst = static_cast(*last); + auto exp = lastExpFromStatement(lst); + BREAK_IF(!exp); + for (auto val : backcallBody->values.objects()) { + exp->backcalls.push_back(val); + } + cond = true; + BLOCK_END + if (!cond) throw std::logic_error(_info.errorMessage("backcall chain must be following a value"sv, x)); + stmt->content.set(nullptr); + auto next = it; ++next; + BLOCK_START + BREAK_IF(next == nodes.end()); + BREAK_IF(!static_cast(*next)->content.as()); + throw std::logic_error(_info.errorMessage("indent mismatch in backcall chain"sv, *next)); + BLOCK_END + } else if (auto backcall = stmt->content.as()) { auto x = *nodes.begin(); auto newBlock = x->new_ptr(); if (it != nodes.begin()) { diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp index 63ffec7..f15492f 100644 --- a/src/MoonP/moon_parser.cpp +++ b/src/MoonP/moon_parser.cpp @@ -319,7 +319,7 @@ MoonParser::MoonParser() { unary_exp = *(Space >> unary_operator) >> expo_exp; BackcallOperator = expr("|>"); - backcall_value = White >> BackcallOperator >> *SpaceBreak >> unary_exp; + backcall_value = Space >> BackcallOperator >> *SpaceBreak >> unary_exp; backcall_exp = unary_exp >> *backcall_value; BinaryOperator = @@ -522,6 +522,8 @@ MoonParser::MoonParser() { fn_arrow_back = expr('<') >> set("-="); Backcall = -FnArgsDef >> Space >> fn_arrow_back >> Space >> ChainValue; + BackcallBody = Seperator >> Space >> BackcallOperator >> unary_exp >> *(+SpaceBreak >> CheckIndent >> Space >> BackcallOperator >> unary_exp); + ExpList = Seperator >> Exp >> *(sym(',') >> Exp); ExpListLow = Seperator >> Exp >> *(Space >> set(",;") >> Exp); @@ -562,14 +564,14 @@ MoonParser::MoonParser() { Import | While | Repeat | For | ForEach | Return | Local | Global | Export | Macro | Space >> BreakLoop | Label | Goto | Backcall | - LocalAttrib | ExpListAssign + LocalAttrib | BackcallBody | ExpListAssign ) >> Space >> -statement_appendix >> -statement_sep; Body = Space >> Break >> *EmptyLine >> InBlock | Statement; empty_line_stop = Space >> and_(Stop); - Line = CheckIndent >> Statement | empty_line_stop; + Line = CheckIndent >> Statement | and_(Space >> BackcallOperator) >> Advance >> ensure(Statement, PopIndent) | empty_line_stop; Block = Seperator >> Line >> *(+Break >> Line); Shebang = expr("#!") >> *(not_(Stop) >> Any); diff --git a/src/MoonP/moon_parser.h b/src/MoonP/moon_parser.h index f036a7c..bee3c9c 100644 --- a/src/MoonP/moon_parser.h +++ b/src/MoonP/moon_parser.h @@ -209,6 +209,7 @@ private: AST_RULE(Goto) AST_RULE(fn_arrow_back) AST_RULE(Backcall) + AST_RULE(BackcallBody) AST_RULE(ExpListLow) AST_RULE(ExpList) AST_RULE(Return) -- cgit v1.2.3-55-g6feb