From 7167828a9d873156ad208d161cd1a2dc8ab78523 Mon Sep 17 00:00:00 2001 From: Li Jin 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 err; + ast_ptr body; + AST_MEMBER(catch_block, &err, &body) +AST_END(catch_block) + +AST_NODE(Try) + ast_sel func; + ast_ptr 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 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 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()) { return static_cast(value->item.get()); } @@ -1042,6 +1042,7 @@ private: case id(): transformFor(static_cast(value), out); break; case id(): transformWhile(static_cast(value), out); break; case id(): transformDo(static_cast(value), out, ExpUsage::Common); break; + case id(): transformTry(static_cast(value), out, ExpUsage::Common); break; case id(): transformCompCommon(static_cast(value), out); break; default: specialSingleValue = false; break; } @@ -2660,6 +2661,7 @@ private: case id(): transformForClosure(static_cast(value), out); break; case id(): transformWhileClosure(static_cast(value), out); break; case id(): transformDo(static_cast(value), out, ExpUsage::Closure); break; + case id(): transformTry(static_cast(value), out, ExpUsage::Closure); break; case id(): transform_unary_value(static_cast(value), out); break; case id(): transformTblComprehension(static_cast(value), out, ExpUsage::Closure); break; case id(): transformTableLit(static_cast(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 errHandler; + if (tryNode->catchBlock) { + auto errHandleStr = "("s + _parser.toString(tryNode->catchBlock->err) + ")->\n"s + _parser.toString(tryNode->catchBlock->body); + errHandler.set(toAst(errHandleStr, x)); + } + if (auto tryBlock = tryNode->func.as()) { + auto tryExp = toAst("->\n"s + _parser.toString(tryBlock), x); + if (errHandler) { + auto xpcall = toAst("xpcall()", x); + auto invoke = ast_to(xpcall->items.back()); + invoke->args.push_back(tryExp); + invoke->args.push_back(errHandler); + transformChainValue(xpcall, out, ExpUsage::Closure); + } else { + auto pcall = toAst("pcall()", x); + auto invoke = ast_to(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(); + BREAK_IF(!chainValue); + BREAK_IF(!isChainValueCall(chainValue)); + ast_ptr last = chainValue->items.back(); + chainValue->items.pop_back(); + _ast_list* args = nullptr; + if (auto invoke = ast_cast(last)) { + args = &invoke->args; + } else { + args = &(ast_to(last)->args); + } + if (errHandler) { + auto xpcall = toAst("xpcall()", x); + auto invoke = ast_to(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("pcall()", x); + auto invoke = ast_to(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("xpcall()", x); + auto invoke = ast_to(xpcall->items.back()); + invoke->args.push_back(tryNode->func); + invoke->args.push_back(errHandler); + transformChainValue(xpcall, out, ExpUsage::Closure); + } else { + auto pcall = toAst("pcall()", x); + auto invoke = ast_to(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 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