From 4d61a00ebc5b956da72525de0e180de28a1e8ac6 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Thu, 13 May 2021 10:38:31 +0800 Subject: fix issue #52, add until statement. --- src/yuescript/yue_ast.h | 19 ++++----- src/yuescript/yue_compiler.cpp | 88 ++++++++++++++++++++++-------------------- src/yuescript/yue_parser.cpp | 9 +++-- src/yuescript/yue_parser.h | 3 +- 4 files changed, 63 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 1e95d11..695fbe1 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h @@ -256,22 +256,23 @@ AST_NODE(IfCond) AST_MEMBER(IfCond, &condition, &assign) AST_END(IfCond) +AST_LEAF(IfType) +AST_END(IfType) + AST_NODE(If) - ast_ptr sep; + ast_ptr type; ast_sel_list nodes; - AST_MEMBER(If, &sep, &nodes) + AST_MEMBER(If, &type, &nodes) AST_END(If) -AST_NODE(Unless) - ast_ptr sep; - ast_sel_list nodes; - AST_MEMBER(Unless, &sep, &nodes) -AST_END(Unless) +AST_LEAF(WhileType) +AST_END(WhileType) AST_NODE(While) + ast_ptr type; ast_ptr condition; ast_sel body; - AST_MEMBER(While, &condition, &body) + AST_MEMBER(While, &type, &condition, &body) AST_END(While) class Body_t; @@ -451,7 +452,7 @@ class FunLit_t; AST_NODE(SimpleValue) ast_selm_begin.m_line + _config.lineOffset) + _newLine; @@ -874,8 +890,10 @@ private: auto appendix = statement->appendix.get(); switch (appendix->item->getId()) { case id(): { - auto if_line = appendix->item.to(); + auto if_line = static_cast(appendix->item.get()); auto ifNode = x->new_ptr(); + auto ifType = toAst("if"sv, x); + ifNode->type.set(ifType); auto ifCond = x->new_ptr(); ifCond->condition.set(if_line->condition); @@ -900,20 +918,22 @@ private: break; } case id(): { - auto unless_line = appendix->item.to(); - auto unless = x->new_ptr(); + auto unless_line = static_cast(appendix->item.get()); + auto ifNode = x->new_ptr(); + auto ifType = toAst("unless"sv, x); + ifNode->type.set(ifType); auto ifCond = x->new_ptr(); ifCond->condition.set(unless_line->condition); - unless->nodes.push_back(ifCond); + ifNode->nodes.push_back(ifCond); auto stmt = x->new_ptr(); stmt->content.set(statement->content); - unless->nodes.push_back(stmt); + ifNode->nodes.push_back(stmt); statement->appendix.set(nullptr); auto simpleValue = x->new_ptr(); - simpleValue->value.set(unless); + simpleValue->value.set(ifNode); auto value = x->new_ptr(); value->item.set(simpleValue); auto exp = newExp(value, x); @@ -985,7 +1005,6 @@ private: switch (value->getId()) { case id(): transformIf(static_cast(value), out, ExpUsage::Common); break; case id(): transformClassDecl(static_cast(value), out, ExpUsage::Common); break; - case id(): transformUnless(static_cast(value), out, ExpUsage::Common); break; case id(): transformSwitch(static_cast(value), out, ExpUsage::Common); break; case id(): transformWith(static_cast(value), out); break; case id(): transformForEach(static_cast(value), out); break; @@ -1208,16 +1227,12 @@ private: } } switch (value->getId()) { - case id(): - case id(): { + case id(): { auto expList = assignment->expList.get(); str_list temp; auto defs = transformAssignDefs(expList, DefOp::Mark); if (!defs.empty()) temp.push_back(getPredefine(defs) + nll(expList)); - switch (value->getId()) { - case id(): transformIf(static_cast(value), temp, ExpUsage::Assignment, expList); break; - case id(): transformUnless(static_cast(value), temp, ExpUsage::Assignment, expList); break; - } + transformIf(static_cast(value), temp, ExpUsage::Assignment, expList); out.push_back(join(temp)); return; } @@ -1806,6 +1821,7 @@ private: if (*it != nodes.front() && cond->assign) { auto x = *it; auto newIf = x->new_ptr(); + newIf->type.set(toAst("if"sv, x)); for (auto j = ns.rbegin(); j != ns.rend(); ++j) { newIf->nodes.push_back(*j); } @@ -1828,6 +1844,7 @@ private: if (nodes.size() != ns.size()) { auto x = ns.back(); auto newIf = x->new_ptr(); + newIf->type.set(toAst("if"sv, x)); for (auto j = ns.rbegin(); j != ns.rend(); ++j) { newIf->nodes.push_back(*j); } @@ -1918,23 +1935,13 @@ private: if (pair.first) { str_list tmp; auto condition = pair.first->condition.get(); - if (unless) { - if (auto value = singleValueFrom(condition)) { - transformValue(value, tmp); - } else { - transformExp(condition, tmp, ExpUsage::Closure); - tmp.back() = s("("sv) + tmp.back() + s(")"sv); - } - tmp.back().insert(0, s("not "sv)); - unless = false; - } else { - transformExp(condition, tmp, ExpUsage::Closure); - } + auto condStr = transformCondExp(condition, unless); + if (unless) unless = false; _buf << indent(); if (pair != ifCondPairs.front()) { _buf << "else"sv; } - _buf << "if "sv << tmp.back() << " then"sv << nll(condition); + _buf << "if "sv << condStr << " then"sv << nll(condition); temp.push_back(clearBuf()); } if (pair.second) { @@ -1966,11 +1973,8 @@ private: } void transformIf(If_t* ifNode, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { - transformCond(ifNode->nodes.objects(), out, usage, false, assignList); - } - - void transformUnless(Unless_t* unless, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { - transformCond(unless->nodes.objects(), out, usage, true, assignList); + bool unless = _parser.toString(ifNode->type) == "unless"sv; + transformCond(ifNode->nodes.objects(), out, usage, unless, assignList); } void transformExpList(ExpList_t* expList, str_list& out) { @@ -2146,7 +2150,6 @@ private: switch (value->getId()) { case id(): transform_const_value(static_cast(value), out); break; case id(): transformIf(static_cast(value), out, ExpUsage::Closure); break; - case id(): transformUnless(static_cast(value), out, ExpUsage::Closure); break; case id(): transformSwitch(static_cast(value), out, ExpUsage::Closure); break; case id(): transformWithClosure(static_cast(value), out); break; case id(): transformClassDeclClosure(static_cast(value), out); break; @@ -2757,9 +2760,6 @@ private: case id(): transformIf(static_cast(value), out, ExpUsage::Return); return; - case id(): - transformUnless(static_cast(value), out, ExpUsage::Return); - return; } } else if (auto chainValue = singleValue->item.as()) { if (specialChainValue(chainValue) != ChainType::Common) { @@ -5054,6 +5054,7 @@ private: _withVars.push(withVar); if (with->eop) { auto ifNode = x->new_ptr(); + ifNode->type.set(toAst("if"sv, x)); ifNode->nodes.push_back(toAst(withVar + s("~=nil"sv), x)); ifNode->nodes.push_back(with->body); transformIf(ifNode, temp, ExpUsage::Common); @@ -5733,8 +5734,9 @@ private: addToScope(lenVar); temp.push_back(indent() + s("local "sv) + accumVar + s(" = { }"sv) + nll(whileNode)); temp.push_back(indent() + s("local "sv) + lenVar + s(" = 1"sv) + nll(whileNode)); - transformExp(whileNode->condition, temp, ExpUsage::Closure); - temp.back() = indent() + s("while "sv) + temp.back() + s(" do"sv) + nll(whileNode); + bool isUntil = _parser.toString(whileNode->type) == "until"sv; + auto condStr = transformCondExp(whileNode->condition, isUntil); + temp.push_back(indent() + s("while "sv) + condStr + s(" do"sv) + nll(whileNode)); pushScope(); auto assignLeft = toAst(accumVar + s("["sv) + lenVar + s("]"sv), x); auto lenLine = lenVar + s(" = "sv) + lenVar + s(" + 1"sv) + nlr(whileNode); @@ -5770,8 +5772,9 @@ private: addToScope(lenVar); temp.push_back(indent() + s("local "sv) + accumVar + s(" = { }"sv) + nll(whileNode)); temp.push_back(indent() + s("local "sv) + lenVar + s(" = 1"sv) + nll(whileNode)); - transformExp(whileNode->condition, temp, ExpUsage::Closure); - temp.back() = indent() + s("while "sv) + temp.back() + s(" do"sv) + nll(whileNode); + bool isUntil = _parser.toString(whileNode->type) == "until"sv; + auto condStr = transformCondExp(whileNode->condition, isUntil); + temp.push_back(indent() + s("while "sv) + condStr + s(" do"sv) + nll(whileNode)); pushScope(); auto assignLeft = toAst(accumVar + s("["sv) + lenVar + s("]"sv), x); auto lenLine = lenVar + s(" = "sv) + lenVar + s(" + 1"sv) + nlr(whileNode); @@ -5788,10 +5791,11 @@ private: void transformWhile(While_t* whileNode, str_list& out) { str_list temp; pushScope(); - transformExp(whileNode->condition, temp, ExpUsage::Closure); + bool isUntil = _parser.toString(whileNode->type) == "until"sv; + auto condStr = transformCondExp(whileNode->condition, isUntil); transformLoopBody(whileNode->body, temp, Empty, ExpUsage::Common); popScope(); - _buf << indent() << "while "sv << temp.front() << " do"sv << nll(whileNode); + _buf << indent() << "while "sv << condStr << " do"sv << nll(whileNode); _buf << temp.back(); _buf << indent() << "end"sv << nlr(whileNode); out.push_back(clearBuf()); diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 607edc9..255469d 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -244,10 +244,11 @@ YueParser::YueParser() { IfCond = disable_chain(Exp >> -Assign); IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> key("elseif") >> IfCond >> plain_body_with("then"); IfElse = -(Break >> *EmptyLine >> CheckIndent) >> key("else") >> plain_body; - If = key("if") >> Seperator >> IfCond >> plain_body_with("then") >> *IfElseIf >> -IfElse; - Unless = key("unless") >> Seperator >> IfCond >> plain_body_with("then") >> *IfElseIf >> -IfElse; + IfType = (expr("if") | expr("unless")) >> not_(AlphaNum); + If = Space >> IfType >> IfCond >> plain_body_with("then") >> *IfElseIf >> -IfElse; - While = key("while") >> disable_do_chain(Exp) >> plain_body_with("do"); + WhileType = (expr("while") | expr("until")) >> not_(AlphaNum); + While = Space >> WhileType >> disable_do_chain(Exp) >> plain_body_with("do"); Repeat = key("repeat") >> Body >> Break >> *EmptyLine >> CheckIndent >> key("until") >> Exp; for_step_value = sym(',') >> Exp; @@ -607,7 +608,7 @@ YueParser::YueParser() { SimpleValue = (Space >> const_value) | - If | Unless | Switch | With | ClassDecl | ForEach | For | While | Do | + If | Switch | With | ClassDecl | ForEach | For | While | Do | (Space >> unary_value) | TblComprehension | TableLit | Comprehension | FunLit | (Space >> Num); diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index b3c311a..2a3c1e4 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h @@ -228,8 +228,9 @@ private: AST_RULE(SwitchCase) AST_RULE(Switch) AST_RULE(IfCond) + AST_RULE(IfType) AST_RULE(If) - AST_RULE(Unless) + AST_RULE(WhileType) AST_RULE(While) AST_RULE(Repeat) AST_RULE(for_step_value) -- cgit v1.2.3-55-g6feb