diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/yuescript/yue_ast.cpp | 10 | ||||
| -rw-r--r-- | src/yuescript/yue_ast.h | 6 | ||||
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 141 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.cpp | 69 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.h | 11 |
5 files changed, 183 insertions, 54 deletions
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp index 83e5985..9d68161 100644 --- a/src/yuescript/yue_ast.cpp +++ b/src/yuescript/yue_ast.cpp | |||
| @@ -527,10 +527,10 @@ std::string While_t::to_string(void* ud) const { | |||
| 527 | } | 527 | } |
| 528 | std::string Repeat_t::to_string(void* ud) const { | 528 | std::string Repeat_t::to_string(void* ud) const { |
| 529 | auto info = reinterpret_cast<YueFormat*>(ud); | 529 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 530 | str_list temp; | 530 | if (body.is<Statement_t>()) { |
| 531 | if (body->content.is<Statement_t>()) { | 531 | return "repeat "s + body->to_string(ud) + " until "s + condition->to_string(ud); |
| 532 | temp.emplace_back("repeat "s + body->to_string(ud)); | ||
| 533 | } else { | 532 | } else { |
| 533 | str_list temp; | ||
| 534 | temp.emplace_back("repeat"s); | 534 | temp.emplace_back("repeat"s); |
| 535 | info->pushScope(); | 535 | info->pushScope(); |
| 536 | temp.emplace_back(body->to_string(ud)); | 536 | temp.emplace_back(body->to_string(ud)); |
| @@ -538,9 +538,9 @@ std::string Repeat_t::to_string(void* ud) const { | |||
| 538 | temp.back() = info->ind() + "--"s; | 538 | temp.back() = info->ind() + "--"s; |
| 539 | } | 539 | } |
| 540 | info->popScope(); | 540 | info->popScope(); |
| 541 | temp.emplace_back(info->ind() + "until "s + condition->to_string(ud)); | ||
| 542 | return join(temp, "\n"sv); | ||
| 541 | } | 543 | } |
| 542 | temp.emplace_back(info->ind() + "until "s + condition->to_string(ud)); | ||
| 543 | return join(temp, "\n"sv); | ||
| 544 | } | 544 | } |
| 545 | std::string ForStepValue_t::to_string(void* ud) const { | 545 | std::string ForStepValue_t::to_string(void* ud) const { |
| 546 | return value->to_string(ud); | 546 | return value->to_string(ud); |
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 946a587..d3e6368 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
| @@ -346,7 +346,7 @@ AST_NODE(While) | |||
| 346 | AST_END(While) | 346 | AST_END(While) |
| 347 | 347 | ||
| 348 | AST_NODE(Repeat) | 348 | AST_NODE(Repeat) |
| 349 | ast_ptr<true, Body_t> body; | 349 | ast_sel<true, Block_t, Statement_t> body; |
| 350 | ast_ptr<true, Exp_t> condition; | 350 | ast_ptr<true, Exp_t> condition; |
| 351 | AST_MEMBER(Repeat, &body, &condition) | 351 | AST_MEMBER(Repeat, &body, &condition) |
| 352 | AST_END(Repeat) | 352 | AST_END(Repeat) |
| @@ -550,8 +550,8 @@ AST_NODE(SimpleValue) | |||
| 550 | ast_sel<true, | 550 | ast_sel<true, |
| 551 | TableLit_t, ConstValue_t, | 551 | TableLit_t, ConstValue_t, |
| 552 | If_t, Switch_t, With_t, ClassDecl_t, | 552 | If_t, Switch_t, With_t, ClassDecl_t, |
| 553 | ForEach_t, For_t, While_t, Do_t, Try_t, | 553 | ForEach_t, For_t, While_t, Repeat_t, |
| 554 | UnaryValue_t, | 554 | Do_t, Try_t, UnaryValue_t, |
| 555 | TblComprehension_t, Comprehension_t, | 555 | TblComprehension_t, Comprehension_t, |
| 556 | FunLit_t, Num_t, VarArg_t> value; | 556 | FunLit_t, Num_t, VarArg_t> value; |
| 557 | AST_MEMBER(SimpleValue, &value) | 557 | AST_MEMBER(SimpleValue, &value) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 9d2037f..2312025 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -78,7 +78,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
| 78 | "close"s // Lua 5.4 | 78 | "close"s // Lua 5.4 |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | const std::string_view version = "0.28.4"sv; | 81 | const std::string_view version = "0.28.5"sv; |
| 82 | const std::string_view extension = "yue"sv; | 82 | const std::string_view extension = "yue"sv; |
| 83 | 83 | ||
| 84 | class CompileError : public std::logic_error { | 84 | class CompileError : public std::logic_error { |
| @@ -1846,6 +1846,7 @@ private: | |||
| 1846 | case id<ForEach_t>(): transformForEach(static_cast<ForEach_t*>(value), out); break; | 1846 | case id<ForEach_t>(): transformForEach(static_cast<ForEach_t*>(value), out); break; |
| 1847 | case id<For_t>(): transformFor(static_cast<For_t*>(value), out); break; | 1847 | case id<For_t>(): transformFor(static_cast<For_t*>(value), out); break; |
| 1848 | case id<While_t>(): transformWhile(static_cast<While_t*>(value), out); break; | 1848 | case id<While_t>(): transformWhile(static_cast<While_t*>(value), out); break; |
| 1849 | case id<Repeat_t>(): transformRepeat(static_cast<Repeat_t*>(value), out); break; | ||
| 1849 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Common); break; | 1850 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Common); break; |
| 1850 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Common); break; | 1851 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Common); break; |
| 1851 | case id<Comprehension_t>(): { | 1852 | case id<Comprehension_t>(): { |
| @@ -2400,6 +2401,13 @@ private: | |||
| 2400 | out.back().insert(0, preDefine); | 2401 | out.back().insert(0, preDefine); |
| 2401 | return false; | 2402 | return false; |
| 2402 | } | 2403 | } |
| 2404 | case id<Repeat_t>(): { | ||
| 2405 | auto expList = assignment->expList.get(); | ||
| 2406 | std::string preDefine = getPreDefineLine(assignment); | ||
| 2407 | transformRepeatInPlace(static_cast<Repeat_t*>(value), out, expList); | ||
| 2408 | out.back().insert(0, preDefine); | ||
| 2409 | return false; | ||
| 2410 | } | ||
| 2403 | case id<TableLit_t>(): { | 2411 | case id<TableLit_t>(): { |
| 2404 | auto tableLit = static_cast<TableLit_t*>(value); | 2412 | auto tableLit = static_cast<TableLit_t*>(value); |
| 2405 | if (hasSpreadExp(tableLit->values.objects())) { | 2413 | if (hasSpreadExp(tableLit->values.objects())) { |
| @@ -4471,6 +4479,7 @@ private: | |||
| 4471 | case id<ForEach_t>(): transformForEachClosure(static_cast<ForEach_t*>(value), out); break; | 4479 | case id<ForEach_t>(): transformForEachClosure(static_cast<ForEach_t*>(value), out); break; |
| 4472 | case id<For_t>(): transformForClosure(static_cast<For_t*>(value), out); break; | 4480 | case id<For_t>(): transformForClosure(static_cast<For_t*>(value), out); break; |
| 4473 | case id<While_t>(): transformWhileClosure(static_cast<While_t*>(value), out); break; | 4481 | case id<While_t>(): transformWhileClosure(static_cast<While_t*>(value), out); break; |
| 4482 | case id<Repeat_t>(): transformRepeatClosure(static_cast<Repeat_t*>(value), out); break; | ||
| 4474 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Closure); break; | 4483 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Closure); break; |
| 4475 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Closure); break; | 4484 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Closure); break; |
| 4476 | case id<UnaryValue_t>(): transformUnaryValue(static_cast<UnaryValue_t*>(value), out); break; | 4485 | case id<UnaryValue_t>(): transformUnaryValue(static_cast<UnaryValue_t*>(value), out); break; |
| @@ -5445,6 +5454,9 @@ private: | |||
| 5445 | case id<While_t>(): | 5454 | case id<While_t>(): |
| 5446 | transformWhileInPlace(static_cast<While_t*>(value), out); | 5455 | transformWhileInPlace(static_cast<While_t*>(value), out); |
| 5447 | return; | 5456 | return; |
| 5457 | case id<Repeat_t>(): | ||
| 5458 | transformRepeatInPlace(static_cast<Repeat_t*>(value), out); | ||
| 5459 | return; | ||
| 5448 | case id<For_t>(): | 5460 | case id<For_t>(): |
| 5449 | transformForInPlace(static_cast<For_t*>(value), out); | 5461 | transformForInPlace(static_cast<For_t*>(value), out); |
| 5450 | return; | 5462 | return; |
| @@ -8386,7 +8398,7 @@ private: | |||
| 8386 | std::string transformRepeatBody(Repeat_t* repeatNode, str_list& out) { | 8398 | std::string transformRepeatBody(Repeat_t* repeatNode, str_list& out) { |
| 8387 | str_list temp; | 8399 | str_list temp; |
| 8388 | bool extraDo = false; | 8400 | bool extraDo = false; |
| 8389 | auto body = repeatNode->body->content.get(); | 8401 | auto body = repeatNode->body.get(); |
| 8390 | auto breakLoopType = getBreakLoopType(body, Empty); | 8402 | auto breakLoopType = getBreakLoopType(body, Empty); |
| 8391 | bool withContinue = hasContinue(breakLoopType); | 8403 | bool withContinue = hasContinue(breakLoopType); |
| 8392 | std::string conditionVar; | 8404 | std::string conditionVar; |
| @@ -9513,22 +9525,19 @@ private: | |||
| 9513 | expListAssign->expList.set(expList); | 9525 | expListAssign->expList.set(expList); |
| 9514 | auto stmt = x->new_ptr<Statement_t>(); | 9526 | auto stmt = x->new_ptr<Statement_t>(); |
| 9515 | stmt->content.set(expListAssign); | 9527 | stmt->content.set(expListAssign); |
| 9516 | auto whileNode = toAst<While_t>("while true do break"s, x); | 9528 | auto repeatNode = toAst<Repeat_t>("repeat\n\t--\nuntil true"s, x); |
| 9517 | auto block = x->new_ptr<Block_t>(); | 9529 | auto block = x->new_ptr<Block_t>(); |
| 9518 | block->statements.push_back(stmt); | 9530 | block->statements.push_back(stmt); |
| 9519 | block->statements.push_back(whileNode->body); | 9531 | repeatNode->body.set(block); |
| 9520 | auto body = x->new_ptr<Body_t>(); | ||
| 9521 | body->content.set(block); | ||
| 9522 | whileNode->body.set(block); | ||
| 9523 | auto sVal = x->new_ptr<SimpleValue_t>(); | 9532 | auto sVal = x->new_ptr<SimpleValue_t>(); |
| 9524 | sVal->value.set(whileNode); | 9533 | sVal->value.set(repeatNode); |
| 9525 | auto asmt = assignmentFrom(toAst<Exp_t>(breakWithVar, x), newExp(sVal, x), x); | 9534 | auto asmt = assignmentFrom(toAst<Exp_t>(breakWithVar, x), newExp(sVal, x), x); |
| 9526 | transformAssignment(asmt, temp); | 9535 | transformAssignment(asmt, temp); |
| 9527 | } | 9536 | } |
| 9528 | } else { | 9537 | } else { |
| 9529 | bool transformed = false; | 9538 | bool transformed = false; |
| 9530 | if (!breakWithVar.empty()) { | 9539 | if (!breakWithVar.empty()) { |
| 9531 | auto whileNode = toAst<While_t>("while true do break"s, x); | 9540 | auto repeatNode = toAst<Repeat_t>("repeat\n\t--\nuntil true"s, x); |
| 9532 | auto block = x->new_ptr<Block_t>(); | 9541 | auto block = x->new_ptr<Block_t>(); |
| 9533 | if (auto blk = with->body.as<Block_t>()) { | 9542 | if (auto blk = with->body.as<Block_t>()) { |
| 9534 | block->statements.dup(blk->statements); | 9543 | block->statements.dup(blk->statements); |
| @@ -9536,15 +9545,9 @@ private: | |||
| 9536 | auto stmt = with->body.to<Statement_t>(); | 9545 | auto stmt = with->body.to<Statement_t>(); |
| 9537 | block->statements.push_back(stmt); | 9546 | block->statements.push_back(stmt); |
| 9538 | } | 9547 | } |
| 9539 | auto breakLoop = whileNode->body.to<Statement_t>()->content.as<BreakLoop_t>(); | 9548 | repeatNode->body.set(block); |
| 9540 | if (!(breakLoop && breakLoop->type.is<Break_t>())) { | ||
| 9541 | block->statements.push_back(whileNode->body); | ||
| 9542 | } | ||
| 9543 | auto body = x->new_ptr<Body_t>(); | ||
| 9544 | body->content.set(block); | ||
| 9545 | whileNode->body.set(block); | ||
| 9546 | auto sVal = x->new_ptr<SimpleValue_t>(); | 9549 | auto sVal = x->new_ptr<SimpleValue_t>(); |
| 9547 | sVal->value.set(whileNode); | 9550 | sVal->value.set(repeatNode); |
| 9548 | auto asmt = assignmentFrom(toAst<Exp_t>(breakWithVar, x), newExp(sVal, x), x); | 9551 | auto asmt = assignmentFrom(toAst<Exp_t>(breakWithVar, x), newExp(sVal, x), x); |
| 9549 | transformAssignment(asmt, temp); | 9552 | transformAssignment(asmt, temp); |
| 9550 | transformed = true; | 9553 | transformed = true; |
| @@ -10708,9 +10711,7 @@ private: | |||
| 10708 | expListAssign->expList.set(expList); | 10711 | expListAssign->expList.set(expList); |
| 10709 | auto stmt = x->new_ptr<Statement_t>(); | 10712 | auto stmt = x->new_ptr<Statement_t>(); |
| 10710 | stmt->content.set(expListAssign); | 10713 | stmt->content.set(expListAssign); |
| 10711 | auto body = x->new_ptr<Body_t>(); | 10714 | repeat->body.set(stmt); |
| 10712 | body->content.set(stmt); | ||
| 10713 | repeat->body.set(body); | ||
| 10714 | transformRepeat(repeat, out); | 10715 | transformRepeat(repeat, out); |
| 10715 | return; | 10716 | return; |
| 10716 | } | 10717 | } |
| @@ -10727,6 +10728,106 @@ private: | |||
| 10727 | out.push_back(clearBuf()); | 10728 | out.push_back(clearBuf()); |
| 10728 | } | 10729 | } |
| 10729 | 10730 | ||
| 10731 | void transformRepeatInPlace(Repeat_t* repeatNode, str_list& out, ExpList_t* expList = nullptr) { | ||
| 10732 | auto x = repeatNode; | ||
| 10733 | str_list temp; | ||
| 10734 | bool extraScope = false; | ||
| 10735 | if (expList) { | ||
| 10736 | if (!currentScope().lastStatement) { | ||
| 10737 | extraScope = true; | ||
| 10738 | temp.push_back(indent() + "do"s + nll(repeatNode)); | ||
| 10739 | pushScope(); | ||
| 10740 | } | ||
| 10741 | } | ||
| 10742 | auto accumVar = getUnusedName("_accum_"sv); | ||
| 10743 | addToScope(accumVar); | ||
| 10744 | auto lenVar = getUnusedName("_len_"sv); | ||
| 10745 | addToScope(lenVar); | ||
| 10746 | auto breakLoopType = getBreakLoopType(repeatNode->body, accumVar); | ||
| 10747 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(repeatNode); | ||
| 10748 | temp.emplace_back(clearBuf()); | ||
| 10749 | _buf << indent() << "local "s << lenVar << " = 1"s << nll(repeatNode); | ||
| 10750 | auto& lenAssign = temp.emplace_back(clearBuf()); | ||
| 10751 | auto condStr = transformCondExp(repeatNode->condition, false); | ||
| 10752 | temp.push_back(indent() + "repeat"s + nll(repeatNode)); | ||
| 10753 | pushScope(); | ||
| 10754 | if (hasBreakWithValue(breakLoopType)) { | ||
| 10755 | lenAssign.clear(); | ||
| 10756 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Common); | ||
| 10757 | } else { | ||
| 10758 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
| 10759 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, repeatNode); | ||
| 10760 | assignLeft->followStmt = followStmt.get(); | ||
| 10761 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
| 10762 | if (!assignLeft->followStmtProcessed) { | ||
| 10763 | lenAssign.clear(); | ||
| 10764 | } | ||
| 10765 | } | ||
| 10766 | popScope(); | ||
| 10767 | temp.push_back(indent() + "until "s + condStr + nlr(repeatNode)); | ||
| 10768 | if (expList) { | ||
| 10769 | auto assign = x->new_ptr<Assign_t>(); | ||
| 10770 | assign->values.push_back(toAst<Exp_t>(accumVar, x)); | ||
| 10771 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 10772 | assignment->expList.set(expList); | ||
| 10773 | assignment->action.set(assign); | ||
| 10774 | transformAssignment(assignment, temp); | ||
| 10775 | if (extraScope) popScope(); | ||
| 10776 | } else { | ||
| 10777 | temp.push_back(indent() + "return "s + accumVar + nlr(repeatNode)); | ||
| 10778 | } | ||
| 10779 | if (expList && extraScope) { | ||
| 10780 | temp.push_back(indent() + "end"s + nlr(repeatNode)); | ||
| 10781 | } | ||
| 10782 | out.push_back(join(temp)); | ||
| 10783 | } | ||
| 10784 | |||
| 10785 | void transformRepeatClosure(Repeat_t* repeatNode, str_list& out) { | ||
| 10786 | auto x = repeatNode; | ||
| 10787 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
| 10788 | simpleValue->value.set(repeatNode); | ||
| 10789 | if (transformAsUpValueFunc(newExp(simpleValue, x), out)) { | ||
| 10790 | return; | ||
| 10791 | } | ||
| 10792 | str_list temp; | ||
| 10793 | pushAnonFunctionScope(); | ||
| 10794 | pushAnonVarArg(); | ||
| 10795 | std::string& funcStart = temp.emplace_back(); | ||
| 10796 | pushScope(); | ||
| 10797 | auto accumVar = getUnusedName("_accum_"sv); | ||
| 10798 | addToScope(accumVar); | ||
| 10799 | auto lenVar = getUnusedName("_len_"sv); | ||
| 10800 | addToScope(lenVar); | ||
| 10801 | auto breakLoopType = getBreakLoopType(repeatNode->body, accumVar); | ||
| 10802 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(repeatNode); | ||
| 10803 | temp.emplace_back(clearBuf()); | ||
| 10804 | auto& lenAssign = temp.emplace_back(indent() + "local "s + lenVar + " = 1"s + nll(repeatNode)); | ||
| 10805 | auto condStr = transformCondExp(repeatNode->condition, false); | ||
| 10806 | temp.push_back(indent() + "repeat"s + nll(repeatNode)); | ||
| 10807 | pushScope(); | ||
| 10808 | if (hasBreakWithValue(breakLoopType)) { | ||
| 10809 | lenAssign.clear(); | ||
| 10810 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Common); | ||
| 10811 | } else { | ||
| 10812 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
| 10813 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, repeatNode); | ||
| 10814 | assignLeft->followStmt = followStmt.get(); | ||
| 10815 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
| 10816 | if (!assignLeft->followStmtProcessed) { | ||
| 10817 | lenAssign.clear(); | ||
| 10818 | } | ||
| 10819 | } | ||
| 10820 | popScope(); | ||
| 10821 | temp.push_back(indent() + "until "s + condStr + nlr(repeatNode)); | ||
| 10822 | temp.push_back(indent() + "return "s + accumVar + nlr(repeatNode)); | ||
| 10823 | popScope(); | ||
| 10824 | funcStart = anonFuncStart() + nll(repeatNode); | ||
| 10825 | temp.push_back(indent() + anonFuncEnd()); | ||
| 10826 | popAnonVarArg(); | ||
| 10827 | popFunctionScope(); | ||
| 10828 | out.push_back(join(temp)); | ||
| 10829 | } | ||
| 10830 | |||
| 10730 | void transformRepeat(Repeat_t* repeat, str_list& out) { | 10831 | void transformRepeat(Repeat_t* repeat, str_list& out) { |
| 10731 | str_list temp; | 10832 | str_list temp; |
| 10732 | pushScope(); | 10833 | pushScope(); |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 0271e07..e5bdc26 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -162,6 +162,13 @@ YueParser::YueParser() { | |||
| 162 | ) \ | 162 | ) \ |
| 163 | ) | 163 | ) |
| 164 | 164 | ||
| 165 | #define disable_until_rule(patt) ( \ | ||
| 166 | disable_until >> ( \ | ||
| 167 | (patt) >> enable_until | \ | ||
| 168 | enable_until >> cut \ | ||
| 169 | ) \ | ||
| 170 | ) | ||
| 171 | |||
| 165 | #define body_with(str) ( \ | 172 | #define body_with(str) ( \ |
| 166 | key(str) >> space >> (in_block | Statement) | \ | 173 | key(str) >> space >> (in_block | Statement) | \ |
| 167 | in_block | \ | 174 | in_block | \ |
| @@ -389,13 +396,19 @@ YueParser::YueParser() { | |||
| 389 | IfType = (expr("if") | "unless") >> not_alpha_num; | 396 | IfType = (expr("if") | "unless") >> not_alpha_num; |
| 390 | If = IfType >> space >> IfCond >> space >> opt_body_with("then") >> *if_else_if >> -if_else; | 397 | If = IfType >> space >> IfCond >> space >> opt_body_with("then") >> *if_else_if >> -if_else; |
| 391 | 398 | ||
| 392 | WhileType = (expr("while") | "until") >> not_alpha_num; | 399 | WhileType = (expr("while") | pl::user("until", [](const item_t& item) { |
| 393 | While = WhileType >> space >> disable_do_chain_arg_table_block_rule(Exp >> -(space >> Assignment)) >> space >> opt_body_with("do"); | 400 | State* st = reinterpret_cast<State*>(item.user_data); |
| 394 | Repeat = key("repeat") >> space >> Body >> line_break >> *space_break >> check_indent_match >> space >> key("until") >> space >> Exp; | 401 | return st->noUntilStack.empty() || !st->noUntilStack.back(); |
| 402 | })) >> not_alpha_num; | ||
| 403 | While = key(WhileType) >> space >> disable_do_chain_arg_table_block_rule(Exp >> -(space >> Assignment)) >> space >> opt_body_with("do"); | ||
| 404 | Repeat = key("repeat") >> space >> ( | ||
| 405 | in_block >> line_break >> *space_break >> check_indent_match | | ||
| 406 | disable_until_rule(Statement) | ||
| 407 | ) >> space >> key("until") >> space >> Exp; | ||
| 395 | 408 | ||
| 396 | for_key = pl::user(key("for"), [](const item_t& item) { | 409 | for_key = pl::user(key("for"), [](const item_t& item) { |
| 397 | State* st = reinterpret_cast<State*>(item.user_data); | 410 | State* st = reinterpret_cast<State*>(item.user_data); |
| 398 | return st->noForStack.empty() || !st->noForStack.top(); | 411 | return st->noForStack.empty() || !st->noForStack.back(); |
| 399 | }); | 412 | }); |
| 400 | ForStepValue = ',' >> space >> Exp; | 413 | ForStepValue = ',' >> space >> Exp; |
| 401 | for_args = Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> space >> -ForStepValue; | 414 | for_args = Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> space >> -ForStepValue; |
| @@ -409,18 +422,18 @@ YueParser::YueParser() { | |||
| 409 | 422 | ||
| 410 | Do = pl::user(key("do"), [](const item_t& item) { | 423 | Do = pl::user(key("do"), [](const item_t& item) { |
| 411 | State* st = reinterpret_cast<State*>(item.user_data); | 424 | State* st = reinterpret_cast<State*>(item.user_data); |
| 412 | return st->noDoStack.empty() || !st->noDoStack.top(); | 425 | return st->noDoStack.empty() || !st->noDoStack.back(); |
| 413 | }) >> space >> Body; | 426 | }) >> space >> Body; |
| 414 | 427 | ||
| 415 | disable_do = pl::user(true_(), [](const item_t& item) { | 428 | disable_do = pl::user(true_(), [](const item_t& item) { |
| 416 | State* st = reinterpret_cast<State*>(item.user_data); | 429 | State* st = reinterpret_cast<State*>(item.user_data); |
| 417 | st->noDoStack.push(true); | 430 | st->noDoStack.push_back(true); |
| 418 | return true; | 431 | return true; |
| 419 | }); | 432 | }); |
| 420 | 433 | ||
| 421 | enable_do = pl::user(true_(), [](const item_t& item) { | 434 | enable_do = pl::user(true_(), [](const item_t& item) { |
| 422 | State* st = reinterpret_cast<State*>(item.user_data); | 435 | State* st = reinterpret_cast<State*>(item.user_data); |
| 423 | st->noDoStack.pop(); | 436 | st->noDoStack.pop_back(); |
| 424 | return true; | 437 | return true; |
| 425 | }); | 438 | }); |
| 426 | 439 | ||
| @@ -438,41 +451,53 @@ YueParser::YueParser() { | |||
| 438 | 451 | ||
| 439 | disable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { | 452 | disable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { |
| 440 | State* st = reinterpret_cast<State*>(item.user_data); | 453 | State* st = reinterpret_cast<State*>(item.user_data); |
| 441 | st->noDoStack.push(true); | 454 | st->noDoStack.push_back(true); |
| 442 | st->noChainBlockStack.push(true); | 455 | st->noChainBlockStack.push_back(true); |
| 443 | st->noTableBlockStack.push(true); | 456 | st->noTableBlockStack.push_back(true); |
| 444 | return true; | 457 | return true; |
| 445 | }); | 458 | }); |
| 446 | 459 | ||
| 447 | enable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { | 460 | enable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { |
| 448 | State* st = reinterpret_cast<State*>(item.user_data); | 461 | State* st = reinterpret_cast<State*>(item.user_data); |
| 449 | st->noDoStack.pop(); | 462 | st->noDoStack.pop_back(); |
| 450 | st->noChainBlockStack.pop(); | 463 | st->noChainBlockStack.pop_back(); |
| 451 | st->noTableBlockStack.pop(); | 464 | st->noTableBlockStack.pop_back(); |
| 452 | return true; | 465 | return true; |
| 453 | }); | 466 | }); |
| 454 | 467 | ||
| 455 | disable_arg_table_block = pl::user(true_(), [](const item_t& item) { | 468 | disable_arg_table_block = pl::user(true_(), [](const item_t& item) { |
| 456 | State* st = reinterpret_cast<State*>(item.user_data); | 469 | State* st = reinterpret_cast<State*>(item.user_data); |
| 457 | st->noTableBlockStack.push(true); | 470 | st->noTableBlockStack.push_back(true); |
| 458 | return true; | 471 | return true; |
| 459 | }); | 472 | }); |
| 460 | 473 | ||
| 461 | enable_arg_table_block = pl::user(true_(), [](const item_t& item) { | 474 | enable_arg_table_block = pl::user(true_(), [](const item_t& item) { |
| 462 | State* st = reinterpret_cast<State*>(item.user_data); | 475 | State* st = reinterpret_cast<State*>(item.user_data); |
| 463 | st->noTableBlockStack.pop(); | 476 | st->noTableBlockStack.pop_back(); |
| 464 | return true; | 477 | return true; |
| 465 | }); | 478 | }); |
| 466 | 479 | ||
| 467 | disable_for = pl::user(true_(), [](const item_t& item) { | 480 | disable_for = pl::user(true_(), [](const item_t& item) { |
| 468 | State* st = reinterpret_cast<State*>(item.user_data); | 481 | State* st = reinterpret_cast<State*>(item.user_data); |
| 469 | st->noForStack.push(true); | 482 | st->noForStack.push_back(true); |
| 470 | return true; | 483 | return true; |
| 471 | }); | 484 | }); |
| 472 | 485 | ||
| 473 | enable_for = pl::user(true_(), [](const item_t& item) { | 486 | enable_for = pl::user(true_(), [](const item_t& item) { |
| 474 | State* st = reinterpret_cast<State*>(item.user_data); | 487 | State* st = reinterpret_cast<State*>(item.user_data); |
| 475 | st->noForStack.pop(); | 488 | st->noForStack.pop_back(); |
| 489 | return true; | ||
| 490 | }); | ||
| 491 | |||
| 492 | disable_until = pl::user(true_(), [](const item_t& item) { | ||
| 493 | State* st = reinterpret_cast<State*>(item.user_data); | ||
| 494 | st->noUntilStack.push_back(true); | ||
| 495 | return true; | ||
| 496 | }); | ||
| 497 | |||
| 498 | enable_until = pl::user(true_(), [](const item_t& item) { | ||
| 499 | State* st = reinterpret_cast<State*>(item.user_data); | ||
| 500 | st->noUntilStack.pop_back(); | ||
| 476 | return true; | 501 | return true; |
| 477 | }); | 502 | }); |
| 478 | 503 | ||
| @@ -564,20 +589,20 @@ YueParser::YueParser() { | |||
| 564 | 589 | ||
| 565 | disable_chain = pl::user(true_(), [](const item_t& item) { | 590 | disable_chain = pl::user(true_(), [](const item_t& item) { |
| 566 | State* st = reinterpret_cast<State*>(item.user_data); | 591 | State* st = reinterpret_cast<State*>(item.user_data); |
| 567 | st->noChainBlockStack.push(true); | 592 | st->noChainBlockStack.push_back(true); |
| 568 | return true; | 593 | return true; |
| 569 | }); | 594 | }); |
| 570 | 595 | ||
| 571 | enable_chain = pl::user(true_(), [](const item_t& item) { | 596 | enable_chain = pl::user(true_(), [](const item_t& item) { |
| 572 | State* st = reinterpret_cast<State*>(item.user_data); | 597 | State* st = reinterpret_cast<State*>(item.user_data); |
| 573 | st->noChainBlockStack.pop(); | 598 | st->noChainBlockStack.pop_back(); |
| 574 | return true; | 599 | return true; |
| 575 | }); | 600 | }); |
| 576 | 601 | ||
| 577 | chain_line = check_indent_match >> space >> (chain_dot_chain | colon_chain) >> -InvokeArgs; | 602 | chain_line = check_indent_match >> space >> (chain_dot_chain | colon_chain) >> -InvokeArgs; |
| 578 | chain_block = pl::user(true_(), [](const item_t& item) { | 603 | chain_block = pl::user(true_(), [](const item_t& item) { |
| 579 | State* st = reinterpret_cast<State*>(item.user_data); | 604 | State* st = reinterpret_cast<State*>(item.user_data); |
| 580 | return st->noChainBlockStack.empty() || !st->noChainBlockStack.top(); | 605 | return st->noChainBlockStack.empty() || !st->noChainBlockStack.back(); |
| 581 | }) >> +space_break >> advance_match >> ensure( | 606 | }) >> +space_break >> advance_match >> ensure( |
| 582 | chain_line >> *(+space_break >> chain_line), pop_indent); | 607 | chain_line >> *(+space_break >> chain_line), pop_indent); |
| 583 | ChainValue = | 608 | ChainValue = |
| @@ -904,7 +929,7 @@ YueParser::YueParser() { | |||
| 904 | 929 | ||
| 905 | arg_table_block = pl::user(true_(), [](const item_t& item) { | 930 | arg_table_block = pl::user(true_(), [](const item_t& item) { |
| 906 | State* st = reinterpret_cast<State*>(item.user_data); | 931 | State* st = reinterpret_cast<State*>(item.user_data); |
| 907 | return st->noTableBlockStack.empty() || !st->noTableBlockStack.top(); | 932 | return st->noTableBlockStack.empty() || !st->noTableBlockStack.back(); |
| 908 | }) >> TableBlock; | 933 | }) >> TableBlock; |
| 909 | 934 | ||
| 910 | invoke_args_with_table = | 935 | invoke_args_with_table = |
| @@ -944,7 +969,7 @@ YueParser::YueParser() { | |||
| 944 | 969 | ||
| 945 | SimpleValue = | 970 | SimpleValue = |
| 946 | TableLit | ConstValue | If | Switch | Try | With | | 971 | TableLit | ConstValue | If | Switch | Try | With | |
| 947 | ClassDecl | ForEach | For | While | Do | | 972 | ClassDecl | ForEach | For | While | Repeat | Do | |
| 948 | UnaryValue | TblComprehension | Comprehension | | 973 | UnaryValue | TblComprehension | Comprehension | |
| 949 | FunLit | Num | VarArg; | 974 | FunLit | Num | VarArg; |
| 950 | 975 | ||
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 6263857..773bdbe 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
| @@ -119,10 +119,11 @@ protected: | |||
| 119 | size_t stringOpen = 0; | 119 | size_t stringOpen = 0; |
| 120 | std::string buffer; | 120 | std::string buffer; |
| 121 | std::stack<int> indents; | 121 | std::stack<int> indents; |
| 122 | std::stack<bool> noDoStack; | 122 | std::vector<bool> noDoStack; |
| 123 | std::stack<bool> noChainBlockStack; | 123 | std::vector<bool> noChainBlockStack; |
| 124 | std::stack<bool> noTableBlockStack; | 124 | std::vector<bool> noTableBlockStack; |
| 125 | std::stack<bool> noForStack; | 125 | std::vector<bool> noForStack; |
| 126 | std::vector<bool> noUntilStack; | ||
| 126 | std::unordered_set<std::string> usedNames; | 127 | std::unordered_set<std::string> usedNames; |
| 127 | }; | 128 | }; |
| 128 | 129 | ||
| @@ -217,6 +218,8 @@ private: | |||
| 217 | NONE_AST_RULE(enable_for); | 218 | NONE_AST_RULE(enable_for); |
| 218 | NONE_AST_RULE(enable_fun_lit); | 219 | NONE_AST_RULE(enable_fun_lit); |
| 219 | NONE_AST_RULE(disable_fun_lit); | 220 | NONE_AST_RULE(disable_fun_lit); |
| 221 | NONE_AST_RULE(disable_until); | ||
| 222 | NONE_AST_RULE(enable_until); | ||
| 220 | NONE_AST_RULE(switch_else); | 223 | NONE_AST_RULE(switch_else); |
| 221 | NONE_AST_RULE(switch_block); | 224 | NONE_AST_RULE(switch_block); |
| 222 | NONE_AST_RULE(if_else_if); | 225 | NONE_AST_RULE(if_else_if); |
