diff options
author | Li Jin <dragon-fly@qq.com> | 2021-02-10 14:34:08 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2021-02-10 20:50:03 +0800 |
commit | c68e11bc6d7631185749aaf0c8d89147b3ac9cc9 (patch) | |
tree | e91306fa43513f7a66022ba16abbc224a91c8bd5 | |
parent | 9f622c5bbd9cfb7e66a9fd3c371461af4249d566 (diff) | |
download | yuescript-c68e11bc6d7631185749aaf0c8d89147b3ac9cc9.tar.gz yuescript-c68e11bc6d7631185749aaf0c8d89147b3ac9cc9.tar.bz2 yuescript-c68e11bc6d7631185749aaf0c8d89147b3ac9cc9.zip |
update backcall operator syntax, fix issue #31.
-rw-r--r-- | spec/inputs/backcall.mp | 28 | ||||
-rw-r--r-- | src/MoonP/moon_ast.h | 8 | ||||
-rw-r--r-- | src/MoonP/moon_compiler.cpp | 104 | ||||
-rw-r--r-- | src/MoonP/moon_parser.cpp | 8 | ||||
-rw-r--r-- | src/MoonP/moon_parser.h | 1 |
5 files changed, 134 insertions, 15 deletions
diff --git a/spec/inputs/backcall.mp b/spec/inputs/backcall.mp index a648b16..0d52f3f 100644 --- a/spec/inputs/backcall.mp +++ b/spec/inputs/backcall.mp | |||
@@ -2,9 +2,9 @@ | |||
2 | {"abc", 123, 998} |> foreach print | 2 | {"abc", 123, 998} |> foreach print |
3 | 3 | ||
4 | {1,2,3} | 4 | {1,2,3} |
5 | |> map((x)-> x * 2) | 5 | |> map (x)-> x * 2 |
6 | |> filter((x)-> x > 4) | 6 | |> filter (x)-> x > 4 |
7 | |> reduce(0, (a,b)-> a + b) | 7 | |> reduce 0, (a,b)-> a + b |
8 | 8 | ||
9 | 9 | ||
10 | [i |> tostring for i = 0,10] |> table.concat(",") |> print | 10 | [i |> tostring for i = 0,10] |> table.concat(",") |> print |
@@ -36,6 +36,28 @@ arr[3] |> f 1, 2, _, 4, 5 | |||
36 | 36 | ||
37 | a = {"1","2","3"} |> table.concat("") |> tonumber |> f1(1, 2, 3, _) |> f2(1, _, 3) | 37 | a = {"1","2","3"} |> table.concat("") |> tonumber |> f1(1, 2, 3, _) |> f2(1, _, 3) |
38 | 38 | ||
39 | readFile "example.txt" | ||
40 | |> extract _, language, {} | ||
41 | |> parse _, language | ||
42 | |> emit | ||
43 | |> render | ||
44 | |||
45 | |||
46 | 123 |> not func! |> f | ||
47 | |||
48 | do | ||
49 | _1 = list{"abc","xyz","123"}\map"#"\value! | ||
50 | |> -func! | ||
51 | |> abc 123, _, "x" | ||
52 | |||
53 | global _2,_3,_4 = 1,2,3 | ||
54 | |> f | ||
55 | |||
56 | local _5 = v |> f1 1 | ||
57 | |> f2 2 | ||
58 | |> f3 3 | ||
59 | |> f4 4 | ||
60 | |||
39 | do | 61 | do |
40 | (x)<- map {1,2,3} | 62 | (x)<- map {1,2,3} |
41 | x * 2 | 63 | x * 2 |
diff --git a/src/MoonP/moon_ast.h b/src/MoonP/moon_ast.h index d00d855..2f5123b 100644 --- a/src/MoonP/moon_ast.h +++ b/src/MoonP/moon_ast.h | |||
@@ -701,6 +701,12 @@ AST_END(unless_line) | |||
701 | AST_LEAF(BreakLoop) | 701 | AST_LEAF(BreakLoop) |
702 | AST_END(BreakLoop) | 702 | AST_END(BreakLoop) |
703 | 703 | ||
704 | AST_NODE(BackcallBody) | ||
705 | ast_ptr<true, Seperator_t> sep; | ||
706 | ast_list<true, unary_exp_t> values; | ||
707 | AST_MEMBER(BackcallBody, &sep, &values) | ||
708 | AST_END(BackcallBody) | ||
709 | |||
704 | AST_NODE(statement_appendix) | 710 | AST_NODE(statement_appendix) |
705 | ast_sel<true, if_line_t, unless_line_t, CompInner_t> item; | 711 | ast_sel<true, if_line_t, unless_line_t, CompInner_t> item; |
706 | AST_MEMBER(statement_appendix, &item) | 712 | AST_MEMBER(statement_appendix, &item) |
@@ -712,7 +718,7 @@ AST_END(statement_sep) | |||
712 | AST_NODE(Statement) | 718 | AST_NODE(Statement) |
713 | ast_sel<true, Import_t, While_t, Repeat_t, For_t, ForEach_t, | 719 | ast_sel<true, Import_t, While_t, Repeat_t, For_t, ForEach_t, |
714 | Return_t, Local_t, Global_t, Export_t, Macro_t, BreakLoop_t, | 720 | Return_t, Local_t, Global_t, Export_t, Macro_t, BreakLoop_t, |
715 | Label_t, Goto_t, Backcall_t, LocalAttrib_t, ExpListAssign_t> content; | 721 | Label_t, Goto_t, Backcall_t, LocalAttrib_t, BackcallBody_t, ExpListAssign_t> content; |
716 | ast_ptr<false, statement_appendix_t> appendix; | 722 | ast_ptr<false, statement_appendix_t> appendix; |
717 | ast_ptr<false, statement_sep_t> needSep; | 723 | ast_ptr<false, statement_sep_t> needSep; |
718 | AST_MEMBER(Statement, &content, &appendix, &needSep) | 724 | AST_MEMBER(Statement, &content, &appendix, &needSep) |
diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index 73bbd60..11d4ed8 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp | |||
@@ -53,7 +53,7 @@ inline std::string s(std::string_view sv) { | |||
53 | return std::string(sv); | 53 | return std::string(sv); |
54 | } | 54 | } |
55 | 55 | ||
56 | const std::string_view version = "0.5.2"sv; | 56 | const std::string_view version = "0.6.0"sv; |
57 | const std::string_view extension = "mp"sv; | 57 | const std::string_view extension = "mp"sv; |
58 | 58 | ||
59 | class MoonCompilerImpl { | 59 | class MoonCompilerImpl { |
@@ -429,7 +429,7 @@ private: | |||
429 | return result; | 429 | return result; |
430 | } | 430 | } |
431 | 431 | ||
432 | Value_t* singleValueFrom(ast_node* item) const { | 432 | unary_exp_t* singleUnaryExpFrom(ast_node* item) const { |
433 | Exp_t* exp = nullptr; | 433 | Exp_t* exp = nullptr; |
434 | switch (item->getId()) { | 434 | switch (item->getId()) { |
435 | case id<Exp_t>(): | 435 | case id<Exp_t>(): |
@@ -451,8 +451,8 @@ private: | |||
451 | } | 451 | } |
452 | case id<unary_exp_t>(): { | 452 | case id<unary_exp_t>(): { |
453 | auto unary = static_cast<unary_exp_t*>(item); | 453 | auto unary = static_cast<unary_exp_t*>(item); |
454 | if (unary->ops.empty() && unary->expos.size() == 1) { | 454 | if (unary->expos.size() == 1) { |
455 | return static_cast<Value_t*>(unary->expos.back()); | 455 | return unary; |
456 | } | 456 | } |
457 | return nullptr; | 457 | return nullptr; |
458 | } | 458 | } |
@@ -463,13 +463,21 @@ private: | |||
463 | BREAK_IF(!exp->opValues.empty()); | 463 | BREAK_IF(!exp->opValues.empty()); |
464 | BREAK_IF(exp->backcalls.size() != 1); | 464 | BREAK_IF(exp->backcalls.size() != 1); |
465 | auto unary = static_cast<unary_exp_t*>(exp->backcalls.back()); | 465 | auto unary = static_cast<unary_exp_t*>(exp->backcalls.back()); |
466 | BREAK_IF(!unary->ops.empty()); | ||
467 | BREAK_IF(unary->expos.size() != 1); | 466 | BREAK_IF(unary->expos.size() != 1); |
468 | return static_cast<Value_t*>(unary->expos.back()); | 467 | return unary; |
469 | BLOCK_END | 468 | BLOCK_END |
470 | return nullptr; | 469 | return nullptr; |
471 | } | 470 | } |
472 | 471 | ||
472 | Value_t* singleValueFrom(ast_node* item) const { | ||
473 | if (auto unary = singleUnaryExpFrom(item)) { | ||
474 | if (unary->ops.empty()) { | ||
475 | return static_cast<Value_t*>(unary->expos.back()); | ||
476 | } | ||
477 | } | ||
478 | return nullptr; | ||
479 | } | ||
480 | |||
473 | ast_ptr<false, Exp_t> newExp(Value_t* value, ast_node* x) { | 481 | ast_ptr<false, Exp_t> newExp(Value_t* value, ast_node* x) { |
474 | auto unary = x->new_ptr<unary_exp_t>(); | 482 | auto unary = x->new_ptr<unary_exp_t>(); |
475 | unary->expos.push_back(value); | 483 | unary->expos.push_back(value); |
@@ -522,6 +530,60 @@ private: | |||
522 | return stmts.empty() ? nullptr : static_cast<Statement_t*>(stmts.back()); | 530 | return stmts.empty() ? nullptr : static_cast<Statement_t*>(stmts.back()); |
523 | } | 531 | } |
524 | 532 | ||
533 | Exp_t* lastExpFromAssign(ast_node* action) { | ||
534 | switch (action->getId()) { | ||
535 | case id<Update_t>(): { | ||
536 | auto update = static_cast<Update_t*>(action); | ||
537 | return update->value; | ||
538 | } | ||
539 | case id<Assign_t>(): { | ||
540 | auto assign = static_cast<Assign_t*>(action); | ||
541 | return ast_cast<Exp_t>(assign->values.back()); | ||
542 | } | ||
543 | } | ||
544 | return nullptr; | ||
545 | } | ||
546 | |||
547 | Exp_t* lastExpFromStatement(Statement_t* stmt) { | ||
548 | if (!stmt->content) return nullptr; | ||
549 | switch (stmt->content->getId()) { | ||
550 | case id<ExpListAssign_t>(): { | ||
551 | auto expListAssign = static_cast<ExpListAssign_t*>(stmt->content.get()); | ||
552 | if (auto action = expListAssign->action.get()) { | ||
553 | return lastExpFromAssign(action); | ||
554 | } else { | ||
555 | return static_cast<Exp_t*>(expListAssign->expList->exprs.back()); | ||
556 | } | ||
557 | } | ||
558 | case id<Export_t>(): { | ||
559 | auto exportNode = static_cast<Export_t*>(stmt->content.get()); | ||
560 | if (auto action = exportNode->assign.get()) { | ||
561 | return lastExpFromAssign(action); | ||
562 | } else { | ||
563 | switch (exportNode->target->getId()) { | ||
564 | case id<Exp_t>(): return exportNode->target.to<Exp_t>(); | ||
565 | case id<ExpList_t>(): return static_cast<Exp_t*>(exportNode->target.to<ExpList_t>()->exprs.back()); | ||
566 | } | ||
567 | } | ||
568 | } | ||
569 | case id<Local_t>(): { | ||
570 | if (auto localValues = static_cast<Local_t*>(stmt->content.get())->item.as<local_values_t>()) { | ||
571 | if (auto expList = localValues->valueList.as<ExpListLow_t>()) { | ||
572 | return static_cast<Exp_t*>(expList->exprs.back()); | ||
573 | } | ||
574 | } | ||
575 | } | ||
576 | case id<Global_t>(): { | ||
577 | if (auto globalValues = static_cast<Global_t*>(stmt->content.get())->item.as<global_values_t>()) { | ||
578 | if (auto expList = globalValues->valueList.as<ExpListLow_t>()) { | ||
579 | return static_cast<Exp_t*>(expList->exprs.back()); | ||
580 | } | ||
581 | } | ||
582 | } | ||
583 | } | ||
584 | return nullptr; | ||
585 | } | ||
586 | |||
525 | template <class T> | 587 | template <class T> |
526 | ast_ptr<false, T> toAst(std::string_view codes, ast_node* parent) { | 588 | ast_ptr<false, T> toAst(std::string_view codes, ast_node* parent) { |
527 | auto res = _parser.parse<T>(s(codes)); | 589 | auto res = _parser.parse<T>(s(codes)); |
@@ -812,6 +874,7 @@ private: | |||
812 | case id<Label_t>(): transformLabel(static_cast<Label_t*>(content), out); break; | 874 | case id<Label_t>(): transformLabel(static_cast<Label_t*>(content), out); break; |
813 | case id<Goto_t>(): transformGoto(static_cast<Goto_t*>(content), out); break; | 875 | case id<Goto_t>(): transformGoto(static_cast<Goto_t*>(content), out); break; |
814 | case id<LocalAttrib_t>(): transformLocalAttrib(static_cast<LocalAttrib_t*>(content), out); break; | 876 | case id<LocalAttrib_t>(): transformLocalAttrib(static_cast<LocalAttrib_t*>(content), out); break; |
877 | case id<BackcallBody_t>(): throw std::logic_error(_info.errorMessage("backcall chain must be following a value"sv, x)); break; | ||
815 | case id<ExpListAssign_t>(): { | 878 | case id<ExpListAssign_t>(): { |
816 | auto expListAssign = static_cast<ExpListAssign_t*>(content); | 879 | auto expListAssign = static_cast<ExpListAssign_t*>(content); |
817 | if (expListAssign->action) { | 880 | if (expListAssign->action) { |
@@ -1692,7 +1755,10 @@ private: | |||
1692 | auto begin = values.begin(); begin++; | 1755 | auto begin = values.begin(); begin++; |
1693 | for (auto it = begin; it != values.end(); ++it) { | 1756 | for (auto it = begin; it != values.end(); ++it) { |
1694 | auto unary = static_cast<unary_exp_t*>(*it); | 1757 | auto unary = static_cast<unary_exp_t*>(*it); |
1695 | auto value = singleValueFrom(unary); | 1758 | auto value = static_cast<Value_t*>(singleUnaryExpFrom(unary) ? unary->expos.back() : nullptr); |
1759 | if (values.back() == *it && !unary->ops.empty() && usage == ExpUsage::Common) { | ||
1760 | throw std::logic_error(_info.errorMessage("expression list is not supported here"sv, x)); | ||
1761 | } | ||
1696 | if (!value) throw std::logic_error(_info.errorMessage("backcall operator must be followed by chain value"sv, *it)); | 1762 | if (!value) throw std::logic_error(_info.errorMessage("backcall operator must be followed by chain value"sv, *it)); |
1697 | if (auto chainValue = value->item.as<ChainValue_t>()) { | 1763 | if (auto chainValue = value->item.as<ChainValue_t>()) { |
1698 | if (isChainValueCall(chainValue)) { | 1764 | if (isChainValueCall(chainValue)) { |
@@ -1936,7 +2002,29 @@ private: | |||
1936 | for (auto it = nodes.begin(); it != nodes.end(); ++it) { | 2002 | for (auto it = nodes.begin(); it != nodes.end(); ++it) { |
1937 | auto node = *it; | 2003 | auto node = *it; |
1938 | auto stmt = static_cast<Statement_t*>(node); | 2004 | auto stmt = static_cast<Statement_t*>(node); |
1939 | if (auto backcall = stmt->content.as<Backcall_t>()) { | 2005 | if (auto backcallBody = stmt->content.as<BackcallBody_t>()) { |
2006 | auto x = stmt; | ||
2007 | bool cond = false; | ||
2008 | BLOCK_START | ||
2009 | BREAK_IF(it == nodes.begin()); | ||
2010 | auto last = it; --last; | ||
2011 | auto lst = static_cast<Statement_t*>(*last); | ||
2012 | auto exp = lastExpFromStatement(lst); | ||
2013 | BREAK_IF(!exp); | ||
2014 | for (auto val : backcallBody->values.objects()) { | ||
2015 | exp->backcalls.push_back(val); | ||
2016 | } | ||
2017 | cond = true; | ||
2018 | BLOCK_END | ||
2019 | if (!cond) throw std::logic_error(_info.errorMessage("backcall chain must be following a value"sv, x)); | ||
2020 | stmt->content.set(nullptr); | ||
2021 | auto next = it; ++next; | ||
2022 | BLOCK_START | ||
2023 | BREAK_IF(next == nodes.end()); | ||
2024 | BREAK_IF(!static_cast<Statement_t*>(*next)->content.as<BackcallBody_t>()); | ||
2025 | throw std::logic_error(_info.errorMessage("indent mismatch in backcall chain"sv, *next)); | ||
2026 | BLOCK_END | ||
2027 | } else if (auto backcall = stmt->content.as<Backcall_t>()) { | ||
1940 | auto x = *nodes.begin(); | 2028 | auto x = *nodes.begin(); |
1941 | auto newBlock = x->new_ptr<Block_t>(); | 2029 | auto newBlock = x->new_ptr<Block_t>(); |
1942 | if (it != nodes.begin()) { | 2030 | if (it != nodes.begin()) { |
diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp index 63ffec7..f15492f 100644 --- a/src/MoonP/moon_parser.cpp +++ b/src/MoonP/moon_parser.cpp | |||
@@ -319,7 +319,7 @@ MoonParser::MoonParser() { | |||
319 | unary_exp = *(Space >> unary_operator) >> expo_exp; | 319 | unary_exp = *(Space >> unary_operator) >> expo_exp; |
320 | 320 | ||
321 | BackcallOperator = expr("|>"); | 321 | BackcallOperator = expr("|>"); |
322 | backcall_value = White >> BackcallOperator >> *SpaceBreak >> unary_exp; | 322 | backcall_value = Space >> BackcallOperator >> *SpaceBreak >> unary_exp; |
323 | backcall_exp = unary_exp >> *backcall_value; | 323 | backcall_exp = unary_exp >> *backcall_value; |
324 | 324 | ||
325 | BinaryOperator = | 325 | BinaryOperator = |
@@ -522,6 +522,8 @@ MoonParser::MoonParser() { | |||
522 | fn_arrow_back = expr('<') >> set("-="); | 522 | fn_arrow_back = expr('<') >> set("-="); |
523 | Backcall = -FnArgsDef >> Space >> fn_arrow_back >> Space >> ChainValue; | 523 | Backcall = -FnArgsDef >> Space >> fn_arrow_back >> Space >> ChainValue; |
524 | 524 | ||
525 | BackcallBody = Seperator >> Space >> BackcallOperator >> unary_exp >> *(+SpaceBreak >> CheckIndent >> Space >> BackcallOperator >> unary_exp); | ||
526 | |||
525 | ExpList = Seperator >> Exp >> *(sym(',') >> Exp); | 527 | ExpList = Seperator >> Exp >> *(sym(',') >> Exp); |
526 | ExpListLow = Seperator >> Exp >> *(Space >> set(",;") >> Exp); | 528 | ExpListLow = Seperator >> Exp >> *(Space >> set(",;") >> Exp); |
527 | 529 | ||
@@ -562,14 +564,14 @@ MoonParser::MoonParser() { | |||
562 | Import | While | Repeat | For | ForEach | | 564 | Import | While | Repeat | For | ForEach | |
563 | Return | Local | Global | Export | Macro | | 565 | Return | Local | Global | Export | Macro | |
564 | Space >> BreakLoop | Label | Goto | Backcall | | 566 | Space >> BreakLoop | Label | Goto | Backcall | |
565 | LocalAttrib | ExpListAssign | 567 | LocalAttrib | BackcallBody | ExpListAssign |
566 | ) >> Space >> | 568 | ) >> Space >> |
567 | -statement_appendix >> -statement_sep; | 569 | -statement_appendix >> -statement_sep; |
568 | 570 | ||
569 | Body = Space >> Break >> *EmptyLine >> InBlock | Statement; | 571 | Body = Space >> Break >> *EmptyLine >> InBlock | Statement; |
570 | 572 | ||
571 | empty_line_stop = Space >> and_(Stop); | 573 | empty_line_stop = Space >> and_(Stop); |
572 | Line = CheckIndent >> Statement | empty_line_stop; | 574 | Line = CheckIndent >> Statement | and_(Space >> BackcallOperator) >> Advance >> ensure(Statement, PopIndent) | empty_line_stop; |
573 | Block = Seperator >> Line >> *(+Break >> Line); | 575 | Block = Seperator >> Line >> *(+Break >> Line); |
574 | 576 | ||
575 | Shebang = expr("#!") >> *(not_(Stop) >> Any); | 577 | Shebang = expr("#!") >> *(not_(Stop) >> Any); |
diff --git a/src/MoonP/moon_parser.h b/src/MoonP/moon_parser.h index f036a7c..bee3c9c 100644 --- a/src/MoonP/moon_parser.h +++ b/src/MoonP/moon_parser.h | |||
@@ -209,6 +209,7 @@ private: | |||
209 | AST_RULE(Goto) | 209 | AST_RULE(Goto) |
210 | AST_RULE(fn_arrow_back) | 210 | AST_RULE(fn_arrow_back) |
211 | AST_RULE(Backcall) | 211 | AST_RULE(Backcall) |
212 | AST_RULE(BackcallBody) | ||
212 | AST_RULE(ExpListLow) | 213 | AST_RULE(ExpListLow) |
213 | AST_RULE(ExpList) | 214 | AST_RULE(ExpList) |
214 | AST_RULE(Return) | 215 | AST_RULE(Return) |