From 2447d158241aeaaf9c0b1ab21a08db7a40e5cef3 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Tue, 24 Mar 2020 10:19:30 +0800 Subject: add goto statement support. --- README.md | 2 ++ spec/inputs/goto.moon | 41 +++++++++++++++++++++++++++++++++++++++++ src/MoonP/moon_ast.h | 17 ++++++++++++++++- src/MoonP/moon_compiler.cpp | 12 +++++++++++- src/MoonP/moon_parser.cpp | 33 +++++++++++++++++++++++---------- src/MoonP/moon_parser.h | 3 +++ 6 files changed, 96 insertions(+), 12 deletions(-) create mode 100644 spec/inputs/goto.moon diff --git a/README.md b/README.md index 319e821..c8159c4 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,8 @@ f! 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. +* Add goto statement support. + * Add macro functions. ```Moonscript -- 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 @@ +do + a = 0 + ::start:: + a += 1 + goto done if a == 5 + goto start + ::done:: + +do + for z = 1, 10 for y = 1, 10 for x = 1, 10 + if x^2 + y^2 == z^2 + print 'found a Pythagorean triple:', x, y, z + goto done + ::done:: + +do + for z = 1, 10 + for y = 1, 10 for x = 1, 10 + if x^2 + y^2 == z^2 + print 'found a Pythagorean triple:', x, y, z + print 'now trying next z...' + goto zcontinue + ::zcontinue:: + +do + ::redo:: + for x = 1, 10 for y = 1, 10 + if not f x, y then goto continue + if not g x, y then goto skip + if not h x, y then goto redo + ::continue:: + ::skip:: + +do + for x in *t + if x % 2 == 0 + print 'list has even number' + goto has + print 'list lacks even number' + ::has:: + 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) AST_MEMBER(Variable, &name) AST_END(Variable) +AST_NODE(LabelName) + ast_ptr name; + AST_MEMBER(LabelName, &name) +AST_END(LabelName) + AST_NODE(LuaKeyword) ast_ptr name; AST_MEMBER(LuaKeyword, &name) @@ -142,6 +147,16 @@ AST_NODE(Import) AST_MEMBER(Import, &content) AST_END(Import) +AST_NODE(Label) + ast_ptr label; + AST_MEMBER(Label, &label) +AST_END(Label) + +AST_NODE(Goto) + ast_ptr label; + AST_MEMBER(Goto, &label) +AST_END(Goto) + class FnArgsDef_t; AST_LEAF(fn_arrow_back) @@ -650,7 +665,7 @@ AST_END(BreakLoop) AST_NODE(Statement) ast_sel content; + Label_t, Goto_t, Backcall_t, ExpListAssign_t> content; ast_ptr appendix; AST_MEMBER(Statement, &content, &appendix) 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) { } const char* moonScriptVersion() { - return "0.5.0-r0.3.4"; + return "0.5.0-r0.3.5"; } // name of table stored in lua registry @@ -750,6 +750,8 @@ private: case id(): transformExport(static_cast(content), out); break; case id(): transformMacro(static_cast(content), out, false); break; case id(): transformBreakLoop(static_cast(content), out); break; + case id(): transformLabel(static_cast(content), out); break; + case id(): transformGoto(static_cast(content), out); break; case id(): { auto expListAssign = static_cast(content); if (expListAssign->action) { @@ -4997,6 +4999,14 @@ private: _buf << indent() << "break"sv << nll(breakLoop); out.push_back(clearBuf()); } + + void transformLabel(Label_t* label, str_list& out) { + out.push_back(indent() + s("::"sv) + _parser.toString(label->label) + s("::"sv) + nll(label)); + } + + void transformGoto(Goto_t* gotoNode, str_list& out) { + out.push_back(indent() + s("goto "sv) + _parser.toString(gotoNode->label) + nll(gotoNode)); + } }; 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; std::unordered_set LuaKeywords = { "and", "break", "do", "else", "elseif", - "end", "false", "for", "function", "if", - "in", "local", "nil", "not", "or", - "repeat", "return", "then", "true", "until", - "while" + "end", "false", "for", "function", "goto", + "if", "in", "local", "nil", "not", + "or", "repeat", "return", "then", "true", + "until", "while" }; std::unordered_set Keywords = { "and", "break", "do", "else", "elseif", - "end", "false", "for", "function", "if", - "in", "local", "nil", "not", "or", - "repeat", "return", "then", "true", "until", - "while", // Lua keywords + "end", "false", "for", "function", "goto", + "if", "in", "local", "nil", "not", + "or", "repeat", "return", "then", "true", + "until", "while", // Lua keywords "as", "class", "continue", "export", "extends", "from", "global", "import", "macro", "switch", "unless", "using", "when", "with" // Moon keywords @@ -85,6 +85,14 @@ MoonParser::MoonParser() { return isValid; }); + LabelName = pl::user(Name, [](const item_t& item) { + State* st = reinterpret_cast(item.user_data); + for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast(*it); + auto isValid = LuaKeywords.find(st->buffer) == LuaKeywords.end(); + st->buffer.clear(); + return isValid; + }); + LuaKeyword = pl::user(Name, [](const item_t& item) { State* st = reinterpret_cast(item.user_data); for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast(*it); @@ -191,9 +199,14 @@ MoonParser::MoonParser() { Import = key("import") >> (ImportAs | ImportFrom); + Label = Space >> expr("::") >> LabelName >> expr("::"); + + Goto = key("goto") >> Space >> LabelName; + BreakLoop = (expr("break") | expr("continue")) >> not_(AlphaNum); Return = key("return") >> -ExpListLow; + WithExp = ExpList >> -Assign; With = key("with") >> DisableDo >> ensure(WithExp, PopDo) >> -key("do") >> Body; @@ -527,8 +540,8 @@ MoonParser::MoonParser() { Statement = ( Import | While | For | ForEach | Return | Local | Global | Export | - Macro | Space >> BreakLoop | - Backcall | ExpListAssign + Macro | Space >> BreakLoop | Label | + Goto | Backcall | ExpListAssign ) >> Space >> -statement_appendix; 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: AST_RULE(Num) AST_RULE(Name) AST_RULE(Variable) + AST_RULE(LabelName) AST_RULE(LuaKeyword) AST_RULE(self) AST_RULE(self_name) @@ -201,6 +202,8 @@ private: AST_RULE(ImportFrom) AST_RULE(ImportAs) AST_RULE(Import) + AST_RULE(Label) + AST_RULE(Goto) AST_RULE(fn_arrow_back) AST_RULE(Backcall) AST_RULE(ExpListLow) -- cgit v1.2.3-55-g6feb