From fb47c11bd942c83317f1f9a2e255535649401cbf Mon Sep 17 00:00:00 2001 From: Li Jin Date: Tue, 28 Jan 2020 00:41:53 +0800 Subject: Add multi-line comment support. Add escape new line symbol. Add back call syntax. --- src/MoonP/moon_ast.cpp | 2 + src/MoonP/moon_ast.h | 16 ++++- src/MoonP/moon_compiler.cpp | 138 +++++++++++++++++++++++++++++++++++++++++--- src/MoonP/moon_parser.cpp | 19 ++++-- 4 files changed, 161 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/MoonP/moon_ast.cpp b/src/MoonP/moon_ast.cpp index 8b8a674..f14fa74 100644 --- a/src/MoonP/moon_ast.cpp +++ b/src/MoonP/moon_ast.cpp @@ -34,6 +34,7 @@ AST_IMPL(ImportLiteral) AST_IMPL(ImportFrom) AST_IMPL(ImportAs) AST_IMPL(Import) +AST_IMPL(Backcall) AST_IMPL(ExpListLow) AST_IMPL(ExpList) AST_IMPL(Return) @@ -59,6 +60,7 @@ AST_IMPL(Assign) AST_IMPL(update_op) AST_IMPL(Update) AST_IMPL(BinaryOperator) +AST_IMPL(BackcallOperator) AST_IMPL(Assignable) AST_IMPL(AssignableChain) AST_IMPL(exp_op_value) diff --git a/src/MoonP/moon_ast.h b/src/MoonP/moon_ast.h index e71afe9..6969688 100644 --- a/src/MoonP/moon_ast.h +++ b/src/MoonP/moon_ast.h @@ -135,6 +135,15 @@ AST_NODE(Import, "Import"_id) AST_MEMBER(Import, &content) AST_END(Import) +class FnArgsDef_t; +class ChainValue_t; + +AST_NODE(Backcall, "Backcall"_id) + ast_ptr argsDef; + ast_ptr value; + AST_MEMBER(Backcall, &argsDef, &value) +AST_END(Backcall) + AST_NODE(ExpListLow, "ExpListLow"_id) ast_ptr sep; ast_list exprs; @@ -295,6 +304,9 @@ AST_END(Update) AST_LEAF(BinaryOperator, "BinaryOperator"_id) AST_END(BinaryOperator) +AST_LEAF(BackcallOperator, "BackcallOperator"_id) +AST_END(BackcallOperator) + class AssignableChain_t; AST_NODE(Assignable, "Assignable"_id) @@ -305,7 +317,7 @@ AST_END(Assignable) class Value_t; AST_NODE(exp_op_value, "exp_op_value"_id) - ast_ptr op; + ast_sel op; ast_ptr value; AST_MEMBER(exp_op_value, &op, &value) AST_END(exp_op_value) @@ -586,7 +598,7 @@ AST_END(BreakLoop) AST_NODE(Statement, "Statement"_id) ast_sel content; + Backcall_t, ExpListAssign_t> content; ast_ptr appendix; AST_MEMBER(Statement, &content, &appendix) AST_END(Statement) diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index 4723af4..6173389 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp @@ -739,6 +739,23 @@ private: break; } } + } else if (expList->exprs.size() == 1){ + auto exp = static_cast(expList->exprs.back()); + if (exp->opValues.size() > 0) { + bool backcall = true; + for (auto _opValue : exp->opValues.objects()) { + auto opValue = static_cast(_opValue); + if (!opValue->op.is()) { + backcall = false; + break; + } + } + if (backcall) { + transformExp(exp, out); + out.back().append(nll(exp)); + break; + } + } } throw std::logic_error(debugInfo("Expression list must appear at the end of body block."sv, expList)); } @@ -1593,11 +1610,55 @@ private: } void transformExp(Exp_t* exp, str_list& out) { + auto x = exp; + const auto& opValues = exp->opValues.objects(); + for (auto it = opValues.begin(); it != opValues.end(); ++it) { + auto opValue = static_cast(*it); + if (opValue->op.is()) { + if (auto chainValue = opValue->value->item.as()) { + auto newExp = x->new_ptr(); + { + auto arg = x->new_ptr(); + arg->value.set(exp->value); + for (auto i = opValues.begin(); i != it; ++i) { + arg->opValues.push_back(*i); + } + auto next = it; ++next; + for (auto i = next; i != opValues.end(); ++i) { + newExp->opValues.push_back(*i); + } + if (isChainValueCall(chainValue)) { + auto last = chainValue->items.back(); + if (auto invoke = ast_cast(last)) { + invoke->args.push_front(arg); + } else { + ast_to(last)->args.push_front(arg); + } + } else { + auto invoke = x->new_ptr(); + invoke->args.push_front(arg); + chainValue->items.push_back(invoke); + } + auto value = x->new_ptr(); + value->item.set(chainValue); + newExp->value.set(value); + } + transformExp(newExp, out); + return; + } else { + throw std::logic_error(debugInfo("Backcall operator must be followed by chain value."sv, opValue->value)); + } + } + } str_list temp; transformValue(exp->value, temp); for (auto _opValue : exp->opValues.objects()) { auto opValue = static_cast(_opValue); - transformBinaryOperator(opValue->op, temp); + if (auto op = opValue->op.as()) { + transformBinaryOperator(op, temp); + } else { + temp.push_back(s("|>"sv)); + } transformValue(opValue->value, temp); } out.push_back(join(temp, " "sv)); @@ -1731,8 +1792,68 @@ private: void transformCodes(const node_container& nodes, str_list& out, bool implicitReturn) { LocalMode mode = LocalMode::None; Local_t* any = nullptr, *capital = nullptr; - for (auto node : nodes) { + for (auto it = nodes.begin(); it != nodes.end(); ++it) { + auto node = *it; auto stmt = static_cast(node); + if (auto backcall = stmt->content.as()) { + auto x = *nodes.begin(); + auto newBlock = x->new_ptr(); + if (it != nodes.begin()) { + for (auto i = nodes.begin(); i != it; ++i) { + newBlock->statements.push_back(*i); + } + } + x = backcall; + auto arg = x->new_ptr(); + { + auto block = x->new_ptr(); + auto next = it; ++next; + if (next != nodes.end()) { + for (auto i = next; i != nodes.end(); ++i) { + block->statements.push_back(*i); + } + } + auto body = x->new_ptr(); + body->content.set(block); + auto funLit = x->new_ptr(); + funLit->argsDef.set(backcall->argsDef); + funLit->arrow.set(toAst("->"sv, fn_arrow, x)); + funLit->body.set(body); + auto simpleValue = x->new_ptr(); + simpleValue->value.set(funLit); + auto value = x->new_ptr(); + value->item.set(simpleValue); + arg->value.set(value); + } + if (isChainValueCall(backcall->value)) { + auto last = backcall->value->items.back(); + if (auto invoke = ast_cast(last)) { + invoke->args.push_back(arg); + } else { + ast_to(last)->args.push_back(arg); + } + } else { + auto invoke = x->new_ptr(); + invoke->args.push_back(arg); + backcall->value->items.push_back(invoke); + } + auto newStmt = x->new_ptr(); + { + auto chainValue = backcall->value.get(); + auto value = x->new_ptr(); + value->item.set(chainValue); + auto exp = x->new_ptr(); + exp->value.set(value); + auto expList = x->new_ptr(); + expList->exprs.push_back(exp); + auto expListAssign = x->new_ptr(); + expListAssign->expList.set(expList); + newStmt->content.set(expListAssign); + newBlock->statements.push_back(newStmt); + } + transformBlock(newBlock, out, implicitReturn); + return; + } if (auto local = stmt->content.as()) { if (auto flag = local->name.as()) { LocalMode newMode = toString(flag) == "*"sv ? LocalMode::Any : LocalMode::Capital; @@ -1802,9 +1923,10 @@ private: } } if (implicitReturn) { + BLOCK_START + BREAK_IF(nodes.empty()); auto last = static_cast(nodes.back()); auto x = last; - BLOCK_START auto expList = expListFrom(last); BREAK_IF(!expList || (last->appendix && @@ -1816,11 +1938,13 @@ private: last->content.set(returnNode); BLOCK_END } - str_list temp; - for (auto node : nodes) { - transformStatement(static_cast(node), temp); + if (!nodes.empty()) { + str_list temp; + for (auto node : nodes) { + transformStatement(static_cast(node), temp); + } + out.push_back(join(temp)); } - out.push_back(join(temp)); } void transformBody(Body_t* body, str_list& out, bool implicitReturn = false) { diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp index 6d1b86c..baea9bf 100644 --- a/src/MoonP/moon_parser.cpp +++ b/src/MoonP/moon_parser.cpp @@ -37,8 +37,13 @@ rule Any = Break | any(); rule White = *(set(" \t") | Break); rule Stop = Break | eof(); rule Comment = "--" >> *(not_(set("\r\n")) >> Any) >> and_(Stop); -rule Indent = *set(" \t"); -rule Space = plain_space >> -Comment; +rule multi_line_open = expr("--[["); +rule multi_line_close = expr("]]"); +rule multi_line_content = *(not_(multi_line_close) >> Any); +rule MultiLineComment = multi_line_open >> multi_line_content >> multi_line_close; +rule Indent = plain_space; +rule EscapeNewLine = expr('\\') >> plain_space >> -Comment >> Break; +rule Space = *(set(" \t") | MultiLineComment | EscapeNewLine) >> -Comment; rule SomeSpace = +set(" \t") >> -Comment; rule SpaceBreak = Space >> Break; rule EmptyLine = SpaceBreak; @@ -287,13 +292,15 @@ rule BinaryOperator = expr("//") | set("+-*/%^><|&"); +rule BackcallOperator = expr("|>"); + extern rule AssignableChain; rule Assignable = AssignableChain | Space >> Variable | SelfName; extern rule Value; -rule exp_op_value = Space >> BinaryOperator >> *SpaceBreak >> Value; +rule exp_op_value = Space >> (BackcallOperator | BinaryOperator) >> *SpaceBreak >> Value; rule Exp = Value >> *exp_op_value; extern rule Chain, Callable, InvokeArgs, existential_op; @@ -334,7 +341,7 @@ rule LuaStringClose = pl::user(lua_string_close, [](const item_t& item) return st->stringOpen == count; }); -rule LuaStringContent = *(not_(LuaStringClose) >> (Break | Any)); +rule LuaStringContent = *(not_(LuaStringClose) >> Any); rule LuaString = pl::user(LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose, [](const item_t& item) { @@ -474,6 +481,8 @@ rule NameList = Seperator >> Space >> Variable >> *(sym(',') >> Space >> Variabl rule NameOrDestructure = Space >> Variable | TableLit; rule AssignableNameList = Seperator >> NameOrDestructure >> *(sym(',') >> NameOrDestructure); +rule Backcall = -FnArgsDef >> Space >> symx("<-") >> Space >> ChainValue; + rule ExpList = Seperator >> Exp >> *(sym(',') >> Exp); rule ExpListLow = Seperator >> Exp >> *((sym(',') | sym(';')) >> Exp); @@ -518,7 +527,7 @@ rule Statement = ( Import | While | For | ForEach | Return | Local | Export | Space >> BreakLoop | - ExpListAssign + Backcall | ExpListAssign ) >> Space >> -statement_appendix; -- cgit v1.2.3-55-g6feb