aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2025-05-27 11:26:15 +0800
committerLi Jin <dragon-fly@qq.com>2025-05-27 11:26:15 +0800
commit87267ca9e93606b70bdc0397349b176b8d142514 (patch)
tree1d24aded412cc9543cbe4c282401129f9fb3229a /src
parenta9d28cb615d2bdc09d2482d5262951f2afc8d6e1 (diff)
downloadyuescript-87267ca9e93606b70bdc0397349b176b8d142514.tar.gz
yuescript-87267ca9e93606b70bdc0397349b176b8d142514.tar.bz2
yuescript-87267ca9e93606b70bdc0397349b176b8d142514.zip
Updated `repeat` syntax functions.
Diffstat (limited to 'src')
-rw-r--r--src/yuescript/yue_ast.cpp10
-rw-r--r--src/yuescript/yue_ast.h6
-rw-r--r--src/yuescript/yue_compiler.cpp141
-rw-r--r--src/yuescript/yue_parser.cpp69
-rw-r--r--src/yuescript/yue_parser.h11
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}
528std::string Repeat_t::to_string(void* ud) const { 528std::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}
545std::string ForStepValue_t::to_string(void* ud) const { 545std::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)
346AST_END(While) 346AST_END(While)
347 347
348AST_NODE(Repeat) 348AST_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)
352AST_END(Repeat) 352AST_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
81const std::string_view version = "0.28.4"sv; 81const std::string_view version = "0.28.5"sv;
82const std::string_view extension = "yue"sv; 82const std::string_view extension = "yue"sv;
83 83
84class CompileError : public std::logic_error { 84class 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);