aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2022-02-21 14:07:07 +0800
committerLi Jin <dragon-fly@qq.com>2022-02-21 14:07:07 +0800
commit7167828a9d873156ad208d161cd1a2dc8ab78523 (patch)
tree3be64f80b735e792e4bfb35dc864f995530305b6
parent6beed7cdbad4577e7dd29c48adcc064a5dab47ba (diff)
downloadyuescript-7167828a9d873156ad208d161cd1a2dc8ab78523.tar.gz
yuescript-7167828a9d873156ad208d161cd1a2dc8ab78523.tar.bz2
yuescript-7167828a9d873156ad208d161cd1a2dc8ab78523.zip
fixing issue #80.
-rw-r--r--spec/inputs/try-catch.yue30
-rw-r--r--spec/outputs/try-catch.lua27
-rw-r--r--src/yuescript/ast.hpp2
-rwxr-xr-xsrc/yuescript/yue_ast.h14
-rwxr-xr-xsrc/yuescript/yue_compiler.cpp87
-rwxr-xr-xsrc/yuescript/yue_parser.cpp12
-rwxr-xr-xsrc/yuescript/yue_parser.h2
7 files changed, 165 insertions, 9 deletions
diff --git a/spec/inputs/try-catch.yue b/spec/inputs/try-catch.yue
new file mode 100644
index 0000000..ad8b1f0
--- /dev/null
+++ b/spec/inputs/try-catch.yue
@@ -0,0 +1,30 @@
1try
2 func 1, 2, 3
3catch err
4 print err
5
6success, result = try
7 func 1, 2, 3
8catch err
9 print err
10
11try func 1, 2, 3
12catch err
13 print err
14
15success, result = try func 1, 2, 3
16
17try
18 print "trying"
19 func 1, 2, 3
20
21try tb.func
22try tb.func!
23try tb.func()
24try (tb.func!)
25
26try tb.func 1
27try tb.func(1)
28
29nil
30
diff --git a/spec/outputs/try-catch.lua b/spec/outputs/try-catch.lua
new file mode 100644
index 0000000..25efda4
--- /dev/null
+++ b/spec/outputs/try-catch.lua
@@ -0,0 +1,27 @@
1xpcall(function()
2 return func(1, 2, 3)
3end, function(err)
4 return print(err)
5end)
6local success, result = xpcall(function()
7 return func(1, 2, 3)
8end, function(err)
9 return print(err)
10end)
11xpcall(func, function(err)
12 return print(err)
13end, 1, 2, 3)
14success, result = pcall(func, 1, 2, 3)
15pcall(function()
16 print("trying")
17 return func(1, 2, 3)
18end)
19pcall(tb.func)
20pcall(tb.func)
21pcall(tb.func)
22pcall((tb.func()))
23pcall(tb.func, 1)
24xpcall(tb.func, function(err)
25 return print(err)
26end, 1)
27return nil
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:
364 364
365class _ast_list : public ast_member { 365class _ast_list : public ast_member {
366public: 366public:
367 ~_ast_list() { 367 ~_ast_list() {
368 clear(); 368 clear();
369 } 369 }
370 370
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)
316 AST_MEMBER(Do, &body) 316 AST_MEMBER(Do, &body)
317AST_END(Do) 317AST_END(Do)
318 318
319AST_NODE(catch_block)
320 ast_ptr<true, Variable_t> err;
321 ast_ptr<true, Block_t> body;
322 AST_MEMBER(catch_block, &err, &body)
323AST_END(catch_block)
324
325AST_NODE(Try)
326 ast_sel<true, Block_t, Exp_t> func;
327 ast_ptr<false, catch_block_t> catchBlock;
328 AST_MEMBER(Try, &func, &catchBlock)
329AST_END(Try)
330
319class CompInner_t; 331class CompInner_t;
320class Statement_t; 332class Statement_t;
321 333
@@ -474,7 +486,7 @@ class FunLit_t;
474AST_NODE(SimpleValue) 486AST_NODE(SimpleValue)
475 ast_sel<true, const_value_t, 487 ast_sel<true, const_value_t,
476 If_t, Switch_t, With_t, ClassDecl_t, 488 If_t, Switch_t, With_t, ClassDecl_t,
477 ForEach_t, For_t, While_t, Do_t, 489 ForEach_t, For_t, While_t, Do_t, Try_t,
478 unary_value_t, 490 unary_value_t,
479 TblComprehension_t, TableLit_t, Comprehension_t, 491 TblComprehension_t, TableLit_t, Comprehension_t,
480 FunLit_t, Num_t> value; 492 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;
60 60
61typedef std::list<std::string> str_list; 61typedef std::list<std::string> str_list;
62 62
63const std::string_view version = "0.9.11"sv; 63const std::string_view version = "0.10.0"sv;
64const std::string_view extension = "yue"sv; 64const std::string_view extension = "yue"sv;
65 65
66class YueCompilerImpl { 66class YueCompilerImpl {
@@ -576,8 +576,8 @@ private:
576 return exp; 576 return exp;
577 } 577 }
578 578
579 SimpleValue_t* simpleSingleValueFrom(ast_node* expList) const { 579 SimpleValue_t* simpleSingleValueFrom(ast_node* node) const {
580 auto value = singleValueFrom(expList); 580 auto value = singleValueFrom(node);
581 if (value && value->item.is<SimpleValue_t>()) { 581 if (value && value->item.is<SimpleValue_t>()) {
582 return static_cast<SimpleValue_t*>(value->item.get()); 582 return static_cast<SimpleValue_t*>(value->item.get());
583 } 583 }
@@ -1042,6 +1042,7 @@ private:
1042 case id<For_t>(): transformFor(static_cast<For_t*>(value), out); break; 1042 case id<For_t>(): transformFor(static_cast<For_t*>(value), out); break;
1043 case id<While_t>(): transformWhile(static_cast<While_t*>(value), out); break; 1043 case id<While_t>(): transformWhile(static_cast<While_t*>(value), out); break;
1044 case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Common); break; 1044 case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Common); break;
1045 case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Common); break;
1045 case id<Comprehension_t>(): transformCompCommon(static_cast<Comprehension_t*>(value), out); break; 1046 case id<Comprehension_t>(): transformCompCommon(static_cast<Comprehension_t*>(value), out); break;
1046 default: specialSingleValue = false; break; 1047 default: specialSingleValue = false; break;
1047 } 1048 }
@@ -2660,6 +2661,7 @@ private:
2660 case id<For_t>(): transformForClosure(static_cast<For_t*>(value), out); break; 2661 case id<For_t>(): transformForClosure(static_cast<For_t*>(value), out); break;
2661 case id<While_t>(): transformWhileClosure(static_cast<While_t*>(value), out); break; 2662 case id<While_t>(): transformWhileClosure(static_cast<While_t*>(value), out); break;
2662 case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Closure); break; 2663 case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Closure); break;
2664 case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Closure); break;
2663 case id<unary_value_t>(): transform_unary_value(static_cast<unary_value_t*>(value), out); break; 2665 case id<unary_value_t>(): transform_unary_value(static_cast<unary_value_t*>(value), out); break;
2664 case id<TblComprehension_t>(): transformTblComprehension(static_cast<TblComprehension_t*>(value), out, ExpUsage::Closure); break; 2666 case id<TblComprehension_t>(): transformTblComprehension(static_cast<TblComprehension_t*>(value), out, ExpUsage::Closure); break;
2665 case id<TableLit_t>(): transformTableLit(static_cast<TableLit_t*>(value), out); break; 2667 case id<TableLit_t>(): transformTableLit(static_cast<TableLit_t*>(value), out); break;
@@ -6087,6 +6089,85 @@ private:
6087 out.push_back(join(temp)); 6089 out.push_back(join(temp));
6088 } 6090 }
6089 6091
6092 void transformTry(Try_t* tryNode, str_list& out, ExpUsage usage) {
6093 auto x = tryNode;
6094 ast_ptr<true, Exp_t> errHandler;
6095 if (tryNode->catchBlock) {
6096 auto errHandleStr = "("s + _parser.toString(tryNode->catchBlock->err) + ")->\n"s + _parser.toString(tryNode->catchBlock->body);
6097 errHandler.set(toAst<Exp_t>(errHandleStr, x));
6098 }
6099 if (auto tryBlock = tryNode->func.as<Block_t>()) {
6100 auto tryExp = toAst<Exp_t>("->\n"s + _parser.toString(tryBlock), x);
6101 if (errHandler) {
6102 auto xpcall = toAst<ChainValue_t>("xpcall()", x);
6103 auto invoke = ast_to<Invoke_t>(xpcall->items.back());
6104 invoke->args.push_back(tryExp);
6105 invoke->args.push_back(errHandler);
6106 transformChainValue(xpcall, out, ExpUsage::Closure);
6107 } else {
6108 auto pcall = toAst<ChainValue_t>("pcall()", x);
6109 auto invoke = ast_to<Invoke_t>(pcall->items.back());
6110 invoke->args.push_back(tryExp);
6111 transformChainValue(pcall, out, ExpUsage::Closure);
6112 }
6113 if (usage == ExpUsage::Common) {
6114 out.back().append(nlr(x));
6115 }
6116 return;
6117 } else if (auto value = singleValueFrom(tryNode->func)) {
6118 BLOCK_START
6119 auto chainValue = value->item.as<ChainValue_t>();
6120 BREAK_IF(!chainValue);
6121 BREAK_IF(!isChainValueCall(chainValue));
6122 ast_ptr<true, ast_node> last = chainValue->items.back();
6123 chainValue->items.pop_back();
6124 _ast_list* args = nullptr;
6125 if (auto invoke = ast_cast<InvokeArgs_t>(last)) {
6126 args = &invoke->args;
6127 } else {
6128 args = &(ast_to<Invoke_t>(last)->args);
6129 }
6130 if (errHandler) {
6131 auto xpcall = toAst<ChainValue_t>("xpcall()", x);
6132 auto invoke = ast_to<Invoke_t>(xpcall->items.back());
6133 invoke->args.push_back(tryNode->func);
6134 invoke->args.push_back(errHandler);
6135 for (auto arg : args->objects()) {
6136 invoke->args.push_back(arg);
6137 }
6138 transformChainValue(xpcall, out, ExpUsage::Closure);
6139 } else {
6140 auto pcall = toAst<ChainValue_t>("pcall()", x);
6141 auto invoke = ast_to<Invoke_t>(pcall->items.back());
6142 invoke->args.push_back(tryNode->func);
6143 for (auto arg : args->objects()) {
6144 invoke->args.push_back(arg);
6145 }
6146 transformChainValue(pcall, out, ExpUsage::Closure);
6147 }
6148 if (usage == ExpUsage::Common) {
6149 out.back().append(nlr(x));
6150 }
6151 return;
6152 BLOCK_END
6153 }
6154 if (errHandler) {
6155 auto xpcall = toAst<ChainValue_t>("xpcall()", x);
6156 auto invoke = ast_to<Invoke_t>(xpcall->items.back());
6157 invoke->args.push_back(tryNode->func);
6158 invoke->args.push_back(errHandler);
6159 transformChainValue(xpcall, out, ExpUsage::Closure);
6160 } else {
6161 auto pcall = toAst<ChainValue_t>("pcall()", x);
6162 auto invoke = ast_to<Invoke_t>(pcall->items.back());
6163 invoke->args.push_back(tryNode->func);
6164 transformChainValue(pcall, out, ExpUsage::Closure);
6165 }
6166 if (usage == ExpUsage::Common) {
6167 out.back().append(nlr(x));
6168 }
6169 }
6170
6090 void transformImportFrom(ImportFrom_t* import, str_list& out) { 6171 void transformImportFrom(ImportFrom_t* import, str_list& out) {
6091 str_list temp; 6172 str_list temp;
6092 auto x = import; 6173 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 = {
29 "until", "while", // Lua keywords 29 "until", "while", // Lua keywords
30 "as", "class", "continue", "export", "extends", 30 "as", "class", "continue", "export", "extends",
31 "from", "global", "import", "is", "macro", 31 "from", "global", "import", "is", "macro",
32 "switch", "unless", "using", "when", "with" // Yue keywords 32 "switch", "try", "unless", "using", "when",
33 "with" // Yue keywords
33}; 34};
34 35
35YueParser::YueParser() { 36YueParser::YueParser() {
@@ -229,8 +230,8 @@ YueParser::YueParser() {
229 SwitchBlock = *EmptyLine >> 230 SwitchBlock = *EmptyLine >>
230 Advance >> Seperator >> 231 Advance >> Seperator >>
231 SwitchCase >> 232 SwitchCase >>
232 *(+SpaceBreak >> SwitchCase) >> 233 *(Break >> *EmptyLine >> CheckIndent >> SwitchCase) >>
233 -(+SpaceBreak >> SwitchElse) >> 234 -(Break >> *EmptyLine >> CheckIndent >> SwitchElse) >>
234 PopIndent; 235 PopIndent;
235 236
236 Switch = Space >> key("switch") >> disable_do(Exp) >> -(Space >> key("do")) 237 Switch = Space >> key("switch") >> disable_do(Exp) >> -(Space >> key("do"))
@@ -299,6 +300,9 @@ YueParser::YueParser() {
299 return true; 300 return true;
300 }); 301 });
301 302
303 catch_block = Break >> *EmptyLine >> CheckIndent >> Space >> key("catch") >> Space >> Variable >> InBlock;
304 Try = Space >> key("try") >> (InBlock | Exp) >> -catch_block;
305
302 Comprehension = sym('[') >> Exp >> Space >> CompInner >> sym(']'); 306 Comprehension = sym('[') >> Exp >> Space >> CompInner >> sym(']');
303 comp_value = sym(',') >> Exp; 307 comp_value = sym(',') >> Exp;
304 TblComprehension = sym('{') >> Exp >> -comp_value >> Space >> CompInner >> sym('}'); 308 TblComprehension = sym('{') >> Exp >> -comp_value >> Space >> CompInner >> sym('}');
@@ -609,7 +613,7 @@ YueParser::YueParser() {
609 const_value = (expr("nil") | expr("true") | expr("false")) >> not_(AlphaNum); 613 const_value = (expr("nil") | expr("true") | expr("false")) >> not_(AlphaNum);
610 614
611 SimpleValue = Space >> (const_value | 615 SimpleValue = Space >> (const_value |
612 If | Switch | With | ClassDecl | ForEach | For | While | Do | 616 If | Switch | Try | With | ClassDecl | ForEach | For | While | Do |
613 unary_value | TblComprehension | TableLit | Comprehension | 617 unary_value | TblComprehension | TableLit | Comprehension |
614 FunLit | Num); 618 FunLit | Num);
615 619
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:
238 AST_RULE(For) 238 AST_RULE(For)
239 AST_RULE(ForEach) 239 AST_RULE(ForEach)
240 AST_RULE(Do) 240 AST_RULE(Do)
241 AST_RULE(catch_block)
242 AST_RULE(Try)
241 AST_RULE(Comprehension) 243 AST_RULE(Comprehension)
242 AST_RULE(comp_value) 244 AST_RULE(comp_value)
243 AST_RULE(TblComprehension) 245 AST_RULE(TblComprehension)