diff options
author | Li Jin <dragon-fly@qq.com> | 2019-10-07 20:05:59 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2019-10-07 20:05:59 +0800 |
commit | 726fee3152c81fdac7e3ad5f663bfbea8f99ddd8 (patch) | |
tree | 203066824db5ad76520ed743c2af4005237d0078 | |
parent | 055fcb596781a8488afeb0030e9ef4295e3d7017 (diff) | |
download | yuescript-726fee3152c81fdac7e3ad5f663bfbea8f99ddd8.tar.gz yuescript-726fee3152c81fdac7e3ad5f663bfbea8f99ddd8.tar.bz2 yuescript-726fee3152c81fdac7e3ad5f663bfbea8f99ddd8.zip |
fixing compile issues.
-rw-r--r-- | MoonParser/moon_ast.cpp | 524 | ||||
-rw-r--r-- | MoonParser/moon_ast.h | 8 | ||||
-rw-r--r-- | MoonParser/moon_parser.cpp | 5 |
3 files changed, 461 insertions, 76 deletions
diff --git a/MoonParser/moon_ast.cpp b/MoonParser/moon_ast.cpp index 52fbd68..50c13db 100644 --- a/MoonParser/moon_ast.cpp +++ b/MoonParser/moon_ast.cpp | |||
@@ -420,18 +420,6 @@ private: | |||
420 | return firstValue; | 420 | return firstValue; |
421 | } | 421 | } |
422 | 422 | ||
423 | void noop(ast_node* node, str_list& out) { | ||
424 | auto str = _converter.to_bytes(std::wstring(node->m_begin.m_it, node->m_end.m_it)); | ||
425 | out.push_back(s("<"sv) + node->getName() + s(">"sv) + trim(str)); | ||
426 | // out.push_back(trim(str)); | ||
427 | } | ||
428 | |||
429 | void noopnl(ast_node* node, str_list& out) { | ||
430 | auto str = _converter.to_bytes(std::wstring(node->m_begin.m_it, node->m_end.m_it)); | ||
431 | out.push_back(s("<"sv) + node->getName() + s(">"sv) + trim(str) + nll(node)); | ||
432 | // out.push_back(trim(str) + nll(node)); | ||
433 | } | ||
434 | |||
435 | Statement_t* lastStatementFrom(Body_t* body) { | 423 | Statement_t* lastStatementFrom(Body_t* body) { |
436 | if (auto stmt = body->content.as<Statement_t>()) { | 424 | if (auto stmt = body->content.as<Statement_t>()) { |
437 | return stmt; | 425 | return stmt; |
@@ -561,7 +549,15 @@ private: | |||
561 | auto stmt = new_ptr<Statement_t>(); | 549 | auto stmt = new_ptr<Statement_t>(); |
562 | stmt->content.set(statement->content); | 550 | stmt->content.set(statement->content); |
563 | comp->value.set(stmt); | 551 | comp->value.set(stmt); |
564 | statement->content.set(comp); | 552 | auto simpleValue = new_ptr<SimpleValue_t>(); |
553 | simpleValue->value.set(comp); | ||
554 | auto value = new_ptr<Value_t>(); | ||
555 | value->item.set(simpleValue); | ||
556 | auto exp = new_ptr<Exp_t>(); | ||
557 | exp->value.set(value); | ||
558 | auto expList = new_ptr<ExpList_t>(); | ||
559 | expList->exprs.push_back(exp); | ||
560 | statement->content.set(expList); | ||
565 | statement->appendix.set(nullptr); | 561 | statement->appendix.set(nullptr); |
566 | break; | 562 | break; |
567 | } | 563 | } |
@@ -576,16 +572,13 @@ private: | |||
576 | switch (content->getId()) { | 572 | switch (content->getId()) { |
577 | case "Import"_id: transformImport(static_cast<Import_t*>(content), out); break; | 573 | case "Import"_id: transformImport(static_cast<Import_t*>(content), out); break; |
578 | case "While"_id: transformWhile(static_cast<While_t*>(content), out); break; | 574 | case "While"_id: transformWhile(static_cast<While_t*>(content), out); break; |
579 | case "With"_id: transformWith(static_cast<With_t*>(content), out); break; | ||
580 | case "For"_id: transformFor(static_cast<For_t*>(content), out); break; | 575 | case "For"_id: transformFor(static_cast<For_t*>(content), out); break; |
581 | case "ForEach"_id: transformForEach(static_cast<ForEach_t*>(content), out); break; | 576 | case "ForEach"_id: transformForEach(static_cast<ForEach_t*>(content), out); break; |
582 | case "Switch"_id: transformSwitch(static_cast<Switch_t*>(content), out); break; | ||
583 | case "Return"_id: transformReturn(static_cast<Return_t*>(content), out); break; | 577 | case "Return"_id: transformReturn(static_cast<Return_t*>(content), out); break; |
584 | case "Local"_id: transformLocal(static_cast<Local_t*>(content), out); break; | 578 | case "Local"_id: transformLocal(static_cast<Local_t*>(content), out); break; |
585 | case "Export"_id: transformExport(static_cast<Export_t*>(content), out); break; | 579 | case "Export"_id: transformExport(static_cast<Export_t*>(content), out); break; |
586 | case "BreakLoop"_id: transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; | 580 | case "BreakLoop"_id: transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; |
587 | case "Assignment"_id: transformAssignment(static_cast<Assignment_t*>(content), out); break; | 581 | case "Assignment"_id: transformAssignment(static_cast<Assignment_t*>(content), out); break; |
588 | case "Comprehension"_id: transformCompCommon(static_cast<Comprehension_t*>(content), out); break; | ||
589 | case "ExpList"_id: { | 582 | case "ExpList"_id: { |
590 | auto expList = static_cast<ExpList_t*>(content); | 583 | auto expList = static_cast<ExpList_t*>(content); |
591 | if (expList->exprs.objects().empty()) { | 584 | if (expList->exprs.objects().empty()) { |
@@ -606,6 +599,7 @@ private: | |||
606 | case "For"_id: transformFor(static_cast<For_t*>(value), out); break; | 599 | case "For"_id: transformFor(static_cast<For_t*>(value), out); break; |
607 | case "While"_id: transformWhile(static_cast<While_t*>(value), out); break; | 600 | case "While"_id: transformWhile(static_cast<While_t*>(value), out); break; |
608 | case "Do"_id: transformDo(static_cast<Do_t*>(value), out); break; | 601 | case "Do"_id: transformDo(static_cast<Do_t*>(value), out); break; |
602 | case "Comprehension"_id: transformCompCommon(static_cast<Comprehension_t*>(value), out); break; | ||
609 | default: specialSingleValue = false; break; | 603 | default: specialSingleValue = false; break; |
610 | } | 604 | } |
611 | if (specialSingleValue) { | 605 | if (specialSingleValue) { |
@@ -653,25 +647,24 @@ private: | |||
653 | 647 | ||
654 | str_list transformAssignDefs(ExpList_t* expList) { | 648 | str_list transformAssignDefs(ExpList_t* expList) { |
655 | str_list preDefs; | 649 | str_list preDefs; |
656 | expList->traverse([&](ast_node* child) { | 650 | for (auto exp_ : expList->exprs.objects()) { |
657 | if (child->getId() == "Value"_id) { | 651 | auto exp = static_cast<Exp_t*>(exp_); |
658 | if (auto callable = child->getByPath<ChainValue_t, Callable_t>()) { | 652 | if (auto value = singleValueFrom(exp)) { |
659 | if (ast_is<Variable_t>(callable->item)) { | 653 | if (auto chain = value->item.as<ChainValue_t>()) { |
654 | do { | ||
655 | if (chain->items.size() != 1) break; | ||
656 | auto callable = ast_cast<Callable_t>(chain->items.front()); | ||
657 | if (!callable) break; | ||
660 | auto name = toString(callable->item); | 658 | auto name = toString(callable->item); |
661 | if (addToScope(name)) { | 659 | if (addToScope(name)) { |
662 | preDefs.push_back(name); | 660 | preDefs.push_back(name); |
663 | } | 661 | } |
664 | } else if (callable->getByPath<SelfName_t, self_t>()) { | 662 | } while (false); |
665 | auto self = s("self"sv); | ||
666 | if (addToScope(self)) { | ||
667 | preDefs.push_back(self); | ||
668 | } | ||
669 | } | ||
670 | } | 663 | } |
671 | return traversal::Return; | 664 | } else { |
665 | throw std::logic_error("left hand expression is not assignable"); | ||
672 | } | 666 | } |
673 | return traversal::Continue; | 667 | } |
674 | }); | ||
675 | return preDefs; | 668 | return preDefs; |
676 | } | 669 | } |
677 | 670 | ||
@@ -706,12 +699,22 @@ private: | |||
706 | 699 | ||
707 | void assignLastExplist(ExpList_t* expList, Body_t* body) { | 700 | void assignLastExplist(ExpList_t* expList, Body_t* body) { |
708 | auto last = lastStatementFrom(body); | 701 | auto last = lastStatementFrom(body); |
709 | auto valueList = last ? last->content.as<ExpList_t>() : nullptr; | 702 | bool lastAssignable = last && ast_is<ExpList_t, For_t, ForEach_t, While_t>(last->content); |
710 | if (last && valueList) { | 703 | if (lastAssignable) { |
711 | auto newAssignment = new_ptr<Assignment_t>(); | 704 | auto newAssignment = new_ptr<Assignment_t>(); |
712 | newAssignment->assignable.set(expList); | 705 | newAssignment->assignable.set(expList); |
713 | auto assign = new_ptr<Assign_t>(); | 706 | auto assign = new_ptr<Assign_t>(); |
714 | assign->values.dup(valueList->exprs); | 707 | if (auto valueList = last->content.as<ExpList_t>()) { |
708 | assign->values.dup(valueList->exprs); | ||
709 | } else { | ||
710 | auto simpleValue = new_ptr<SimpleValue_t>(); | ||
711 | simpleValue->value.set(last->content); | ||
712 | auto value = new_ptr<Value_t>(); | ||
713 | value->item.set(simpleValue); | ||
714 | auto exp = new_ptr<Exp_t>(); | ||
715 | exp->value.set(value); | ||
716 | assign->values.push_back(exp); | ||
717 | } | ||
715 | newAssignment->target.set(assign); | 718 | newAssignment->target.set(assign); |
716 | last->content.set(newAssignment); | 719 | last->content.set(newAssignment); |
717 | } | 720 | } |
@@ -767,19 +770,19 @@ private: | |||
767 | out.back() = preDefine + out.back(); | 770 | out.back() = preDefine + out.back(); |
768 | return; | 771 | return; |
769 | } | 772 | } |
773 | if (auto withNode = ast_cast<With_t>(value)) { | ||
774 | str_list temp; | ||
775 | auto expList = assignment->assignable.get(); | ||
776 | std::string preDefine = getPredefine(assignment); | ||
777 | transformWith(withNode, temp, expList); | ||
778 | out.push_back(preDefine + temp.back()); | ||
779 | return; | ||
780 | } | ||
770 | auto exp = ast_cast<Exp_t>(value); | 781 | auto exp = ast_cast<Exp_t>(value); |
771 | if (!exp) break; | 782 | if (!exp) break; |
772 | if (auto simpleVal = exp->value->item.as<SimpleValue_t>()) { | 783 | if (auto simpleVal = exp->value->item.as<SimpleValue_t>()) { |
773 | auto valueItem = simpleVal->value.get(); | 784 | auto valueItem = simpleVal->value.get(); |
774 | switch (valueItem->getId()) { | 785 | switch (valueItem->getId()) { |
775 | case "With"_id: { | ||
776 | str_list temp; | ||
777 | auto expList = assignment->assignable.get(); | ||
778 | std::string preDefine = getPredefine(assignment); | ||
779 | transformWith(static_cast<With_t*>(valueItem), temp, expList); | ||
780 | out.push_back(preDefine + temp.front()); | ||
781 | return; | ||
782 | } | ||
783 | case "Do"_id: { | 786 | case "Do"_id: { |
784 | auto doNode = static_cast<Do_t*>(valueItem); | 787 | auto doNode = static_cast<Do_t*>(valueItem); |
785 | auto expList = assignment->assignable.get(); | 788 | auto expList = assignment->assignable.get(); |
@@ -808,7 +811,7 @@ private: | |||
808 | auto expList = assignment->assignable.get(); | 811 | auto expList = assignment->assignable.get(); |
809 | std::string preDefine = getPredefine(assignment); | 812 | std::string preDefine = getPredefine(assignment); |
810 | transformForInPlace(static_cast<For_t*>(valueItem), temp, expList); | 813 | transformForInPlace(static_cast<For_t*>(valueItem), temp, expList); |
811 | out.push_back(preDefine + temp.front()); | 814 | out.push_back(preDefine + temp.back()); |
812 | return; | 815 | return; |
813 | } | 816 | } |
814 | case "ForEach"_id: { | 817 | case "ForEach"_id: { |
@@ -816,7 +819,7 @@ private: | |||
816 | auto expList = assignment->assignable.get(); | 819 | auto expList = assignment->assignable.get(); |
817 | std::string preDefine = getPredefine(assignment); | 820 | std::string preDefine = getPredefine(assignment); |
818 | transformForEachInPlace(static_cast<ForEach_t*>(valueItem), temp, expList); | 821 | transformForEachInPlace(static_cast<ForEach_t*>(valueItem), temp, expList); |
819 | out.push_back(preDefine + temp.front()); | 822 | out.push_back(preDefine + temp.back()); |
820 | return; | 823 | return; |
821 | } | 824 | } |
822 | case "ClassDecl"_id: { | 825 | case "ClassDecl"_id: { |
@@ -824,7 +827,7 @@ private: | |||
824 | auto expList = assignment->assignable.get(); | 827 | auto expList = assignment->assignable.get(); |
825 | std::string preDefine = getPredefine(assignment); | 828 | std::string preDefine = getPredefine(assignment); |
826 | transformClassDecl(static_cast<ClassDecl_t*>(valueItem), temp, ExpUsage::Assignment, expList); | 829 | transformClassDecl(static_cast<ClassDecl_t*>(valueItem), temp, ExpUsage::Assignment, expList); |
827 | out.push_back(preDefine + temp.front()); | 830 | out.push_back(preDefine + temp.back()); |
828 | return; | 831 | return; |
829 | } | 832 | } |
830 | case "While"_id: { | 833 | case "While"_id: { |
@@ -832,7 +835,7 @@ private: | |||
832 | auto expList = assignment->assignable.get(); | 835 | auto expList = assignment->assignable.get(); |
833 | std::string preDefine = getPredefine(assignment); | 836 | std::string preDefine = getPredefine(assignment); |
834 | transformWhileClosure(static_cast<While_t*>(valueItem), temp, expList); | 837 | transformWhileClosure(static_cast<While_t*>(valueItem), temp, expList); |
835 | out.push_back(preDefine + temp.front()); | 838 | out.push_back(preDefine + temp.back()); |
836 | return; | 839 | return; |
837 | } | 840 | } |
838 | } | 841 | } |
@@ -912,7 +915,7 @@ private: | |||
912 | 915 | ||
913 | void transformAssignItem(ast_node* value, str_list& out) { | 916 | void transformAssignItem(ast_node* value, str_list& out) { |
914 | switch (value->getId()) { | 917 | switch (value->getId()) { |
915 | case "With"_id: transformWith(static_cast<With_t*>(value), out); break; | 918 | case "With"_id: transformWithClosure(static_cast<With_t*>(value), out); break; |
916 | case "If"_id: transformIf(static_cast<If_t*>(value), out, IfUsage::Closure); break; | 919 | case "If"_id: transformIf(static_cast<If_t*>(value), out, IfUsage::Closure); break; |
917 | case "Switch"_id: transformSwitchClosure(static_cast<Switch_t*>(value), out); break; | 920 | case "Switch"_id: transformSwitchClosure(static_cast<Switch_t*>(value), out); break; |
918 | case "TableBlock"_id: transformTableBlock(static_cast<TableBlock_t*>(value), out); break; | 921 | case "TableBlock"_id: transformTableBlock(static_cast<TableBlock_t*>(value), out); break; |
@@ -1248,9 +1251,19 @@ private: | |||
1248 | if (pair.first) { | 1251 | if (pair.first) { |
1249 | str_list tmp; | 1252 | str_list tmp; |
1250 | auto condition = pair.first->condition.get(); | 1253 | auto condition = pair.first->condition.get(); |
1251 | transformExp(condition, tmp); | 1254 | if (unless) { |
1255 | if (auto value = singleValueFrom(condition)) { | ||
1256 | transformValue(value, tmp); | ||
1257 | } else { | ||
1258 | transformExp(condition, tmp); | ||
1259 | tmp.back() = s("("sv) + tmp.back() + s(")"sv); | ||
1260 | } | ||
1261 | tmp.back().insert(0, s("not "sv)); | ||
1262 | } else { | ||
1263 | transformExp(condition, tmp); | ||
1264 | } | ||
1252 | _buf << indent() << (pair == ifCondPairs.front() ? ""sv : "else"sv) << | 1265 | _buf << indent() << (pair == ifCondPairs.front() ? ""sv : "else"sv) << |
1253 | "if "sv << (unless ? "not ("sv : ""sv) << tmp.front() << (unless ? ") then"sv : " then"sv) << nll(condition); | 1266 | "if "sv << tmp.back() << " then"sv << nll(condition); |
1254 | temp.push_back(clearBuf()); | 1267 | temp.push_back(clearBuf()); |
1255 | } | 1268 | } |
1256 | if (pair.second) { | 1269 | if (pair.second) { |
@@ -1355,7 +1368,7 @@ private: | |||
1355 | case "If"_id: transformIf(static_cast<If_t*>(value), out, IfUsage::Closure); break; | 1368 | case "If"_id: transformIf(static_cast<If_t*>(value), out, IfUsage::Closure); break; |
1356 | case "Unless"_id: transformUnless(static_cast<Unless_t*>(value), out, IfUsage::Closure); break; | 1369 | case "Unless"_id: transformUnless(static_cast<Unless_t*>(value), out, IfUsage::Closure); break; |
1357 | case "Switch"_id: transformSwitchClosure(static_cast<Switch_t*>(value), out); break; | 1370 | case "Switch"_id: transformSwitchClosure(static_cast<Switch_t*>(value), out); break; |
1358 | case "With"_id: transformWith(static_cast<With_t*>(value), out); break; | 1371 | case "With"_id: transformWithClosure(static_cast<With_t*>(value), out); break; |
1359 | case "ClassDecl"_id: transformClassDeclClosure(static_cast<ClassDecl_t*>(value), out); break; | 1372 | case "ClassDecl"_id: transformClassDeclClosure(static_cast<ClassDecl_t*>(value), out); break; |
1360 | case "ForEach"_id: transformForEachClosure(static_cast<ForEach_t*>(value), out); break; | 1373 | case "ForEach"_id: transformForEachClosure(static_cast<ForEach_t*>(value), out); break; |
1361 | case "For"_id: transformForClosure(static_cast<For_t*>(value), out); break; | 1374 | case "For"_id: transformForClosure(static_cast<For_t*>(value), out); break; |
@@ -1535,6 +1548,10 @@ private: | |||
1535 | transformTblCompReturn(comp, out); | 1548 | transformTblCompReturn(comp, out); |
1536 | return; | 1549 | return; |
1537 | } | 1550 | } |
1551 | if (auto with = simpleValue->value.as<With_t>()) { | ||
1552 | transformWith(with, out, nullptr, true); | ||
1553 | return; | ||
1554 | } | ||
1538 | if (auto classDecl = simpleValue->value.as<ClassDecl_t>()) { | 1555 | if (auto classDecl = simpleValue->value.as<ClassDecl_t>()) { |
1539 | transformClassDecl(classDecl, out, ExpUsage::Return); | 1556 | transformClassDecl(classDecl, out, ExpUsage::Return); |
1540 | return; | 1557 | return; |
@@ -1579,15 +1596,15 @@ private: | |||
1579 | if (!argsDef->defList) { | 1596 | if (!argsDef->defList) { |
1580 | out.push_back(Empty); | 1597 | out.push_back(Empty); |
1581 | out.push_back(Empty); | 1598 | out.push_back(Empty); |
1582 | return; | 1599 | } else { |
1600 | transformFnArgDefList(argsDef->defList, out); | ||
1583 | } | 1601 | } |
1584 | transformFnArgDefList(argsDef->defList, out); | ||
1585 | if (argsDef->shadowOption) { | 1602 | if (argsDef->shadowOption) { |
1586 | transform_outer_var_shadow(argsDef->shadowOption, out); | 1603 | transform_outer_var_shadow(argsDef->shadowOption); |
1587 | } | 1604 | } |
1588 | } | 1605 | } |
1589 | 1606 | ||
1590 | void transform_outer_var_shadow(outer_var_shadow_t* shadow, str_list& out) { | 1607 | void transform_outer_var_shadow(outer_var_shadow_t* shadow) { |
1591 | markVarShadowed(); | 1608 | markVarShadowed(); |
1592 | if (shadow->varList) { | 1609 | if (shadow->varList) { |
1593 | for (auto name : shadow->varList->names.objects()) { | 1610 | for (auto name : shadow->varList->names.objects()) { |
@@ -1752,7 +1769,12 @@ private: | |||
1752 | _buf << indent(-1) << "do"sv << nll(chainValue); | 1769 | _buf << indent(-1) << "do"sv << nll(chainValue); |
1753 | } | 1770 | } |
1754 | _buf << indent() << "local "sv << baseVar << " = "sv << caller << nll(chainValue); | 1771 | _buf << indent() << "local "sv << baseVar << " = "sv << caller << nll(chainValue); |
1755 | _buf << indent() << "local "sv << fnVar << " = "sv << baseVar << "."sv << funcName << nll(chainValue); | 1772 | _buf << indent() << "local "sv << fnVar << " = "sv << baseVar; |
1773 | if (State::luaKeywords.find(funcName) != State::luaKeywords.end()) { | ||
1774 | _buf << "[\""sv << funcName << "\"]" << nll(chainValue); | ||
1775 | } else { | ||
1776 | _buf << "."sv << funcName << nll(chainValue); | ||
1777 | } | ||
1756 | switch (usage) { | 1778 | switch (usage) { |
1757 | case ExpUsage::Return: | 1779 | case ExpUsage::Return: |
1758 | _buf << indent() << "return function(...)" << nll(chainValue); | 1780 | _buf << indent() << "return function(...)" << nll(chainValue); |
@@ -1841,7 +1863,8 @@ private: | |||
1841 | } | 1863 | } |
1842 | 1864 | ||
1843 | void transformColonChainItem(ColonChainItem_t* colonChainItem, str_list& out) { | 1865 | void transformColonChainItem(ColonChainItem_t* colonChainItem, str_list& out) { |
1844 | out.push_back(s(colonChainItem->switchToDot ? "."sv : ":"sv) + toString(colonChainItem->name)); | 1866 | auto name = toString(colonChainItem->name); |
1867 | out.push_back(s(colonChainItem->switchToDot ? "."sv : ":"sv) + name); | ||
1845 | } | 1868 | } |
1846 | 1869 | ||
1847 | void transformSlice(Slice_t* slice, str_list& out) { | 1870 | void transformSlice(Slice_t* slice, str_list& out) { |
@@ -1899,7 +1922,15 @@ private: | |||
1899 | break; | 1922 | break; |
1900 | } | 1923 | } |
1901 | } | 1924 | } |
1902 | transformStatement(comp->value.to<Statement_t>(), temp); | 1925 | if (auto stmt = comp->value.as<Statement_t>()) { |
1926 | transformStatement(stmt, temp); | ||
1927 | } else if (auto exp = comp->value.as<Exp_t>()) { | ||
1928 | auto expList = new_ptr<ExpList_t>(); | ||
1929 | expList->exprs.push_back(exp); | ||
1930 | auto statement = new_ptr<Statement_t>(); | ||
1931 | statement->content.set(expList); | ||
1932 | transformStatement(statement, temp); | ||
1933 | } | ||
1903 | auto value = temp.back(); | 1934 | auto value = temp.back(); |
1904 | temp.pop_back(); | 1935 | temp.pop_back(); |
1905 | _buf << join(temp) << value; | 1936 | _buf << join(temp) << value; |
@@ -2306,10 +2337,10 @@ private: | |||
2306 | str_list temp; | 2337 | str_list temp; |
2307 | std::string accum = getUnusedName("_accum_"); | 2338 | std::string accum = getUnusedName("_accum_"); |
2308 | std::string len = getUnusedName("_len_"); | 2339 | std::string len = getUnusedName("_len_"); |
2309 | addToScope(accum); | ||
2310 | addToScope(len); | ||
2311 | _buf << "(function()"sv << nll(forEach); | 2340 | _buf << "(function()"sv << nll(forEach); |
2312 | pushScope(); | 2341 | pushScope(); |
2342 | addToScope(accum); | ||
2343 | addToScope(len); | ||
2313 | _buf << indent() << "local "sv << accum << " = { }"sv << nll(forEach); | 2344 | _buf << indent() << "local "sv << accum << " = { }"sv << nll(forEach); |
2314 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); | 2345 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); |
2315 | temp.push_back(clearBuf()); | 2346 | temp.push_back(clearBuf()); |
@@ -2599,9 +2630,7 @@ private: | |||
2599 | temp.push_back(indent() + s("local "sv) + parentVar + s(" = "sv) + parent + nll(classDecl)); | 2630 | temp.push_back(indent() + s("local "sv) + parentVar + s(" = "sv) + parent + nll(classDecl)); |
2600 | } | 2631 | } |
2601 | auto baseVar = getUnusedName("_base_"sv); | 2632 | auto baseVar = getUnusedName("_base_"sv); |
2602 | auto selfVar = getUnusedName("_self_"sv); | ||
2603 | addToScope(baseVar); | 2633 | addToScope(baseVar); |
2604 | addToScope(selfVar); | ||
2605 | temp.push_back(indent() + s("local "sv) + baseVar + s(" = "sv)); | 2634 | temp.push_back(indent() + s("local "sv) + baseVar + s(" = "sv)); |
2606 | str_list builtins; | 2635 | str_list builtins; |
2607 | str_list commons; | 2636 | str_list commons; |
@@ -2702,9 +2731,13 @@ private: | |||
2702 | _buf << indent(1) << "__index = "sv << baseVar << ","sv << nll(classDecl); | 2731 | _buf << indent(1) << "__index = "sv << baseVar << ","sv << nll(classDecl); |
2703 | } | 2732 | } |
2704 | _buf << indent(1) << "__call = function(cls, ...)"sv << nll(classDecl); | 2733 | _buf << indent(1) << "__call = function(cls, ...)"sv << nll(classDecl); |
2705 | _buf << indent(2) << "local " << selfVar << " = setmetatable({}, "sv << baseVar << ")"sv << nll(classDecl); | 2734 | pushScope(); |
2706 | _buf << indent(2) << "cls.__init("sv << selfVar << ", ...)"sv << nll(classDecl); | 2735 | auto selfVar = getUnusedName("_self_"sv); |
2707 | _buf << indent(2) << "return "sv << selfVar << nll(classDecl); | 2736 | addToScope(selfVar); |
2737 | _buf << indent(1) << "local " << selfVar << " = setmetatable({}, "sv << baseVar << ")"sv << nll(classDecl); | ||
2738 | _buf << indent(1) << "cls.__init("sv << selfVar << ", ...)"sv << nll(classDecl); | ||
2739 | _buf << indent(1) << "return "sv << selfVar << nll(classDecl); | ||
2740 | popScope(); | ||
2708 | _buf << indent(1) << "end"sv << nll(classDecl); | 2741 | _buf << indent(1) << "end"sv << nll(classDecl); |
2709 | _buf << indent() << "})"sv << nll(classDecl); | 2742 | _buf << indent() << "})"sv << nll(classDecl); |
2710 | _buf << indent() << baseVar << ".__class = "sv << classVar << nll(classDecl); | 2743 | _buf << indent() << baseVar << ".__class = "sv << classVar << nll(classDecl); |
@@ -2846,7 +2879,17 @@ private: | |||
2846 | } | 2879 | } |
2847 | } | 2880 | } |
2848 | 2881 | ||
2849 | void transformWith(With_t* with, str_list& out, ExpList_t* assignList = nullptr) { | 2882 | void transformWithClosure(With_t* with, str_list& out) { |
2883 | str_list temp; | ||
2884 | temp.push_back(s("(function()"sv) + nll(with)); | ||
2885 | pushScope(); | ||
2886 | transformWith(with, temp, nullptr, true); | ||
2887 | popScope(); | ||
2888 | temp.push_back(indent() + s("end)()"sv)); | ||
2889 | out.push_back(join(temp)); | ||
2890 | } | ||
2891 | |||
2892 | void transformWith(With_t* with, str_list& out, ExpList_t* assignList = nullptr, bool returnValue = false) { | ||
2850 | str_list temp; | 2893 | str_list temp; |
2851 | std::string withVar; | 2894 | std::string withVar; |
2852 | bool scoped = false; | 2895 | bool scoped = false; |
@@ -2926,6 +2969,12 @@ private: | |||
2926 | assignment->target.set(assign); | 2969 | assignment->target.set(assign); |
2927 | transformAssignment(assignment, temp); | 2970 | transformAssignment(assignment, temp); |
2928 | } | 2971 | } |
2972 | if (returnValue) { | ||
2973 | auto stmt = lastStatementFrom(with->body); | ||
2974 | if (!stmt->content.is<Return_t>()) { | ||
2975 | temp.push_back(indent() + s("return "sv) + withVar + nll(with)); | ||
2976 | } | ||
2977 | } | ||
2929 | if (scoped) { | 2978 | if (scoped) { |
2930 | popScope(); | 2979 | popScope(); |
2931 | temp.push_back(indent() + s("end"sv) + nll(with)); | 2980 | temp.push_back(indent() + s("end"sv) + nll(with)); |
@@ -2992,6 +3041,10 @@ private: | |||
2992 | } | 3041 | } |
2993 | 3042 | ||
2994 | void transformTable(ast_node* table, const std::list<ast_node*>& pairs, str_list& out) { | 3043 | void transformTable(ast_node* table, const std::list<ast_node*>& pairs, str_list& out) { |
3044 | if (pairs.empty()) { | ||
3045 | out.push_back(s("{ }"sv)); | ||
3046 | return; | ||
3047 | } | ||
2995 | str_list temp; | 3048 | str_list temp; |
2996 | pushScope(); | 3049 | pushScope(); |
2997 | for (auto pair : pairs) { | 3050 | for (auto pair : pairs) { |
@@ -3386,13 +3439,346 @@ const std::string MoonCompliler::Empty; | |||
3386 | int main() | 3439 | int main() |
3387 | { | 3440 | { |
3388 | std::string s = R"TestCodesHere( | 3441 | std::string s = R"TestCodesHere( |
3442 | Dorothy builtin.ImGui | ||
3443 | import Set,Path from require "Utils" | ||
3444 | LintGlobal = require "LintGlobal" | ||
3445 | moonscript = require "moonscript" | ||
3446 | |||
3447 | LoadFontTTF "Font/DroidSansFallback.ttf", 20, "Chinese" | ||
3448 | |||
3449 | moduleCache = {} | ||
3450 | oldRequire = _G.require | ||
3451 | newRequire = (path)-> | ||
3452 | loaded = package.loaded[path] | ||
3453 | if not loaded | ||
3454 | table.insert moduleCache,path | ||
3455 | return oldRequire path | ||
3456 | loaded | ||
3457 | _G.require = newRequire | ||
3458 | builtin.require = newRequire | ||
3459 | |||
3460 | allowedUseOfGlobals = Set { | ||
3461 | } | ||
3389 | 3462 | ||
3390 | do | 3463 | LintMoonGlobals = (moonCodes,entry)-> |
3391 | a = -> | 3464 | globals,err = LintGlobal moonCodes |
3392 | with something | 3465 | if not globals |
3393 | print .hello | 3466 | error "Compile failed in #{entry}\n#{err}" |
3394 | print hi | 3467 | requireModules = {} |
3395 | print "world" | 3468 | withImGui = false |
3469 | withPlatformer = false | ||
3470 | importCodes = table.concat ( | ||
3471 | for importLine in moonCodes\gmatch "Dorothy%s*%(?([^%)!\r\n]*)%s*[%)!]?" | ||
3472 | continue if importLine == "" | ||
3473 | importLine | ||
3474 | ), "," | ||
3475 | importItems = if importCodes | ||
3476 | for item in importCodes\gmatch "%s*([^,\n\r]+)%s*" | ||
3477 | getImport = loadstring "return #{item}" | ||
3478 | importItem = if getImport then getImport! else nil | ||
3479 | continue if not importItem or "table" ~= type importItem | ||
3480 | {importItem, item} | ||
3481 | else {} | ||
3482 | importSet = {} | ||
3483 | for name,_ in pairs globals | ||
3484 | if not allowedUseOfGlobals[name] | ||
3485 | if builtin[name] | ||
3486 | table.insert requireModules, "local #{name} = require(\"#{name}\")" | ||
3487 | else | ||
3488 | findModule = false | ||
3489 | for i,importItem in ipairs importItems | ||
3490 | if importItem[1][name] ~= nil | ||
3491 | moduleName = "_module_#{i-1}" | ||
3492 | if not importSet[importItem[1]] | ||
3493 | importSet[importItem[1]] = true | ||
3494 | table.insert requireModules, "local #{moduleName} = #{importItem[2]}" | ||
3495 | table.insert requireModules, "local #{name} = #{moduleName}.#{name}" | ||
3496 | findModule = true | ||
3497 | break | ||
3498 | if not findModule | ||
3499 | error "Used invalid global value \"#{name}\" in \"#{entry}\"." | ||
3500 | table.concat requireModules, "\n" | ||
3501 | |||
3502 | totalFiles = 0 | ||
3503 | totalMoonTime = 0 | ||
3504 | totalXmlTime = 0 | ||
3505 | totalMinifyTime = 0 | ||
3506 | compile = (dir,clean,minify)-> | ||
3507 | {:ParseLua} = require "luaminify.ParseLua" | ||
3508 | FormatMini = require "luaminify.FormatMini" | ||
3509 | files = Path.getAllFiles dir, {"moon","xml"} | ||
3510 | for file in *files | ||
3511 | path = Path.getPath file | ||
3512 | name = Path.getName file | ||
3513 | isXml = "xml" == Path.getExtension file | ||
3514 | compileFunc = isXml and xmltolua or moonscript.to_lua | ||
3515 | requires = nil | ||
3516 | if not clean | ||
3517 | sourceCodes = Content\loadAsync "#{dir}/#{file}" | ||
3518 | requires = LintMoonGlobals sourceCodes, file unless isXml | ||
3519 | startTime = App.eclapsedTime | ||
3520 | codes,err = compileFunc sourceCodes | ||
3521 | if isXml | ||
3522 | totalXmlTime += App.eclapsedTime - startTime | ||
3523 | else | ||
3524 | totalMoonTime += App.eclapsedTime - startTime | ||
3525 | startTime = App.eclapsedTime | ||
3526 | if not codes | ||
3527 | print "Compile errors in #{file}." | ||
3528 | print err | ||
3529 | return false | ||
3530 | else | ||
3531 | codes = requires..codes\gsub "Dorothy%([^%)]*%)","" unless isXml | ||
3532 | if minify | ||
3533 | st, ast = ParseLua codes | ||
3534 | if not st | ||
3535 | print ast | ||
3536 | return false | ||
3537 | codes = FormatMini ast | ||
3538 | totalMinifyTime += App.eclapsedTime - startTime | ||
3539 | filePath = Content.writablePath..path | ||
3540 | Content\mkdir filePath | ||
3541 | filename = "#{filePath}#{name}.lua" | ||
3542 | Content\saveAsync filename,codes | ||
3543 | print "#{isXml and "Xml" or "Moon"} compiled: #{path}#{name}.#{isXml and "xml" or "moon"}" | ||
3544 | totalFiles += 1 | ||
3545 | else | ||
3546 | filePath = Content.writablePath..path | ||
3547 | Content\mkdir filePath | ||
3548 | filename = "#{filePath}#{name}.lua" | ||
3549 | if Content\exist filename | ||
3550 | print "#{isXml and "Xml" or "Moon"} cleaned: #{path}#{name}.lua" | ||
3551 | Content\remove filename | ||
3552 | if clean or minify | ||
3553 | files = Path.getAllFiles dir, "lua" | ||
3554 | for file in *files | ||
3555 | path = Path.getPath file | ||
3556 | name = Path.getName file | ||
3557 | if not clean | ||
3558 | sourceCodes = Content\loadAsync "#{dir}/#{file}" | ||
3559 | startTime = App.eclapsedTime | ||
3560 | st, ast = ParseLua sourceCodes | ||
3561 | if not st | ||
3562 | print ast | ||
3563 | return false | ||
3564 | codes = FormatMini ast | ||
3565 | totalMinifyTime += App.eclapsedTime - startTime | ||
3566 | filePath = Content.writablePath..path | ||
3567 | Content\mkdir filePath | ||
3568 | filename = "#{filePath}#{name}.lua" | ||
3569 | Content\saveAsync filename,codes | ||
3570 | print "Lua minified: #{path}#{name}.lua" | ||
3571 | totalFiles += 1 | ||
3572 | else | ||
3573 | filePath = Content.writablePath..path | ||
3574 | Content\mkdir filePath | ||
3575 | filename = "#{filePath}#{name}.lua" | ||
3576 | if Content\exist filename | ||
3577 | print "Lua cleaned: #{path}#{name}.lua" | ||
3578 | Content\remove filename | ||
3579 | return true | ||
3580 | |||
3581 | building = false | ||
3582 | |||
3583 | doCompile = (minify)-> | ||
3584 | return if building | ||
3585 | building = true | ||
3586 | totalFiles = 0 | ||
3587 | totalMoonTime = 0 | ||
3588 | totalXmlTime = 0 | ||
3589 | totalMinifyTime = 0 | ||
3590 | thread -> | ||
3591 | print "Output path: #{Content.writablePath}" | ||
3592 | xpcall (-> compile Content.assetPath\sub(1,-2),false,minify),(msg)-> | ||
3593 | msg = debug.traceback msg | ||
3594 | print msg | ||
3595 | building = false | ||
3596 | print string.format "Compile #{minify and 'and minify ' or ''}done. %d files in total.\nCompile time, Moon %.3fs, Xml %.3fs#{minify and ', Minify %.3fs' or ''}.\n",totalFiles,totalMoonTime,totalXmlTime,totalMinifyTime | ||
3597 | building = false | ||
3598 | |||
3599 | doClean = -> | ||
3600 | return if building | ||
3601 | building = true | ||
3602 | thread -> | ||
3603 | print "Clean path: #{Content.writablePath}" | ||
3604 | compile Content.assetPath\sub(1,-2),true | ||
3605 | print "Clean done.\n" | ||
3606 | building = false | ||
3607 | |||
3608 | isInEntry = true | ||
3609 | |||
3610 | allClear = -> | ||
3611 | for module in *moduleCache | ||
3612 | package.loaded[module] = nil | ||
3613 | moduleCache = {} | ||
3614 | with Director.ui | ||
3615 | \removeAllChildren! | ||
3616 | .userData = nil | ||
3617 | with Director.entry | ||
3618 | \removeAllChildren! | ||
3619 | .userData = nil | ||
3620 | with Director.postNode | ||
3621 | \removeAllChildren! | ||
3622 | .userData = nil | ||
3623 | Director\popCamera! | ||
3624 | Cache\unload! | ||
3625 | Entity\clear! | ||
3626 | Platformer.Data\clear! | ||
3627 | Platformer.UnitAction\clear! | ||
3628 | currentEntryName = nil | ||
3629 | isInEntry = true | ||
3630 | Audio\stopStream 0.2 | ||
3631 | |||
3632 | games = [Path.getName item for item in *Path.getFolders Content.assetPath.."Script/Game", {"xml","lua","moon"}] | ||
3633 | table.sort games | ||
3634 | examples = [Path.getName item for item in *Path.getAllFiles Content.assetPath.."Script/Example", {"xml","lua","moon"}] | ||
3635 | table.sort examples | ||
3636 | tests = [Path.getName item for item in *Path.getAllFiles Content.assetPath.."Script/Test", {"xml","lua","moon"}] | ||
3637 | table.sort tests | ||
3638 | currentEntryName = nil | ||
3639 | allNames = for game in *games do "Game/#{game}/init" | ||
3640 | for example in *examples do table.insert allNames,"Example/#{example}" | ||
3641 | for test in *tests do table.insert allNames,"Test/#{test}" | ||
3642 | |||
3643 | enterDemoEntry = (name)-> | ||
3644 | isInEntry = false | ||
3645 | xpcall (-> | ||
3646 | result = require name | ||
3647 | if "function" == type result | ||
3648 | result = result! | ||
3649 | Director.entry\addChild if tolua.cast result, "Node" | ||
3650 | result | ||
3651 | else | ||
3652 | Node! | ||
3653 | else | ||
3654 | Director.entry\addChild Node! | ||
3655 | currentEntryName = name | ||
3656 | ),(msg)-> | ||
3657 | msg = debug.traceback msg | ||
3658 | print msg | ||
3659 | allClear! | ||
3660 | |||
3661 | showEntry = false | ||
3662 | |||
3663 | thread -> | ||
3664 | {:width,:height} = App.visualSize | ||
3665 | scale = App.deviceRatio*0.7*math.min(width,height)/760 | ||
3666 | with Sprite GetDorothySSRHappyWhite scale | ||
3667 | \addTo Director.entry | ||
3668 | sleep 1.0 | ||
3669 | \removeFromParent! | ||
3670 | showEntry = true | ||
3671 | Director.clearColor = Color 0xff1a1a1a | ||
3672 | |||
3673 | showStats = false | ||
3674 | showLog = false | ||
3675 | showFooter = true | ||
3676 | scaleContent = false | ||
3677 | footerFocus = false | ||
3678 | screenScale = 2 -- App.deviceRatio | ||
3679 | threadLoop -> | ||
3680 | return unless showEntry | ||
3681 | left = Keyboard\isKeyDown "Left" | ||
3682 | right = Keyboard\isKeyDown "Right" | ||
3683 | App\shutdown! if Keyboard\isKeyDown "Escape" | ||
3684 | {:width,:height} = App.visualSize | ||
3685 | SetNextWindowSize Vec2(190,50) | ||
3686 | SetNextWindowPos Vec2(width-190,height-50) | ||
3687 | if width >= 600 | ||
3688 | if not footerFocus | ||
3689 | footerFocus = true | ||
3690 | SetNextWindowFocus! | ||
3691 | PushStyleColor "WindowBg", Color(0x0), -> | ||
3692 | Begin "Show", "NoTitleBar|NoResize|NoMove|NoCollapse|NoSavedSettings", -> | ||
3693 | Columns 2,false | ||
3694 | if showFooter | ||
3695 | changed, scaleContent = Checkbox string.format("%.1fx",screenScale), scaleContent | ||
3696 | View.scale = scaleContent and screenScale or 1 if changed | ||
3697 | else | ||
3698 | Dummy Vec2 10,30 | ||
3699 | SameLine! | ||
3700 | NextColumn! | ||
3701 | _, showFooter = Checkbox "Footer", showFooter | ||
3702 | elseif footerFocus | ||
3703 | footerFocus = false | ||
3704 | return unless showFooter | ||
3705 | SetNextWindowSize Vec2(width,60) | ||
3706 | SetNextWindowPos Vec2(0,height-60) | ||
3707 | Begin "Footer", "NoTitleBar|NoResize|NoMove|NoCollapse|NoBringToFrontOnFocus|NoSavedSettings", -> | ||
3708 | Separator! | ||
3709 | _, showStats = Checkbox "Stats", showStats | ||
3710 | SameLine! | ||
3711 | _, showLog = Checkbox "Log", showLog | ||
3712 | SameLine! | ||
3713 | if isInEntry | ||
3714 | OpenPopup "build" if Button "Build", Vec2(70,30) | ||
3715 | BeginPopup "build", -> | ||
3716 | doCompile false if Selectable "Compile" | ||
3717 | Separator! | ||
3718 | doCompile true if Selectable "Minify" | ||
3719 | Separator! | ||
3720 | doClean! if Selectable "Clean" | ||
3721 | else | ||
3722 | SameLine! | ||
3723 | allClear! if Button "Home", Vec2(70,30) | ||
3724 | currentIndex = 1 | ||
3725 | for i,name in ipairs allNames | ||
3726 | if currentEntryName == name | ||
3727 | currentIndex = i | ||
3728 | SameLine! | ||
3729 | if currentIndex > 1 | ||
3730 | if Button("Prev", Vec2(70,30)) or left | ||
3731 | allClear! | ||
3732 | isInEntry = false | ||
3733 | thread -> enterDemoEntry allNames[currentIndex-1] | ||
3734 | else Dummy Vec2 70,30 | ||
3735 | SameLine! | ||
3736 | if currentIndex < #allNames | ||
3737 | if Button("Next", Vec2(70,30)) or right | ||
3738 | allClear! | ||
3739 | isInEntry = false | ||
3740 | thread -> enterDemoEntry allNames[currentIndex+1] | ||
3741 | else Dummy Vec2 70,30 | ||
3742 | if showStats | ||
3743 | SetNextWindowPos Vec2(0,height-65-296), "FirstUseEver" | ||
3744 | ShowStats! | ||
3745 | if showLog | ||
3746 | SetNextWindowPos Vec2(width-400,height-65-300), "FirstUseEver" | ||
3747 | ShowLog! | ||
3748 | |||
3749 | threadLoop -> | ||
3750 | return unless showEntry | ||
3751 | return unless isInEntry | ||
3752 | {:width,:height} = App.visualSize | ||
3753 | SetNextWindowPos Vec2.zero | ||
3754 | SetNextWindowSize Vec2(width,53) | ||
3755 | PushStyleColor "TitleBgActive", Color(0xcc000000), -> | ||
3756 | Begin "Dorothy Dev", "NoResize|NoMove|NoCollapse|NoBringToFrontOnFocus|NoSavedSettings", -> | ||
3757 | Separator! | ||
3758 | SetNextWindowPos Vec2(0,53) | ||
3759 | SetNextWindowSize Vec2(width,height-107) | ||
3760 | PushStyleColor "WindowBg",Color(0x0), -> | ||
3761 | Begin "Content", "NoTitleBar|NoResize|NoMove|NoCollapse|NoBringToFrontOnFocus|NoSavedSettings", -> | ||
3762 | TextColored Color(0xff00ffff), "Game Demos" | ||
3763 | Columns math.max(math.floor(width/200),1), false | ||
3764 | for game in *games | ||
3765 | if Button game, Vec2(-1,40) | ||
3766 | enterDemoEntry "Game/#{game}/init" | ||
3767 | NextColumn! | ||
3768 | Columns 1, false | ||
3769 | TextColored Color(0xff00ffff), "Examples" | ||
3770 | Columns math.max(math.floor(width/200),1), false | ||
3771 | for example in *examples | ||
3772 | if Button example, Vec2(-1,40) | ||
3773 | enterDemoEntry "Example/#{example}" | ||
3774 | NextColumn! | ||
3775 | Columns 1, false | ||
3776 | TextColored Color(0xff00ffff), "Tests" | ||
3777 | Columns math.max(math.floor(width/200),1), false | ||
3778 | for test in *tests | ||
3779 | if Button test, Vec2(-1,40) | ||
3780 | enterDemoEntry "Test/#{test}" | ||
3781 | NextColumn! | ||
3396 | )TestCodesHere"; | 3782 | )TestCodesHere"; |
3397 | MoonCompliler{}.complile(s); | 3783 | MoonCompliler{}.complile(s); |
3398 | return 0; | 3784 | return 0; |
diff --git a/MoonParser/moon_ast.h b/MoonParser/moon_ast.h index d4ade53..795c0c8 100644 --- a/MoonParser/moon_ast.h +++ b/MoonParser/moon_ast.h | |||
@@ -477,11 +477,9 @@ AST_LEAF(BreakLoop, "BreakLoop"_id) | |||
477 | AST_END(BreakLoop) | 477 | AST_END(BreakLoop) |
478 | 478 | ||
479 | AST_NODE(Statement, "Statement"_id) | 479 | AST_NODE(Statement, "Statement"_id) |
480 | ast_ptr<ast_node> content; /* | 480 | ast_sel<Import_t, While_t, For_t, ForEach_t, |
481 | Import_t | While_t | With_t | For_t | ForEach_t | | 481 | Return_t, Local_t, Export_t, BreakLoop_t, |
482 | Return_t | Local_t | Export_t | BreakLoop_t | | 482 | Assignment_t, ExpList_t> content; |
483 | Assignment_t | ExpList_t | ||
484 | */ | ||
485 | ast_ptr<statement_appendix_t, true> appendix; | 483 | ast_ptr<statement_appendix_t, true> appendix; |
486 | AST_END(Statement) | 484 | AST_END(Statement) |
487 | 485 | ||
diff --git a/MoonParser/moon_parser.cpp b/MoonParser/moon_parser.cpp index ad86020..d709e29 100644 --- a/MoonParser/moon_parser.cpp +++ b/MoonParser/moon_parser.cpp | |||
@@ -15,7 +15,8 @@ std::unordered_set<std::string> State::keywords = { | |||
15 | "repeat", "return", "then", "true", "until", | 15 | "repeat", "return", "then", "true", "until", |
16 | "while", // Lua keywords | 16 | "while", // Lua keywords |
17 | "class", "continue", "export", "extends", | 17 | "class", "continue", "export", "extends", |
18 | "import", "switch", "unless", "using", "with" // Moon keywords | 18 | "import", "switch", "when", "unless", "using", |
19 | "with" // Moon keywords | ||
19 | }; | 20 | }; |
20 | 21 | ||
21 | rule plain_space = *set(" \t"); | 22 | rule plain_space = *set(" \t"); |
@@ -487,7 +488,7 @@ rule unless_line = key("unless") >> Exp; | |||
487 | rule statement_appendix = (if_else_line | unless_line | CompInner) >> Space; | 488 | rule statement_appendix = (if_else_line | unless_line | CompInner) >> Space; |
488 | rule Statement = | 489 | rule Statement = |
489 | ( | 490 | ( |
490 | Import | While | With | For | ForEach | | 491 | Import | While | For | ForEach | |
491 | Return | Local | Export | Space >> BreakLoop | | 492 | Return | Local | Export | Space >> BreakLoop | |
492 | Assignment | ExpList | 493 | Assignment | ExpList |
493 | ) >> Space >> | 494 | ) >> Space >> |