diff options
author | Li Jin <dragon-fly@qq.com> | 2020-03-24 10:19:30 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2020-03-24 10:19:30 +0800 |
commit | 2447d158241aeaaf9c0b1ab21a08db7a40e5cef3 (patch) | |
tree | a8c17610aae77e61ee713b090546e3ae7d35f967 | |
parent | 14d7e02285857226e26288c1ac83a14eb4fbd478 (diff) | |
download | yuescript-2447d158241aeaaf9c0b1ab21a08db7a40e5cef3.tar.gz yuescript-2447d158241aeaaf9c0b1ab21a08db7a40e5cef3.tar.bz2 yuescript-2447d158241aeaaf9c0b1ab21a08db7a40e5cef3.zip |
add goto statement support.
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | spec/inputs/goto.moon | 41 | ||||
-rw-r--r-- | src/MoonP/moon_ast.h | 17 | ||||
-rw-r--r-- | src/MoonP/moon_compiler.cpp | 12 | ||||
-rw-r--r-- | src/MoonP/moon_parser.cpp | 33 | ||||
-rw-r--r-- | src/MoonP/moon_parser.h | 3 |
6 files changed, 96 insertions, 12 deletions
@@ -42,6 +42,8 @@ f! | |||
42 | 42 | ||
43 | The original Moonscript language 0.5.0 support can be found in the `0.5.0` branch. Moonscript with new features is in the master branch. Here are the new features introduced in MoonPlus. | 43 | The original Moonscript language 0.5.0 support can be found in the `0.5.0` branch. Moonscript with new features is in the master branch. Here are the new features introduced in MoonPlus. |
44 | 44 | ||
45 | * Add goto statement support. | ||
46 | |||
45 | * Add macro functions. | 47 | * Add macro functions. |
46 | ```Moonscript | 48 | ```Moonscript |
47 | -- file 'macro.moon' | 49 | -- file 'macro.moon' |
diff --git a/spec/inputs/goto.moon b/spec/inputs/goto.moon new file mode 100644 index 0000000..3410ca3 --- /dev/null +++ b/spec/inputs/goto.moon | |||
@@ -0,0 +1,41 @@ | |||
1 | do | ||
2 | a = 0 | ||
3 | ::start:: | ||
4 | a += 1 | ||
5 | goto done if a == 5 | ||
6 | goto start | ||
7 | ::done:: | ||
8 | |||
9 | do | ||
10 | for z = 1, 10 for y = 1, 10 for x = 1, 10 | ||
11 | if x^2 + y^2 == z^2 | ||
12 | print 'found a Pythagorean triple:', x, y, z | ||
13 | goto done | ||
14 | ::done:: | ||
15 | |||
16 | do | ||
17 | for z = 1, 10 | ||
18 | for y = 1, 10 for x = 1, 10 | ||
19 | if x^2 + y^2 == z^2 | ||
20 | print 'found a Pythagorean triple:', x, y, z | ||
21 | print 'now trying next z...' | ||
22 | goto zcontinue | ||
23 | ::zcontinue:: | ||
24 | |||
25 | do | ||
26 | ::redo:: | ||
27 | for x = 1, 10 for y = 1, 10 | ||
28 | if not f x, y then goto continue | ||
29 | if not g x, y then goto skip | ||
30 | if not h x, y then goto redo | ||
31 | ::continue:: | ||
32 | ::skip:: | ||
33 | |||
34 | do | ||
35 | for x in *t | ||
36 | if x % 2 == 0 | ||
37 | print 'list has even number' | ||
38 | goto has | ||
39 | print 'list lacks even number' | ||
40 | ::has:: | ||
41 | |||
diff --git a/src/MoonP/moon_ast.h b/src/MoonP/moon_ast.h index 0725bda..3f9ce79 100644 --- a/src/MoonP/moon_ast.h +++ b/src/MoonP/moon_ast.h | |||
@@ -46,6 +46,11 @@ AST_NODE(Variable) | |||
46 | AST_MEMBER(Variable, &name) | 46 | AST_MEMBER(Variable, &name) |
47 | AST_END(Variable) | 47 | AST_END(Variable) |
48 | 48 | ||
49 | AST_NODE(LabelName) | ||
50 | ast_ptr<true, Name_t> name; | ||
51 | AST_MEMBER(LabelName, &name) | ||
52 | AST_END(LabelName) | ||
53 | |||
49 | AST_NODE(LuaKeyword) | 54 | AST_NODE(LuaKeyword) |
50 | ast_ptr<true, Name_t> name; | 55 | ast_ptr<true, Name_t> name; |
51 | AST_MEMBER(LuaKeyword, &name) | 56 | AST_MEMBER(LuaKeyword, &name) |
@@ -142,6 +147,16 @@ AST_NODE(Import) | |||
142 | AST_MEMBER(Import, &content) | 147 | AST_MEMBER(Import, &content) |
143 | AST_END(Import) | 148 | AST_END(Import) |
144 | 149 | ||
150 | AST_NODE(Label) | ||
151 | ast_ptr<true, LabelName_t> label; | ||
152 | AST_MEMBER(Label, &label) | ||
153 | AST_END(Label) | ||
154 | |||
155 | AST_NODE(Goto) | ||
156 | ast_ptr<true, LabelName_t> label; | ||
157 | AST_MEMBER(Goto, &label) | ||
158 | AST_END(Goto) | ||
159 | |||
145 | class FnArgsDef_t; | 160 | class FnArgsDef_t; |
146 | 161 | ||
147 | AST_LEAF(fn_arrow_back) | 162 | AST_LEAF(fn_arrow_back) |
@@ -650,7 +665,7 @@ AST_END(BreakLoop) | |||
650 | AST_NODE(Statement) | 665 | AST_NODE(Statement) |
651 | ast_sel<true, Import_t, While_t, For_t, ForEach_t, | 666 | ast_sel<true, Import_t, While_t, For_t, ForEach_t, |
652 | Return_t, Local_t, Global_t, Export_t, Macro_t, BreakLoop_t, | 667 | Return_t, Local_t, Global_t, Export_t, Macro_t, BreakLoop_t, |
653 | Backcall_t, ExpListAssign_t> content; | 668 | Label_t, Goto_t, Backcall_t, ExpListAssign_t> content; |
654 | ast_ptr<false, statement_appendix_t> appendix; | 669 | ast_ptr<false, statement_appendix_t> appendix; |
655 | AST_MEMBER(Statement, &content, &appendix) | 670 | AST_MEMBER(Statement, &content, &appendix) |
656 | AST_END(Statement) | 671 | AST_END(Statement) |
diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index c176c01..b89f6d1 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp | |||
@@ -43,7 +43,7 @@ inline std::string s(std::string_view sv) { | |||
43 | } | 43 | } |
44 | 44 | ||
45 | const char* moonScriptVersion() { | 45 | const char* moonScriptVersion() { |
46 | return "0.5.0-r0.3.4"; | 46 | return "0.5.0-r0.3.5"; |
47 | } | 47 | } |
48 | 48 | ||
49 | // name of table stored in lua registry | 49 | // name of table stored in lua registry |
@@ -750,6 +750,8 @@ private: | |||
750 | case id<Export_t>(): transformExport(static_cast<Export_t*>(content), out); break; | 750 | case id<Export_t>(): transformExport(static_cast<Export_t*>(content), out); break; |
751 | case id<Macro_t>(): transformMacro(static_cast<Macro_t*>(content), out, false); break; | 751 | case id<Macro_t>(): transformMacro(static_cast<Macro_t*>(content), out, false); break; |
752 | case id<BreakLoop_t>(): transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; | 752 | case id<BreakLoop_t>(): transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; |
753 | case id<Label_t>(): transformLabel(static_cast<Label_t*>(content), out); break; | ||
754 | case id<Goto_t>(): transformGoto(static_cast<Goto_t*>(content), out); break; | ||
753 | case id<ExpListAssign_t>(): { | 755 | case id<ExpListAssign_t>(): { |
754 | auto expListAssign = static_cast<ExpListAssign_t*>(content); | 756 | auto expListAssign = static_cast<ExpListAssign_t*>(content); |
755 | if (expListAssign->action) { | 757 | if (expListAssign->action) { |
@@ -4997,6 +4999,14 @@ private: | |||
4997 | _buf << indent() << "break"sv << nll(breakLoop); | 4999 | _buf << indent() << "break"sv << nll(breakLoop); |
4998 | out.push_back(clearBuf()); | 5000 | out.push_back(clearBuf()); |
4999 | } | 5001 | } |
5002 | |||
5003 | void transformLabel(Label_t* label, str_list& out) { | ||
5004 | out.push_back(indent() + s("::"sv) + _parser.toString(label->label) + s("::"sv) + nll(label)); | ||
5005 | } | ||
5006 | |||
5007 | void transformGoto(Goto_t* gotoNode, str_list& out) { | ||
5008 | out.push_back(indent() + s("goto "sv) + _parser.toString(gotoNode->label) + nll(gotoNode)); | ||
5009 | } | ||
5000 | }; | 5010 | }; |
5001 | 5011 | ||
5002 | const std::string MoonCompilerImpl::Empty; | 5012 | const std::string MoonCompilerImpl::Empty; |
diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp index c8a3a23..872e30e 100644 --- a/src/MoonP/moon_parser.cpp +++ b/src/MoonP/moon_parser.cpp | |||
@@ -15,18 +15,18 @@ using namespace std::string_view_literals; | |||
15 | 15 | ||
16 | std::unordered_set<std::string> LuaKeywords = { | 16 | std::unordered_set<std::string> LuaKeywords = { |
17 | "and", "break", "do", "else", "elseif", | 17 | "and", "break", "do", "else", "elseif", |
18 | "end", "false", "for", "function", "if", | 18 | "end", "false", "for", "function", "goto", |
19 | "in", "local", "nil", "not", "or", | 19 | "if", "in", "local", "nil", "not", |
20 | "repeat", "return", "then", "true", "until", | 20 | "or", "repeat", "return", "then", "true", |
21 | "while" | 21 | "until", "while" |
22 | }; | 22 | }; |
23 | 23 | ||
24 | std::unordered_set<std::string> Keywords = { | 24 | std::unordered_set<std::string> Keywords = { |
25 | "and", "break", "do", "else", "elseif", | 25 | "and", "break", "do", "else", "elseif", |
26 | "end", "false", "for", "function", "if", | 26 | "end", "false", "for", "function", "goto", |
27 | "in", "local", "nil", "not", "or", | 27 | "if", "in", "local", "nil", "not", |
28 | "repeat", "return", "then", "true", "until", | 28 | "or", "repeat", "return", "then", "true", |
29 | "while", // Lua keywords | 29 | "until", "while", // Lua keywords |
30 | "as", "class", "continue", "export", "extends", | 30 | "as", "class", "continue", "export", "extends", |
31 | "from", "global", "import", "macro", "switch", | 31 | "from", "global", "import", "macro", "switch", |
32 | "unless", "using", "when", "with" // Moon keywords | 32 | "unless", "using", "when", "with" // Moon keywords |
@@ -85,6 +85,14 @@ MoonParser::MoonParser() { | |||
85 | return isValid; | 85 | return isValid; |
86 | }); | 86 | }); |
87 | 87 | ||
88 | LabelName = pl::user(Name, [](const item_t& item) { | ||
89 | State* st = reinterpret_cast<State*>(item.user_data); | ||
90 | for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); | ||
91 | auto isValid = LuaKeywords.find(st->buffer) == LuaKeywords.end(); | ||
92 | st->buffer.clear(); | ||
93 | return isValid; | ||
94 | }); | ||
95 | |||
88 | LuaKeyword = pl::user(Name, [](const item_t& item) { | 96 | LuaKeyword = pl::user(Name, [](const item_t& item) { |
89 | State* st = reinterpret_cast<State*>(item.user_data); | 97 | State* st = reinterpret_cast<State*>(item.user_data); |
90 | for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); | 98 | for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); |
@@ -191,9 +199,14 @@ MoonParser::MoonParser() { | |||
191 | 199 | ||
192 | Import = key("import") >> (ImportAs | ImportFrom); | 200 | Import = key("import") >> (ImportAs | ImportFrom); |
193 | 201 | ||
202 | Label = Space >> expr("::") >> LabelName >> expr("::"); | ||
203 | |||
204 | Goto = key("goto") >> Space >> LabelName; | ||
205 | |||
194 | BreakLoop = (expr("break") | expr("continue")) >> not_(AlphaNum); | 206 | BreakLoop = (expr("break") | expr("continue")) >> not_(AlphaNum); |
195 | 207 | ||
196 | Return = key("return") >> -ExpListLow; | 208 | Return = key("return") >> -ExpListLow; |
209 | |||
197 | WithExp = ExpList >> -Assign; | 210 | WithExp = ExpList >> -Assign; |
198 | 211 | ||
199 | With = key("with") >> DisableDo >> ensure(WithExp, PopDo) >> -key("do") >> Body; | 212 | With = key("with") >> DisableDo >> ensure(WithExp, PopDo) >> -key("do") >> Body; |
@@ -527,8 +540,8 @@ MoonParser::MoonParser() { | |||
527 | Statement = ( | 540 | Statement = ( |
528 | Import | While | For | ForEach | | 541 | Import | While | For | ForEach | |
529 | Return | Local | Global | Export | | 542 | Return | Local | Global | Export | |
530 | Macro | Space >> BreakLoop | | 543 | Macro | Space >> BreakLoop | Label | |
531 | Backcall | ExpListAssign | 544 | Goto | Backcall | ExpListAssign |
532 | ) >> Space >> | 545 | ) >> Space >> |
533 | -statement_appendix; | 546 | -statement_appendix; |
534 | 547 | ||
diff --git a/src/MoonP/moon_parser.h b/src/MoonP/moon_parser.h index 4d67696..cea14fa 100644 --- a/src/MoonP/moon_parser.h +++ b/src/MoonP/moon_parser.h | |||
@@ -182,6 +182,7 @@ private: | |||
182 | AST_RULE(Num) | 182 | AST_RULE(Num) |
183 | AST_RULE(Name) | 183 | AST_RULE(Name) |
184 | AST_RULE(Variable) | 184 | AST_RULE(Variable) |
185 | AST_RULE(LabelName) | ||
185 | AST_RULE(LuaKeyword) | 186 | AST_RULE(LuaKeyword) |
186 | AST_RULE(self) | 187 | AST_RULE(self) |
187 | AST_RULE(self_name) | 188 | AST_RULE(self_name) |
@@ -201,6 +202,8 @@ private: | |||
201 | AST_RULE(ImportFrom) | 202 | AST_RULE(ImportFrom) |
202 | AST_RULE(ImportAs) | 203 | AST_RULE(ImportAs) |
203 | AST_RULE(Import) | 204 | AST_RULE(Import) |
205 | AST_RULE(Label) | ||
206 | AST_RULE(Goto) | ||
204 | AST_RULE(fn_arrow_back) | 207 | AST_RULE(fn_arrow_back) |
205 | AST_RULE(Backcall) | 208 | AST_RULE(Backcall) |
206 | AST_RULE(ExpListLow) | 209 | AST_RULE(ExpListLow) |