aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/yuescript/yue_ast.cpp6
-rw-r--r--src/yuescript/yue_ast.h7
-rw-r--r--src/yuescript/yue_compiler.cpp248
-rw-r--r--src/yuescript/yue_parser.cpp3
-rw-r--r--src/yuescript/yue_parser.h1
5 files changed, 232 insertions, 33 deletions
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp
index c4f133b..da99d07 100644
--- a/src/yuescript/yue_ast.cpp
+++ b/src/yuescript/yue_ast.cpp
@@ -870,6 +870,12 @@ std::string Exp_t::to_string(void* ud) const {
870 } 870 }
871 return join(temp, " "sv); 871 return join(temp, " "sv);
872} 872}
873std::string ReversedIndex_t::to_string(void* ud) const {
874 if (modifier) {
875 return "[# - "s + modifier->to_string(ud) + ']';
876 }
877 return "[#]"s;
878}
873std::string Callable_t::to_string(void* ud) const { 879std::string Callable_t::to_string(void* ud) const {
874 return item->to_string(ud); 880 return item->to_string(ud);
875} 881}
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index 6bdc31b..d396d82 100644
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -643,9 +643,14 @@ AST_END(TableAppendingOp)
643AST_LEAF(PlainItem) 643AST_LEAF(PlainItem)
644AST_END(PlainItem) 644AST_END(PlainItem)
645 645
646AST_NODE(ReversedIndex)
647 ast_ptr<false, Exp_t> modifier;
648 AST_MEMBER(ReversedIndex, &modifier)
649AST_END(ReversedIndex)
650
646AST_NODE(ChainValue) 651AST_NODE(ChainValue)
647 ast_ptr<true, Seperator_t> sep; 652 ast_ptr<true, Seperator_t> sep;
648 ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, ExistentialOp_t, TableAppendingOp_t, 653 ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, ExistentialOp_t, TableAppendingOp_t, ReversedIndex_t,
649 /*non-syntax-rule*/ PlainItem_t> items; 654 /*non-syntax-rule*/ PlainItem_t> items;
650 AST_MEMBER(ChainValue, &sep, &items) 655 AST_MEMBER(ChainValue, &sep, &items)
651AST_END(ChainValue) 656AST_END(ChainValue)
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 4bac51b..cbf976f 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.7"sv; 81const std::string_view version = "0.29.0"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 {
@@ -1281,6 +1281,8 @@ private:
1281 Common, 1281 Common,
1282 EndWithColon, 1282 EndWithColon,
1283 EndWithEOP, 1283 EndWithEOP,
1284 EndWithSlice,
1285 HasRIndex,
1284 HasEOP, 1286 HasEOP,
1285 HasKeyword, 1287 HasKeyword,
1286 HasUnicode, 1288 HasUnicode,
@@ -1299,6 +1301,9 @@ private:
1299 if (ast_is<ExistentialOp_t>(chainValue->items.back())) { 1301 if (ast_is<ExistentialOp_t>(chainValue->items.back())) {
1300 return ChainType::EndWithEOP; 1302 return ChainType::EndWithEOP;
1301 } 1303 }
1304 if (ast_is<Slice_t>(chainValue->items.back())) {
1305 return ChainType::EndWithSlice;
1306 }
1302 if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) { 1307 if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) {
1303 if (dot->name.is<Metatable_t>()) { 1308 if (dot->name.is<Metatable_t>()) {
1304 return ChainType::Metatable; 1309 return ChainType::Metatable;
@@ -1324,6 +1329,8 @@ private:
1324 } 1329 }
1325 } else if (ast_is<ExistentialOp_t>(item)) { 1330 } else if (ast_is<ExistentialOp_t>(item)) {
1326 return ChainType::HasEOP; 1331 return ChainType::HasEOP;
1332 } else if (ast_is<ReversedIndex_t>(item)) {
1333 return ChainType::HasRIndex;
1327 } 1334 }
1328 } 1335 }
1329 return type; 1336 return type;
@@ -2471,12 +2478,14 @@ private:
2471 switch (type) { 2478 switch (type) {
2472 case ChainType::HasEOP: 2479 case ChainType::HasEOP:
2473 case ChainType::EndWithColon: 2480 case ChainType::EndWithColon:
2481 case ChainType::EndWithSlice:
2474 case ChainType::MetaFieldInvocation: { 2482 case ChainType::MetaFieldInvocation: {
2475 std::string preDefine = getPreDefineLine(assignment); 2483 std::string preDefine = getPreDefineLine(assignment);
2476 transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct); 2484 transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct);
2477 out.back().insert(0, preDefine); 2485 out.back().insert(0, preDefine);
2478 return false; 2486 return false;
2479 } 2487 }
2488 case ChainType::HasRIndex:
2480 case ChainType::HasKeyword: 2489 case ChainType::HasKeyword:
2481 case ChainType::HasUnicode: 2490 case ChainType::HasUnicode:
2482 case ChainType::Macro: 2491 case ChainType::Macro:
@@ -2832,17 +2841,19 @@ private:
2832 if (!tableItems) throw CompileError("invalid destructure value"sv, node); 2841 if (!tableItems) throw CompileError("invalid destructure value"sv, node);
2833 std::list<DestructItem> pairs; 2842 std::list<DestructItem> pairs;
2834 int index = 0; 2843 int index = 0;
2844 int count = 0;
2845 bool hasSpread = false;
2835 auto subMetaDestruct = node->new_ptr<TableLit_t>(); 2846 auto subMetaDestruct = node->new_ptr<TableLit_t>();
2836 for (auto pair : *tableItems) { 2847 for (auto pair : *tableItems) {
2837 switch (pair->get_id()) { 2848 switch (pair->get_id()) {
2838 case id<Exp_t>(): 2849 case id<Exp_t>():
2839 case id<NormalDef_t>(): { 2850 case id<NormalDef_t>(): {
2851 ++index;
2840 Exp_t* defVal = nullptr; 2852 Exp_t* defVal = nullptr;
2841 if (auto nd = ast_cast<NormalDef_t>(pair)) { 2853 if (auto nd = ast_cast<NormalDef_t>(pair)) {
2842 pair = nd->item.get(); 2854 pair = nd->item.get();
2843 defVal = nd->defVal.get(); 2855 defVal = nd->defVal.get();
2844 } 2856 }
2845 ++index;
2846 bool assignable = false; 2857 bool assignable = false;
2847 try { 2858 try {
2848 assignable = isAssignable(static_cast<Exp_t*>(pair)); 2859 assignable = isAssignable(static_cast<Exp_t*>(pair));
@@ -2853,13 +2864,19 @@ private:
2853 if (optional) break; 2864 if (optional) break;
2854 throw CompileError("can't destructure value"sv, pair); 2865 throw CompileError("can't destructure value"sv, pair);
2855 } 2866 }
2867 ast_ptr<true, ast_node> indexItem;
2868 if (hasSpread) {
2869 int rIndex = count - index;
2870 indexItem.set(toAst<ReversedIndex_t>('#' + (rIndex == 0 ? Empty : "-"s + std::to_string(rIndex)), pair));
2871 } else {
2872 indexItem.set(toAst<Exp_t>(std::to_string(index), pair));
2873 }
2856 if (optional && varDefOnly && !assignable) { 2874 if (optional && varDefOnly && !assignable) {
2857 if (defVal) { 2875 if (defVal) {
2858 throw CompileError("default value is not supported here"sv, defVal); 2876 throw CompileError("default value is not supported here"sv, defVal);
2859 } 2877 }
2860 auto exp = static_cast<Exp_t*>(pair); 2878 auto exp = static_cast<Exp_t*>(pair);
2861 auto chain = exp->new_ptr<ChainValue_t>(); 2879 auto chain = exp->new_ptr<ChainValue_t>();
2862 auto indexItem = toAst<Exp_t>(std::to_string(index), exp);
2863 chain->items.push_back(indexItem); 2880 chain->items.push_back(indexItem);
2864 pairs.push_back({exp, Empty, chain, nullptr}); 2881 pairs.push_back({exp, Empty, chain, nullptr});
2865 break; 2882 break;
@@ -2874,7 +2891,6 @@ private:
2874 throw CompileError("default value is not supported here"sv, defVal); 2891 throw CompileError("default value is not supported here"sv, defVal);
2875 } 2892 }
2876 } 2893 }
2877 auto indexItem = toAst<Exp_t>(std::to_string(index), value);
2878 for (auto& p : subPairs) { 2894 for (auto& p : subPairs) {
2879 if (sep) p.structure->items.push_front(sep); 2895 if (sep) p.structure->items.push_front(sep);
2880 p.structure->items.push_front(indexItem); 2896 p.structure->items.push_front(indexItem);
@@ -2885,7 +2901,6 @@ private:
2885 auto varName = singleVariableFrom(exp, AccessType::None); 2901 auto varName = singleVariableFrom(exp, AccessType::None);
2886 if (varName == "_"sv) break; 2902 if (varName == "_"sv) break;
2887 auto chain = exp->new_ptr<ChainValue_t>(); 2903 auto chain = exp->new_ptr<ChainValue_t>();
2888 auto indexItem = toAst<Exp_t>(std::to_string(index), exp);
2889 chain->items.push_back(indexItem); 2904 chain->items.push_back(indexItem);
2890 pairs.push_back({exp, 2905 pairs.push_back({exp,
2891 varName, 2906 varName,
@@ -3010,7 +3025,13 @@ private:
3010 auto tb = static_cast<TableBlockIndent_t*>(pair); 3025 auto tb = static_cast<TableBlockIndent_t*>(pair);
3011 ++index; 3026 ++index;
3012 auto subPairs = destructFromExp(tb, varDefOnly, optional); 3027 auto subPairs = destructFromExp(tb, varDefOnly, optional);
3013 auto indexItem = toAst<Exp_t>(std::to_string(index), tb); 3028 ast_ptr<true, ast_node> indexItem;
3029 if (hasSpread) {
3030 int rIndex = count - index;
3031 indexItem.set(toAst<ReversedIndex_t>('#' + (rIndex == 0 ? Empty : "-"s + std::to_string(rIndex)), tb));
3032 } else {
3033 indexItem.set(toAst<Exp_t>(std::to_string(index), tb));
3034 }
3014 for (auto& p : subPairs) { 3035 for (auto& p : subPairs) {
3015 if (sep) p.structure->items.push_front(sep); 3036 if (sep) p.structure->items.push_front(sep);
3016 p.structure->items.push_front(indexItem); 3037 p.structure->items.push_front(indexItem);
@@ -3067,6 +3088,42 @@ private:
3067 subMetaDestruct->values.push_back(newPairDef); 3088 subMetaDestruct->values.push_back(newPairDef);
3068 break; 3089 break;
3069 } 3090 }
3091 case id<SpreadListExp_t>():
3092 case id<SpreadExp_t>(): {
3093 ++index;
3094 if (hasSpread) {
3095 throw CompileError("duplicated spread expression"sv, pair);
3096 }
3097 hasSpread = true;
3098 for (auto item : *tableItems) {
3099 if (ast_is<
3100 SpreadListExp_t, SpreadExp_t,
3101 TableBlockIndent_t,
3102 Exp_t, NormalDef_t>(item)) {
3103 count++;
3104 }
3105 }
3106 Exp_t* exp = nullptr;
3107 if (auto se = ast_cast<SpreadExp_t>(pair)) {
3108 exp = se->exp.get();
3109 } else {
3110 exp = ast_to<SpreadListExp_t>(pair)->exp.get();
3111 }
3112 auto varName = singleVariableFrom(exp, AccessType::None);
3113 if (varName == "_"sv) break;
3114 int start = index;
3115 int stop = index - count - 1;
3116 auto chain = exp->new_ptr<ChainValue_t>();
3117 auto slice = toAst<Slice_t>(
3118 '[' + (start == 1 ? Empty : std::to_string(start)) + ',' + (stop == -1 ? Empty : std::to_string(stop)) + ']', exp);
3119 chain->items.push_back(slice);
3120 auto nil = toAst<Exp_t>("nil"sv, slice);
3121 pairs.push_back({exp,
3122 varName,
3123 chain,
3124 nil.get()});
3125 break;
3126 }
3070 default: YUEE("AST node mismatch", pair); break; 3127 default: YUEE("AST node mismatch", pair); break;
3071 } 3128 }
3072 } 3129 }
@@ -5706,6 +5763,45 @@ private:
5706 } 5763 }
5707 } 5764 }
5708 5765
5766 bool transformChainEndWithSlice(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) {
5767 auto x = chainList.front();
5768 if (ast_is<Slice_t>(chainList.back())) {
5769 auto comp = x->new_ptr<Comprehension_t>();
5770 {
5771 auto chainValue = x->new_ptr<ChainValue_t>();
5772 for (auto item : chainList) {
5773 chainValue->items.push_back(item);
5774 }
5775 auto itemVar = getUnusedName("_item_"sv);
5776 auto expCode = YueFormat{}.toString(chainValue);
5777 auto compCode = '[' + itemVar + " for "s + itemVar + " in *"s + expCode + ']';
5778 comp.set(toAst<Comprehension_t>(compCode, x));
5779 }
5780 switch (usage) {
5781 case ExpUsage::Assignment: {
5782 auto simpleValue = x->new_ptr<SimpleValue_t>();
5783 simpleValue->value.set(comp);
5784 auto exp = newExp(simpleValue, x);
5785 auto assignment = x->new_ptr<ExpListAssign_t>();
5786 assignment->expList.set(assignList);
5787 auto assign = x->new_ptr<Assign_t>();
5788 assign->values.push_back(exp);
5789 assignment->action.set(assign);
5790 transformAssignment(assignment, out);
5791 break;
5792 }
5793 case ExpUsage::Return:
5794 transformComprehension(comp, out, ExpUsage::Return);
5795 break;
5796 default:
5797 transformComprehension(comp, out, ExpUsage::Closure);
5798 break;
5799 }
5800 return true;
5801 }
5802 return false;
5803 }
5804
5709 bool transformChainEndWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { 5805 bool transformChainEndWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) {
5710 auto x = chainList.front(); 5806 auto x = chainList.front();
5711 if (ast_is<ExistentialOp_t>(chainList.back())) { 5807 if (ast_is<ExistentialOp_t>(chainList.back())) {
@@ -6369,6 +6465,93 @@ private:
6369 } 6465 }
6370 return; 6466 return;
6371 } 6467 }
6468 break;
6469 }
6470 case id<ReversedIndex_t>(): {
6471 auto rIndex = static_cast<ReversedIndex_t*>(*it);
6472 auto current = it;
6473 auto prevChain = x->new_ptr<ChainValue_t>();
6474 for (auto i = chainList.begin(); i != current; ++i) {
6475 prevChain->items.push_back(*i);
6476 }
6477 auto var = singleVariableFrom(prevChain, AccessType::None);
6478 if (!var.empty() && isLocal(var)) {
6479 auto indexNode = toAst<Exp_t>('#' + var, rIndex);
6480 if (rIndex->modifier) {
6481 auto opValue = rIndex->new_ptr<ExpOpValue_t>();
6482 opValue->op.set(toAst<BinaryOperator_t>("-"sv, rIndex));
6483 opValue->pipeExprs.dup(rIndex->modifier->pipeExprs);
6484 indexNode->opValues.push_back(opValue);
6485 indexNode->opValues.dup(rIndex->modifier->opValues);
6486 indexNode->nilCoalesed.set(rIndex->modifier->nilCoalesed);
6487 }
6488 prevChain->items.push_back(indexNode);
6489 auto next = current;
6490 ++next;
6491 for (auto i = next; i != chainList.end(); ++i) {
6492 prevChain->items.push_back(*i);
6493 }
6494 if (usage == ExpUsage::Assignment) {
6495 auto assignment = x->new_ptr<ExpListAssign_t>();
6496 assignment->expList.set(assignList);
6497 auto assign = x->new_ptr<Assign_t>();
6498 assign->values.push_back(newExp(prevChain, x));
6499 assignment->action.set(assign);
6500 transformAssignment(assignment, out);
6501 return;
6502 }
6503 transformChainValue(prevChain, out, usage, assignList);
6504 return;
6505 } else {
6506 auto itemVar = getUnusedName("_item_"sv);
6507 auto asmt = assignmentFrom(toAst<Exp_t>(itemVar, x), newExp(prevChain, x), x);
6508 auto stmt1 = x->new_ptr<Statement_t>();
6509 stmt1->content.set(asmt);
6510 auto newChain = x->new_ptr<ChainValue_t>();
6511 newChain->items.push_back(toAst<Callable_t>(itemVar, x));
6512 auto indexNode = toAst<Exp_t>('#' + itemVar, rIndex);
6513 if (rIndex->modifier) {
6514 auto opValue = rIndex->new_ptr<ExpOpValue_t>();
6515 opValue->op.set(toAst<BinaryOperator_t>("-"sv, rIndex));
6516 opValue->pipeExprs.dup(rIndex->modifier->pipeExprs);
6517 indexNode->opValues.push_back(opValue);
6518 indexNode->opValues.dup(rIndex->modifier->opValues);
6519 indexNode->nilCoalesed.set(rIndex->modifier->nilCoalesed);
6520 }
6521 newChain->items.push_back(indexNode);
6522 auto next = current;
6523 ++next;
6524 for (auto i = next; i != chainList.end(); ++i) {
6525 newChain->items.push_back(*i);
6526 }
6527 auto expList = x->new_ptr<ExpList_t>();
6528 expList->exprs.push_back(newExp(newChain, x));
6529 auto expListAssign = x->new_ptr<ExpListAssign_t>();
6530 expListAssign->expList.set(expList);
6531 auto stmt2 = x->new_ptr<Statement_t>();
6532 stmt2->content.set(expListAssign);
6533 auto block = x->new_ptr<Block_t>();
6534 block->statements.push_back(stmt1);
6535 block->statements.push_back(stmt2);
6536 auto body = x->new_ptr<Body_t>();
6537 body->content.set(block);
6538 auto doNode = x->new_ptr<Do_t>();
6539 doNode->body.set(body);
6540 if (usage == ExpUsage::Assignment) {
6541 auto assignment = x->new_ptr<ExpListAssign_t>();
6542 assignment->expList.set(assignList);
6543 auto assign = x->new_ptr<Assign_t>();
6544 auto sVal = x->new_ptr<SimpleValue_t>();
6545 sVal->value.set(doNode);
6546 assign->values.push_back(newExp(sVal, x));
6547 assignment->action.set(assign);
6548 transformAssignment(assignment, out);
6549 return;
6550 }
6551 transformDo(doNode, out, usage);
6552 return;
6553 }
6554 break;
6372 } 6555 }
6373 } 6556 }
6374 } 6557 }
@@ -6887,6 +7070,9 @@ private:
6887 if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { 7070 if (transformChainEndWithColonItem(chainList, out, usage, assignList)) {
6888 return; 7071 return;
6889 } 7072 }
7073 if (transformChainEndWithSlice(chainList, out, usage, assignList)) {
7074 return;
7075 }
6890 transformChainList(chainList, out, usage, assignList); 7076 transformChainList(chainList, out, usage, assignList);
6891 } 7077 }
6892 7078
@@ -8107,7 +8293,7 @@ private:
8107 if (stopValue.empty()) { 8293 if (stopValue.empty()) {
8108 _buf << "#"sv << listVar; 8294 _buf << "#"sv << listVar;
8109 } else { 8295 } else {
8110 _buf << maxVar << " < 0 and #"sv << listVar << " + "sv << maxVar << " or "sv << maxVar; 8296 _buf << maxVar << " < 0 and #"sv << listVar << " + "sv << maxVar << " + 1 or "sv << maxVar;
8111 } 8297 }
8112 if (!stepValue.empty()) { 8298 if (!stepValue.empty()) {
8113 _buf << ", "sv << stepValue; 8299 _buf << ", "sv << stepValue;
@@ -10059,24 +10245,24 @@ private:
10059 str_list rets; 10245 str_list rets;
10060 pushScope(); 10246 pushScope();
10061 auto okVar = getUnusedName("_ok_"sv); 10247 auto okVar = getUnusedName("_ok_"sv);
10062 for (size_t i = 0; i < assignList->exprs.size(); i++) { 10248 for (size_t i = 0; i < assignList->exprs.size(); i++) {
10063 auto retVar = getUnusedName("_ret_"sv); 10249 auto retVar = getUnusedName("_ret_"sv);
10064 rets.emplace_back(retVar); 10250 rets.emplace_back(retVar);
10065 addToScope(retVar); 10251 addToScope(retVar);
10066 } 10252 }
10067 popScope(); 10253 popScope();
10068 auto varList = join(rets, ","sv); 10254 auto varList = join(rets, ","sv);
10069 auto ifNode = toAst<If_t>("if "s + okVar + ',' + varList + ":=try nil then "s + varList, x); 10255 auto ifNode = toAst<If_t>("if "s + okVar + ',' + varList + ":=try nil then "s + varList, x);
10070 auto exp = ast_to<IfCond_t>(ifNode->nodes.front())->assignment->assign->values.front(); 10256 auto exp = ast_to<IfCond_t>(ifNode->nodes.front())->assignment->assign->values.front();
10071 auto sVal = simpleSingleValueFrom(exp); 10257 auto sVal = simpleSingleValueFrom(exp);
10072 auto newTry = sVal->value.to<Try_t>(); 10258 auto newTry = sVal->value.to<Try_t>();
10073 newTry->func.set(tryNode->func); 10259 newTry->func.set(tryNode->func);
10074 newTry->catchBlock.set(tryNode->catchBlock); 10260 newTry->catchBlock.set(tryNode->catchBlock);
10075 auto assignment = x->new_ptr<ExpListAssign_t>(); 10261 auto assignment = x->new_ptr<ExpListAssign_t>();
10076 assignment->expList.set(assignList); 10262 assignment->expList.set(assignList);
10077 auto assign = x->new_ptr<Assign_t>(); 10263 auto assign = x->new_ptr<Assign_t>();
10078 assign->values.push_back(ifNode); 10264 assign->values.push_back(ifNode);
10079 assignment->action.set(assign); 10265 assignment->action.set(assign);
10080 transformAssignment(assignment, out); 10266 transformAssignment(assignment, out);
10081 return; 10267 return;
10082 } 10268 }
@@ -10084,12 +10270,12 @@ private:
10084 auto okVar = getUnusedName("_ok_"sv); 10270 auto okVar = getUnusedName("_ok_"sv);
10085 auto code = "do\n\t"s + okVar + ", ... = try nil\n\t... if "s + okVar; 10271 auto code = "do\n\t"s + okVar + ", ... = try nil\n\t... if "s + okVar;
10086 auto doNode = toAst<Do_t>(code, x); 10272 auto doNode = toAst<Do_t>(code, x);
10087 auto block = doNode->body->content.to<Block_t>(); 10273 auto block = doNode->body->content.to<Block_t>();
10088 auto asmt = static_cast<Statement_t*>(block->statements.front())->content.to<ExpListAssign_t>(); 10274 auto asmt = static_cast<Statement_t*>(block->statements.front())->content.to<ExpListAssign_t>();
10089 auto assign = asmt->action.to<Assign_t>(); 10275 auto assign = asmt->action.to<Assign_t>();
10090 auto sVal = simpleSingleValueFrom(assign->values.back()); 10276 auto sVal = simpleSingleValueFrom(assign->values.back());
10091 auto newTry = sVal->value.to<Try_t>(); 10277 auto newTry = sVal->value.to<Try_t>();
10092 newTry->func.set(tryNode->func); 10278 newTry->func.set(tryNode->func);
10093 newTry->catchBlock.set(tryNode->catchBlock); 10279 newTry->catchBlock.set(tryNode->catchBlock);
10094 transformDo(doNode, out, usage); 10280 transformDo(doNode, out, usage);
10095 return; 10281 return;
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index e860d55..1011a49 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -709,7 +709,8 @@ YueParser::YueParser() {
709 chain_with_colon = +chain_item >> -colon_chain; 709 chain_with_colon = +chain_item >> -colon_chain;
710 chain_items = chain_with_colon | colon_chain; 710 chain_items = chain_with_colon | colon_chain;
711 711
712 index = '[' >> not_('[') >> space >> Exp >> space >> ']'; 712 index = '[' >> not_('[') >> space >> (ReversedIndex >> and_(space >> ']') | Exp) >> space >> ']';
713 ReversedIndex = '#' >> space >> -('-' >> space >> Exp);
713 chain_item = 714 chain_item =
714 Invoke >> -ExistentialOp | 715 Invoke >> -ExistentialOp |
715 DotChainItem >> -ExistentialOp | 716 DotChainItem >> -ExistentialOp |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h
index 0d9db19..1057626 100644
--- a/src/yuescript/yue_parser.h
+++ b/src/yuescript/yue_parser.h
@@ -365,6 +365,7 @@ private:
365 AST_RULE(ExpOpValue); 365 AST_RULE(ExpOpValue);
366 AST_RULE(Exp); 366 AST_RULE(Exp);
367 AST_RULE(Callable); 367 AST_RULE(Callable);
368 AST_RULE(ReversedIndex);
368 AST_RULE(ChainValue); 369 AST_RULE(ChainValue);
369 AST_RULE(SimpleTable); 370 AST_RULE(SimpleTable);
370 AST_RULE(SimpleValue); 371 AST_RULE(SimpleValue);