From 7167828a9d873156ad208d161cd1a2dc8ab78523 Mon Sep 17 00:00:00 2001 From: Li Jin <dragon-fly@qq.com> Date: Mon, 21 Feb 2022 14:07:07 +0800 Subject: fixing issue #80. --- src/yuescript/ast.hpp | 2 +- src/yuescript/yue_ast.h | 14 ++++++- src/yuescript/yue_compiler.cpp | 87 ++++++++++++++++++++++++++++++++++++++++-- src/yuescript/yue_parser.cpp | 12 ++++-- src/yuescript/yue_parser.h | 2 + 5 files changed, 108 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/yuescript/ast.hpp b/src/yuescript/ast.hpp index 0636a74..6f89b52 100644 --- a/src/yuescript/ast.hpp +++ b/src/yuescript/ast.hpp @@ -364,7 +364,7 @@ private: class _ast_list : public ast_member { public: - ~_ast_list() { + ~_ast_list() { clear(); } diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 79e35a5..d2a6557 100755 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h @@ -316,6 +316,18 @@ AST_NODE(Do) AST_MEMBER(Do, &body) AST_END(Do) +AST_NODE(catch_block) + ast_ptr<true, Variable_t> err; + ast_ptr<true, Block_t> body; + AST_MEMBER(catch_block, &err, &body) +AST_END(catch_block) + +AST_NODE(Try) + ast_sel<true, Block_t, Exp_t> func; + ast_ptr<false, catch_block_t> catchBlock; + AST_MEMBER(Try, &func, &catchBlock) +AST_END(Try) + class CompInner_t; class Statement_t; @@ -474,7 +486,7 @@ class FunLit_t; AST_NODE(SimpleValue) ast_sel<true, const_value_t, If_t, Switch_t, With_t, ClassDecl_t, - ForEach_t, For_t, While_t, Do_t, + ForEach_t, For_t, While_t, Do_t, Try_t, unary_value_t, TblComprehension_t, TableLit_t, Comprehension_t, FunLit_t, Num_t> value; diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index fbb3fb5..2b9ebc9 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -60,7 +60,7 @@ using namespace parserlib; typedef std::list<std::string> str_list; -const std::string_view version = "0.9.11"sv; +const std::string_view version = "0.10.0"sv; const std::string_view extension = "yue"sv; class YueCompilerImpl { @@ -576,8 +576,8 @@ private: return exp; } - SimpleValue_t* simpleSingleValueFrom(ast_node* expList) const { - auto value = singleValueFrom(expList); + SimpleValue_t* simpleSingleValueFrom(ast_node* node) const { + auto value = singleValueFrom(node); if (value && value->item.is<SimpleValue_t>()) { return static_cast<SimpleValue_t*>(value->item.get()); } @@ -1042,6 +1042,7 @@ private: case id<For_t>(): transformFor(static_cast<For_t*>(value), out); break; case id<While_t>(): transformWhile(static_cast<While_t*>(value), out); break; case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Common); break; + case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Common); break; case id<Comprehension_t>(): transformCompCommon(static_cast<Comprehension_t*>(value), out); break; default: specialSingleValue = false; break; } @@ -2660,6 +2661,7 @@ private: case id<For_t>(): transformForClosure(static_cast<For_t*>(value), out); break; case id<While_t>(): transformWhileClosure(static_cast<While_t*>(value), out); break; case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Closure); break; + case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Closure); break; case id<unary_value_t>(): transform_unary_value(static_cast<unary_value_t*>(value), out); break; case id<TblComprehension_t>(): transformTblComprehension(static_cast<TblComprehension_t*>(value), out, ExpUsage::Closure); break; case id<TableLit_t>(): transformTableLit(static_cast<TableLit_t*>(value), out); break; @@ -6087,6 +6089,85 @@ private: out.push_back(join(temp)); } + void transformTry(Try_t* tryNode, str_list& out, ExpUsage usage) { + auto x = tryNode; + ast_ptr<true, Exp_t> errHandler; + if (tryNode->catchBlock) { + auto errHandleStr = "("s + _parser.toString(tryNode->catchBlock->err) + ")->\n"s + _parser.toString(tryNode->catchBlock->body); + errHandler.set(toAst<Exp_t>(errHandleStr, x)); + } + if (auto tryBlock = tryNode->func.as<Block_t>()) { + auto tryExp = toAst<Exp_t>("->\n"s + _parser.toString(tryBlock), x); + if (errHandler) { + auto xpcall = toAst<ChainValue_t>("xpcall()", x); + auto invoke = ast_to<Invoke_t>(xpcall->items.back()); + invoke->args.push_back(tryExp); + invoke->args.push_back(errHandler); + transformChainValue(xpcall, out, ExpUsage::Closure); + } else { + auto pcall = toAst<ChainValue_t>("pcall()", x); + auto invoke = ast_to<Invoke_t>(pcall->items.back()); + invoke->args.push_back(tryExp); + transformChainValue(pcall, out, ExpUsage::Closure); + } + if (usage == ExpUsage::Common) { + out.back().append(nlr(x)); + } + return; + } else if (auto value = singleValueFrom(tryNode->func)) { + BLOCK_START + auto chainValue = value->item.as<ChainValue_t>(); + BREAK_IF(!chainValue); + BREAK_IF(!isChainValueCall(chainValue)); + ast_ptr<true, ast_node> last = chainValue->items.back(); + chainValue->items.pop_back(); + _ast_list* args = nullptr; + if (auto invoke = ast_cast<InvokeArgs_t>(last)) { + args = &invoke->args; + } else { + args = &(ast_to<Invoke_t>(last)->args); + } + if (errHandler) { + auto xpcall = toAst<ChainValue_t>("xpcall()", x); + auto invoke = ast_to<Invoke_t>(xpcall->items.back()); + invoke->args.push_back(tryNode->func); + invoke->args.push_back(errHandler); + for (auto arg : args->objects()) { + invoke->args.push_back(arg); + } + transformChainValue(xpcall, out, ExpUsage::Closure); + } else { + auto pcall = toAst<ChainValue_t>("pcall()", x); + auto invoke = ast_to<Invoke_t>(pcall->items.back()); + invoke->args.push_back(tryNode->func); + for (auto arg : args->objects()) { + invoke->args.push_back(arg); + } + transformChainValue(pcall, out, ExpUsage::Closure); + } + if (usage == ExpUsage::Common) { + out.back().append(nlr(x)); + } + return; + BLOCK_END + } + if (errHandler) { + auto xpcall = toAst<ChainValue_t>("xpcall()", x); + auto invoke = ast_to<Invoke_t>(xpcall->items.back()); + invoke->args.push_back(tryNode->func); + invoke->args.push_back(errHandler); + transformChainValue(xpcall, out, ExpUsage::Closure); + } else { + auto pcall = toAst<ChainValue_t>("pcall()", x); + auto invoke = ast_to<Invoke_t>(pcall->items.back()); + invoke->args.push_back(tryNode->func); + transformChainValue(pcall, out, ExpUsage::Closure); + } + if (usage == ExpUsage::Common) { + out.back().append(nlr(x)); + } + } + void transformImportFrom(ImportFrom_t* import, str_list& out) { str_list temp; auto x = import; diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 3d12190..8325366 100755 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -29,7 +29,8 @@ std::unordered_set<std::string> Keywords = { "until", "while", // Lua keywords "as", "class", "continue", "export", "extends", "from", "global", "import", "is", "macro", - "switch", "unless", "using", "when", "with" // Yue keywords + "switch", "try", "unless", "using", "when", + "with" // Yue keywords }; YueParser::YueParser() { @@ -229,8 +230,8 @@ YueParser::YueParser() { SwitchBlock = *EmptyLine >> Advance >> Seperator >> SwitchCase >> - *(+SpaceBreak >> SwitchCase) >> - -(+SpaceBreak >> SwitchElse) >> + *(Break >> *EmptyLine >> CheckIndent >> SwitchCase) >> + -(Break >> *EmptyLine >> CheckIndent >> SwitchElse) >> PopIndent; Switch = Space >> key("switch") >> disable_do(Exp) >> -(Space >> key("do")) @@ -299,6 +300,9 @@ YueParser::YueParser() { return true; }); + catch_block = Break >> *EmptyLine >> CheckIndent >> Space >> key("catch") >> Space >> Variable >> InBlock; + Try = Space >> key("try") >> (InBlock | Exp) >> -catch_block; + Comprehension = sym('[') >> Exp >> Space >> CompInner >> sym(']'); comp_value = sym(',') >> Exp; TblComprehension = sym('{') >> Exp >> -comp_value >> Space >> CompInner >> sym('}'); @@ -609,7 +613,7 @@ YueParser::YueParser() { const_value = (expr("nil") | expr("true") | expr("false")) >> not_(AlphaNum); SimpleValue = Space >> (const_value | - If | Switch | With | ClassDecl | ForEach | For | While | Do | + If | Switch | Try | With | ClassDecl | ForEach | For | While | Do | unary_value | TblComprehension | TableLit | Comprehension | FunLit | Num); diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 7dea126..bd86f50 100755 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h @@ -238,6 +238,8 @@ private: AST_RULE(For) AST_RULE(ForEach) AST_RULE(Do) + AST_RULE(catch_block) + AST_RULE(Try) AST_RULE(Comprehension) AST_RULE(comp_value) AST_RULE(TblComprehension) -- cgit v1.2.3-55-g6feb