From 8d1af508f4173e4af6a4ea98584c1a86619f6a20 Mon Sep 17 00:00:00 2001 From: Li Jin <dragon-fly@qq.com> Date: Sat, 18 Jan 2020 18:15:24 +0800 Subject: fix Moonscript issue 122, add support for ? operator. --- makefile | 2 +- spec/inputs/assign.moon | 2 +- spec/inputs/class.moon | 30 +-- spec/inputs/comprehension.moon | 14 +- spec/inputs/cond.moon | 12 +- spec/inputs/destructure.moon | 2 +- spec/inputs/do.moon | 2 +- spec/inputs/existential.moon | 8 + spec/inputs/funcs.moon | 30 +-- spec/inputs/lists.moon | 8 +- spec/inputs/literals.moon | 62 ++--- spec/inputs/local.moon | 2 +- spec/inputs/loops.moon | 12 +- spec/inputs/return.moon | 8 +- spec/inputs/string.moon | 2 +- spec/inputs/switch.moon | 10 +- spec/inputs/syntax.moon | 42 ++-- spec/inputs/tables.moon | 2 +- spec/inputs/using.moon | 8 +- spec/inputs/whitespace.moon | 22 +- spec/inputs/with.moon | 4 +- src/MoonP/ast.hpp | 6 + src/MoonP/moon_ast.cpp | 1 + src/MoonP/moon_ast.h | 5 +- src/MoonP/moon_compiler.cpp | 508 +++++++++++++++++++++++++++++------------ src/MoonP/moon_parser.cpp | 15 +- src/moonc.cpp | 12 +- 27 files changed, 523 insertions(+), 308 deletions(-) create mode 100644 spec/inputs/existential.moon diff --git a/makefile b/makefile index 5042b08..a3379a4 100644 --- a/makefile +++ b/makefile @@ -206,7 +206,7 @@ clean: .PHONY: test test: release @echo "Compiling Moonscript codes..." - @./$(BIN_NAME) $(TEST_INPUT)/*.moon -a -s -t $(TEST_OUTPUT) + @./$(BIN_NAME) $(TEST_INPUT)/*.moon -l -t $(TEST_OUTPUT) # Main rule, checks the executable and symlinks to the output all: $(BIN_PATH)/$(BIN_NAME) diff --git a/spec/inputs/assign.moon b/spec/inputs/assign.moon index 1e5e7a6..3e66491 100644 --- a/spec/inputs/assign.moon +++ b/spec/inputs/assign.moon @@ -1,5 +1,5 @@ --> +_ = -> joop = 2302 (hi) -> diff --git a/spec/inputs/class.moon b/spec/inputs/class.moon index 9a98055..2290bc7 100644 --- a/spec/inputs/class.moon +++ b/spec/inputs/class.moon @@ -73,11 +73,11 @@ class CoolSuper hi: => super(1,2,3,4) 1,2,3,4 super.something 1,2,3,4 - super.something(1,2,3,4).world + _ = super.something(1,2,3,4).world super\yeah"world".okay hi, hi, hi - something.super - super.super.super.super - super\hello + _ = something.super + _ = super.super.super.super + _ = super\hello nil @@ -114,11 +114,11 @@ y = @@ @ = 343 @.hello 2,3,4 -hello[@].world +_ = hello[@].world class Whacko - @hello + _ = @hello if something print "hello world" @@ -132,20 +132,20 @@ print "hello" yyy = -> class Cool - nil + _ = nil -- class a.b.c.D - nil + _ = nil class a.b["hello"] - nil + _ = nil class (-> require "moon")!.Something extends Hello.World - nil + _ = nil -- @@ -160,7 +160,7 @@ print (class WhatsUp).__name export ^ class Something - nil + _ = nil -- @@ -197,17 +197,17 @@ class Whack extends Thing class Wowha extends Thing @butt: -> super! - super.hello + _ = super.hello super\hello! - super\hello + _ = super\hello @zone: cool { -> super! - super.hello + _ = super.hello super\hello! - super\hello + _ = super\hello } nil diff --git a/spec/inputs/comprehension.moon b/spec/inputs/comprehension.moon index 1609d79..f07cf89 100644 --- a/spec/inputs/comprehension.moon +++ b/spec/inputs/comprehension.moon @@ -11,11 +11,11 @@ copy = {k,v for k,v in pairs x when k != "okay"} -- -{ unpack(x) for x in yes } -{ unpack(x) for x in *yes } +_ = { unpack(x) for x in yes } +_ = { unpack(x) for x in *yes } -{ xxxx for x in yes } -{ unpack [a*i for i, a in ipairs x] for x in *{{1,2}, {3,4}} } +_ = { xxxx for x in yes } +_ = { unpack [a*i for i, a in ipairs x] for x in *{{1,2}, {3,4}} } -- @@ -28,7 +28,7 @@ bb = [y for thing in y for i=1,10] cc = [y for i=1,10 for thing in y] dd = [y for i=1,10 when cool for thing in y when x > 3 when c + 3] -{"hello", "world" for i=1,10} +_ = {"hello", "world" for i=1,10} -- @@ -44,8 +44,8 @@ ok(a,b,c) for {a,b,c} in things -- -[item for item in *items[1 + 2,3+4]] -[item for item in *items[hello! * 4, 2 - thing[4]]] +_ = [item for item in *items[1 + 2,3+4]] +_ = [item for item in *items[hello! * 4, 2 - thing[4]]] diff --git a/spec/inputs/cond.moon b/spec/inputs/cond.moon index 18e42b9..e8b6283 100644 --- a/spec/inputs/cond.moon +++ b/spec/inputs/cond.moon @@ -1,25 +1,25 @@ you_cool = false -if cool +_ = if cool if you_cool one else if eatdic yeah else - two + _ = two three else no -if cool then no -if cool then no else yes +_ = if cool then no +_ = if cool then no else yes if cool then wow cool else noso cool if working - if cool then if cool then okay else what else nah + _ = if cool then if cool then okay else what else nah if yeah then no day elseif cool me then okay ya else u way @@ -70,7 +70,7 @@ hello = 5 + if something = 10 z = false -if false +_ = if false one elseif x = true two diff --git a/spec/inputs/destructure.moon b/spec/inputs/destructure.moon index beb79d6..2509968 100644 --- a/spec/inputs/destructure.moon +++ b/spec/inputs/destructure.moon @@ -90,7 +90,7 @@ do do {a,b,c} = z -(z) -> +_ = (z) -> {a,b,c} = z do diff --git a/spec/inputs/do.moon b/spec/inputs/do.moon index 334e68f..21e2127 100644 --- a/spec/inputs/do.moon +++ b/spec/inputs/do.moon @@ -11,7 +11,7 @@ y = do things = "shhh" -> "hello: " .. things --> if something then do "yeah" +_ = -> if something then do "yeah" t = { y: do diff --git a/spec/inputs/existential.moon b/spec/inputs/existential.moon new file mode 100644 index 0000000..97e8de0 --- /dev/null +++ b/spec/inputs/existential.moon @@ -0,0 +1,8 @@ +if {:x} = a?.if?\then?(123)? @?\function 998 + print x + +with abc?!\func?! + if \p? "abc" + return 123 + +@?\func 998 diff --git a/spec/inputs/funcs.moon b/spec/inputs/funcs.moon index 08a29b6..7a4d5d6 100644 --- a/spec/inputs/funcs.moon +++ b/spec/inputs/funcs.moon @@ -2,9 +2,9 @@ x = -> print what --> +_ = -> --> -> -> +_ = -> -> -> go to the barn @@ -27,29 +27,29 @@ x = (...) -> hello! hello.world! -hello!.something -what!["ofefe"] +_ = hello!.something +_ = what!["ofefe"] what! the! heck! -(a,b,c,d,e) -> +_ = (a,b,c,d,e) -> -(a,a,a,a,a) -> +_ = (a,a,a,a,a) -> print a -(x=23023) -> +_ = (x=23023) -> -(x=(y=()->) ->) -> +_ = (x=(y=()->) ->) -> -(x = if something then yeah else no) -> +_ = (x = if something then yeah else no) -> something = (hello=100, world=(x=[[yeah cool]])-> print "eat rice") -> print hello -(x, y) => -(@x, @y) => -(x=1) => -(@x=1,y,@z="hello world") => +_ = (x, y) => +_ = (@x, @y) => +_ = (x=1) => +_ = (@x=1,y,@z="hello world") => x -> return @@ -57,7 +57,7 @@ y -> return 1 z -> return 1, "hello", "world" k -> if yes then return else return --> real_name if something +_ = -> real_name if something -- @@ -97,7 +97,7 @@ f( x = (a, b) -> - print "what" + print "what" y = (a="hi", diff --git a/spec/inputs/lists.moon b/spec/inputs/lists.moon index c119185..e377d5e 100644 --- a/spec/inputs/lists.moon +++ b/spec/inputs/lists.moon @@ -3,14 +3,14 @@ hi = [x*2 for _, x in ipairs{1,2,3,4}] items = {1,2,3,4,5,6} -[z for z in ipairs items when z > 4] +_ = [z for z in ipairs items when z > 4] rad = [{a} for a in ipairs { 1,2,3,4,5,6, } when good_number a] -[z for z in items for j in list when z > 4] +_ = [z for z in items for j in list when z > 4] require "util" @@ -32,7 +32,7 @@ print x,y for x in ipairs{1,2,4} for y in ipairs{1,2,3} when x != 2 print "hello", x for x in items -[x for x in x] +_ = [x for x in x] x = [x for x in x] print x,y for x in ipairs{1,2,4} for y in ipairs{1,2,3} when x != 2 @@ -67,6 +67,6 @@ normal = (hello) -> test = x 1,2,3,4,5 print thing for thing in *test --> a = b for row in *rows +_ = -> a = b for row in *rows diff --git a/spec/inputs/literals.moon b/spec/inputs/literals.moon index c3a24a6..d4b0326 100644 --- a/spec/inputs/literals.moon +++ b/spec/inputs/literals.moon @@ -1,46 +1,46 @@ +_ = { + 121 + 121.2323 + 121.2323e-1 + 121.2323e13434 + 2323E34 + 0x12323 -121 -121.2323 -121.2323e-1 -121.2323e13434 -2323E34 -0x12323 + 0xfF2323 + 0xabcdef + 0xABCDEF -0xfF2323 -0xabcdef -0xABCDEF + .2323 + .2323e-1 + .2323e13434 -.2323 -.2323e-1 -.2323e13434 + 1LL + 1ULL + 9332LL + 9332 + 0x2aLL + 0x2aULL -1LL -1ULL -9332LL -9332 -0x2aLL -0x2aULL + [[ hello world ]] -[[ hello world ]] + [=[ hello world ]=] + [====[ hello world ]====] -[=[ hello world ]=] -[====[ hello world ]====] + "another world" -"another world" + 'what world' -'what world' + " + hello world + " -" -hello world -" - -'yeah -what is going on -here is something cool' - + 'yeah + what is going on + here is something cool' +} nil diff --git a/spec/inputs/local.moon b/spec/inputs/local.moon index fec78b1..f14f575 100644 --- a/spec/inputs/local.moon +++ b/spec/inputs/local.moon @@ -89,6 +89,6 @@ do do local * -- this generates a nil value in the body - for a in *{} do a + for a in *{} do _ = a g = 2323 -- test if anything leaked diff --git a/spec/inputs/loops.moon b/spec/inputs/loops.moon index a704e56..130570e 100644 --- a/spec/inputs/loops.moon +++ b/spec/inputs/loops.moon @@ -33,7 +33,7 @@ for x in y, z, k x = -> for x in y - y + _ = y hello = {1,2,3,4,5} @@ -43,7 +43,7 @@ x = for y in *hello x = -> for x in *hello - y + _ = y t = for i=10,20 do i * 2 @@ -52,11 +52,11 @@ y = for j = 3,30, 8 hmm += 1 j * hmm --> +_ = -> for k=10,40 - "okay" + _ = "okay" --> +_ = -> return for k=10,40 "okay" @@ -68,7 +68,7 @@ while 5 + 5 while also do i work too - "okay" + _ = "okay" i = 0 x = while i < 10 diff --git a/spec/inputs/return.moon b/spec/inputs/return.moon index 61d3dca..98c3104 100644 --- a/spec/inputs/return.moon +++ b/spec/inputs/return.moon @@ -1,7 +1,7 @@ -- testing `return` propagation --> x for x in *things --> [x for x in *things] +_ = -> _ = x for x in *things +_ = -> [x for x in *things] -- doesn't make sense on purpose @@ -14,7 +14,7 @@ do do return {x,y for x,y in *things} --> +_ = -> if a if a a @@ -49,7 +49,7 @@ do else b --> a\b +_ = -> a\b do a\b diff --git a/spec/inputs/string.moon b/spec/inputs/string.moon index 897056a..5d8f772 100644 --- a/spec/inputs/string.moon +++ b/spec/inputs/string.moon @@ -52,7 +52,7 @@ c = 'hello #{hello}' -- -"hello" +_ = "hello" "hello"\format 1 "hello"\format(1,2,3) "hello"\format(1,2,3) 1,2,3 diff --git a/spec/inputs/switch.moon b/spec/inputs/switch.moon index 3bc179b..a028f98 100644 --- a/spec/inputs/switch.moon +++ b/spec/inputs/switch.moon @@ -15,7 +15,7 @@ switch value when "cool" print "hello world" when "yeah" - [[FFFF]] + [[MMMM]] + _ = [[FFFF]] + [[MMMM]] when 2323 + 32434 print "okay" else @@ -33,9 +33,9 @@ out = switch value with something switch \value! when .okay - "world" + _ = "world" else - "yesh" + _ = "yesh" fix this call_func switch something @@ -46,7 +46,7 @@ call_func switch something switch hi when hello or world - greene + _ = greene -- @@ -54,7 +54,7 @@ switch hi when "one", "two" print "cool" when "dad" - no + _ = no switch hi when 3+1, hello!, (-> 4)! diff --git a/spec/inputs/syntax.moon b/spec/inputs/syntax.moon index 854f629..351b22c 100644 --- a/spec/inputs/syntax.moon +++ b/spec/inputs/syntax.moon @@ -27,7 +27,7 @@ what(the)[3243] world, yeck heck hairy[hands][are](gross) okay okay[world] -(get[something] + 5)[years] +_ = (get[something] + 5)[years] i,x = 200, 300 @@ -37,27 +37,27 @@ yeah = ((1+5)*3)/2 + i % 100 whoa = (1+2) * (3+4) * (4+5) --> +_ = -> if something return 1,2,4 print "hello" --> +_ = -> if hello "heloo", "world" else no, way --> 1,2,34 +_ = -> 1,2,34 return 5 + () -> 4 + 2 return 5 + (() -> 4) + 2 print 5 + () -> - 34 + _ = 34 good nads @@ -66,19 +66,19 @@ something 'else', "ya" something'else' something"else" -something[[hey]] * 2 -something[======[hey]======] * 2 +_ = something[[hey]] * 2 +_ = something[======[hey]======] * 2 -something'else', 2 -something"else", 2 -something[[else]], 2 +_ = something'else', 2 +_ = something"else", 2 +_ = something[[else]], 2 something 'else', 2 something "else", 2 something [[else]], 2 -here(we)"go"[12123] +_ = here(we)"go"[12123] -- this runs something = @@ -120,9 +120,9 @@ print "hello" for i=1,10 print "nutjob" -if hello then 343 +if hello then _ = 343 -print "what" if cool else whack +print "what" if cool else whack! arg = {...} @@ -139,7 +139,7 @@ y = #"hello" x = #{#{},#{1},#{1,2}} -hello, world +_ = hello, world something\hello(what) a,b something\hello what @@ -163,7 +163,7 @@ a["hello#{tostring ff}"] += 10 a[four].x += 10 x = 0 -(if ntype(v) == "fndef" then x += 1) for v in *values +_ = (if ntype(v) == "fndef" then x += 1) for v in *values hello = @@ -176,10 +176,10 @@ hello = div class: "cool" -5 + what wack +_ = 5 + what wack what whack + 5 -5 - what wack +_ = 5 - what wack what whack - 5 x = hello - world - something @@ -189,16 +189,16 @@ x = hello - world - something print something)! if something - 03589 + _ = 03589 -- okay what about this else - 3434 + _ = 3434 if something - yeah + _ = yeah elseif "ymmm" @@ -207,7 +207,7 @@ elseif "ymmm" else - okay + _ = okay -- test names containing keywords diff --git a/spec/inputs/tables.moon b/spec/inputs/tables.moon index 2bf66d7..10bccde 100644 --- a/spec/inputs/tables.moon +++ b/spec/inputs/tables.moon @@ -138,7 +138,7 @@ thing what: thing what: "great", no: "more" -okay: 123 -- a anon table +_ = okay: 123 -- a anon table -- diff --git a/spec/inputs/using.moon b/spec/inputs/using.moon index 55a16a7..e407983 100644 --- a/spec/inputs/using.moon +++ b/spec/inputs/using.moon @@ -2,18 +2,18 @@ hello = "hello" world = "world" -(using nil) -> +_ = (using nil) -> hello = 3223 -(a using nil) -> +_ = (a using nil) -> hello = 3223 a = 323 -(a,b,c using a,b,c) -> +_ = (a,b,c using a,b,c) -> a,b,c = 1,2,3 world = 12321 -(a,e,f using a,b,c, hello) -> +_ = (a,e,f using a,b,c, hello) -> a,b,c = 1,2,3 hello = 12321 world = "yeah" diff --git a/spec/inputs/whitespace.moon b/spec/inputs/whitespace.moon index 4a2ff1f..e505b1b 100644 --- a/spec/inputs/whitespace.moon +++ b/spec/inputs/whitespace.moon @@ -1,42 +1,42 @@ -{ +_ = { 1, 2 } -{ 1, 2 +_ = { 1, 2 } -{ 1, 2 } +_ = { 1, 2 } -{1,2} +_ = {1,2} -{ +_ = { 1,2 } -{ something 1,2, +_ = { something 1,2, 4,5,6, 3,4,5 } -{ +_ = { a 1,2,3, 4,5,6 1,2,3 } -{ +_ = { b 1,2,3, 4,5,6 1,2,3, 1,2,3 } -{ 1,2,3 } +_ = { 1,2,3 } -{ c 1,2,3, +_ = { c 1,2,3, } @@ -58,7 +58,7 @@ hello 1,2,3, 9,9 -{ +_ = { hello 1,2, 3,4, 5, 6 diff --git a/spec/inputs/with.moon b/spec/inputs/with.moon index ae3c8c0..f543356 100644 --- a/spec/inputs/with.moon +++ b/spec/inputs/with.moon @@ -37,7 +37,7 @@ do do with foo - \prop"something".hello + _ = \prop"something".hello .prop\send(one) .prop\send one @@ -107,7 +107,7 @@ do print .c do - -> + _ = -> with hi return .a, .b diff --git a/src/MoonP/ast.hpp b/src/MoonP/ast.hpp index f2ef76c..0b5ffca 100644 --- a/src/MoonP/ast.hpp +++ b/src/MoonP/ast.hpp @@ -392,6 +392,12 @@ public: node->release(); } + void pop_back() { + auto node = m_objects.back(); + m_objects.pop_back(); + node->release(); + } + const node_container& objects() const { return m_objects; } diff --git a/src/MoonP/moon_ast.cpp b/src/MoonP/moon_ast.cpp index 0ccd0ed..f3fe31e 100644 --- a/src/MoonP/moon_ast.cpp +++ b/src/MoonP/moon_ast.cpp @@ -79,6 +79,7 @@ AST_IMPL(ColonChainItem) AST_IMPL(default_value) AST_IMPL(Slice) AST_IMPL(Invoke) +AST_IMPL(existential_op) AST_IMPL(TableLit) AST_IMPL(TableBlock) AST_IMPL(class_member_list) diff --git a/src/MoonP/moon_ast.h b/src/MoonP/moon_ast.h index a614465..8b80af3 100644 --- a/src/MoonP/moon_ast.h +++ b/src/MoonP/moon_ast.h @@ -407,11 +407,14 @@ AST_NODE(Invoke, "Invoke"_id) AST_MEMBER(Invoke, &sep, &args) AST_END(Invoke) +AST_LEAF(existential_op, "existential_op"_id) +AST_END(existential_op) + class InvokeArgs_t; AST_NODE(ChainValue, "ChainValue"_id) ast_ptr<true, Seperator_t> sep; - ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t> items; + ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, existential_op_t> items; AST_MEMBER(ChainValue, &sep, &items) AST_END(ChainValue) diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index d30f413..9164f6a 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp @@ -15,6 +15,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include <memory> #include <sstream> #include <string_view> +#include <iostream> using namespace std::string_view_literals; #include "MoonP/parser.hpp" #include "MoonP/moon_ast.h" @@ -426,6 +427,35 @@ private: return ast_is<InvokeArgs_t, Invoke_t>(chainValue->items.back()); } + bool isSpecialChainValue(ChainValue_t* chainValue) { + if (ast_is<ColonChainItem_t>(chainValue->items.back())) { + return true; + } + for (auto item : chainValue->items.objects()) { + if (auto colonChain = ast_cast<ColonChainItem_t>(item)) { + if (ast_is<LuaKeyword_t>(colonChain->name)) { + return true; + } + } else if (ast_is<existential_op_t>(item) && item != chainValue->items.back()) { + return true; + } + } + return false; + } + + std::string singleVariableFrom(ChainValue_t* chainValue) { + BLOCK_START + BREAK_IF(!chainValue); + BREAK_IF(chainValue->items.size() != 1); + auto callable = ast_cast<Callable_t>(chainValue->items.front()); + BREAK_IF(!callable || !(callable->item.is<Variable_t>() || callable->getByPath<SelfName_t,self_t>())); + str_list tmp; + transformCallable(callable, tmp); + return tmp.back(); + BLOCK_END + return Empty; + } + std::string singleVariableFrom(ast_node* expList) { if (!ast_is<Exp_t, ExpList_t>(expList)) return Empty; BLOCK_START @@ -435,7 +465,7 @@ private: BREAK_IF(!chainValue); BREAK_IF(chainValue->items.size() != 1); auto callable = ast_cast<Callable_t>(chainValue->items.front()); - BREAK_IF(!callable || !callable->item.is<Variable_t>()); + BREAK_IF(!callable || !(callable->item.is<Variable_t>() || callable->getByPath<SelfName_t,self_t>())); str_list tmp; transformCallable(callable, tmp); return tmp.back(); @@ -443,22 +473,6 @@ private: return Empty; } - bool isColonChain(ChainValue_t* chainValue) { - return ast_is<ColonChainItem_t>(chainValue->items.back()); - } - - bool hasKeywordColonChainItem(ChainValue_t* chainValue) { - const auto& chainList = chainValue->items.objects(); - for (auto it = chainList.begin(); it != chainList.end(); ++it) { - if (auto colonItem = ast_cast<ColonChainItem_t>(*it)) { - if (colonItem->name.is<LuaKeyword_t>()) { - return true; - } - } - } - return false; - } - bool isAssignable(const node_container& chainItems) { if (chainItems.size() == 1) { auto firstItem = chainItems.back(); @@ -539,7 +553,7 @@ private: } auto line = _converter.to_bytes(std::wstring(begin, end)); int oldCol = loc->m_begin.m_col; - int col = loc->m_begin.m_col - 1; + int col = std::max(0, oldCol - 1); auto it = begin; for (int i = 0; i < oldCol; ++i) { if (*it > ASCII) { @@ -558,7 +572,7 @@ private: auto x = statement; if (statement->appendix) { if (auto assignment = assignmentFrom(statement)) { - auto preDefine = getPredefine(transformAssignDefs(assignment->expList)); + auto preDefine = getPredefine(assignment); if (!preDefine.empty()) out.push_back(preDefine + nll(statement)); } auto appendix = statement->appendix.get(); @@ -790,7 +804,7 @@ private: } std::string getDestrucureDefine(ExpListAssign_t* assignment) { - auto info = extractDestructureInfo(assignment); + auto info = extractDestructureInfo(assignment, true); if (!info.first.empty()) { for (const auto& destruct : info.first) { str_list defs; @@ -909,11 +923,10 @@ private: } case "With"_id: { auto withNode = static_cast<With_t*>(value); - str_list temp; auto expList = assignment->expList.get(); std::string preDefine = getPredefine(assignment); - transformWith(withNode, temp, expList); - out.push_back(preDefine + temp.back()); + transformWith(withNode, out, expList); + out.back() = preDefine + out.back(); return; } case "Do"_id: { @@ -940,50 +953,42 @@ private: return; } case "For"_id: { - str_list temp; auto expList = assignment->expList.get(); std::string preDefine = getPredefine(assignment); - transformForInPlace(static_cast<For_t*>(value), temp, expList); - out.push_back(preDefine + temp.back()); + transformForInPlace(static_cast<For_t*>(value), out, expList); + out.back() = preDefine + out.back(); return; } case "ForEach"_id: { - str_list temp; auto expList = assignment->expList.get(); std::string preDefine = getPredefine(assignment); - transformForEachInPlace(static_cast<ForEach_t*>(value), temp, expList); - out.push_back(preDefine + temp.back()); + transformForEachInPlace(static_cast<ForEach_t*>(value), out, expList); + out.back() = preDefine + out.back(); return; } case "ClassDecl"_id: { - str_list temp; auto expList = assignment->expList.get(); std::string preDefine = getPredefine(assignment); - transformClassDecl(static_cast<ClassDecl_t*>(value), temp, ExpUsage::Assignment, expList); - out.push_back(preDefine + temp.back()); + transformClassDecl(static_cast<ClassDecl_t*>(value), out, ExpUsage::Assignment, expList); + out.back() = preDefine + out.back(); return; } case "While"_id: { - str_list temp; auto expList = assignment->expList.get(); std::string preDefine = getPredefine(assignment); - transformWhileInPlace(static_cast<While_t*>(value), temp, expList); - out.push_back(preDefine + temp.back()); + transformWhileInPlace(static_cast<While_t*>(value), out, expList); + out.back() = preDefine + out.back(); return; } } auto exp = ast_cast<Exp_t>(value); BREAK_IF(!exp); if (auto chainValue = exp->value->item.as<ChainValue_t>()) { - if (isColonChain(chainValue)) { - auto assignable = assignment->expList.get(); - std::string preDefine = getPredefine(transformAssignDefs(assignable)); - transformColonChain(chainValue, out, ExpUsage::Assignment, assignable); - auto nl = preDefine.empty() ? Empty : nll(chainValue); - if (!preDefine.empty()) out.back() = preDefine + nl + out.back(); - return; - } else if (hasKeywordColonChainItem(chainValue)) { - transformChainValue(chainValue, out, ExpUsage::Assignment, assignment->expList); + if (isSpecialChainValue(chainValue)) { + auto expList = assignment->expList.get(); + std::string preDefine = getPredefine(assignment); + transformChainValue(chainValue, out, ExpUsage::Assignment, expList); + out.back() = preDefine + out.back(); return; } } @@ -1169,7 +1174,7 @@ private: } std::pair<std::list<Destructure>, ast_ptr<false, ExpListAssign_t>> - extractDestructureInfo(ExpListAssign_t* assignment) { + extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly = false) { auto x = assignment; std::list<Destructure> destructs; if (!assignment->action.is<Assign_t>()) return { destructs, nullptr }; @@ -1187,19 +1192,21 @@ private: while (values.size() < size) values.emplace_back(nullNode); } using iter = node_container::iterator; - std::vector<std::pair<iter, iter>> destructPairs; + std::vector<std::pair<iter,iter>> destructPairs; str_list temp; for (auto i = exprs.begin(), j = values.begin(); i != exprs.end(); ++i, ++j) { auto expr = *i; ast_node* destructNode = expr->getByPath<Value_t, SimpleValue_t, TableLit_t>(); if (destructNode || (destructNode = expr->getByPath<Value_t, simple_table_t>())) { destructPairs.push_back({i,j}); - pushScope(); - transformAssignItem(*j, temp); - popScope(); auto& destruct = destructs.emplace_back(); - destruct.value = temp.back(); - temp.pop_back(); + if (!varDefOnly) { + pushScope(); + transformAssignItem(*j, temp); + destruct.value = temp.back(); + temp.pop_back(); + popScope(); + } auto pairs = destructFromExp(expr); destruct.items = std::move(pairs); } @@ -1244,7 +1251,7 @@ private: BREAK_IF(!exp); auto var = singleVariableFrom(exp); BREAK_IF(!var.empty()); - auto upVar = getUnusedName("_update_"); + auto upVar = getUnusedName("_update_"sv); auto assignment = x->new_ptr<ExpListAssign_t>(); assignment->expList.set(toAst<ExpList_t>(upVar, ExpList, x)); auto assign = x->new_ptr<Assign_t>(); @@ -1532,11 +1539,7 @@ private: case "simple_table"_id: transform_simple_table(static_cast<simple_table_t*>(item), out); break; case "ChainValue"_id: { auto chainValue = static_cast<ChainValue_t*>(item); - if (isColonChain(chainValue)) { - transformColonChainClosure(chainValue, out); - } else { - transformChainValue(chainValue, out); - } + transformChainValue(chainValue, out); break; } case "String"_id: transformString(static_cast<String_t*>(item), out); break; @@ -1689,7 +1692,7 @@ private: any->decls.push_back(var); } } - auto info = extractDestructureInfo(assignment); + auto info = extractDestructureInfo(assignment, true); if (!info.first.empty()) { for (const auto& destruct : info.first) for (const auto& item : destruct.items) @@ -1803,12 +1806,10 @@ private: } } if (auto chainValue = singleValue->item.as<ChainValue_t>()) { - if (isColonChain(chainValue)) { - transformColonChain(chainValue, out, ExpUsage::Return); - } else { + if (isSpecialChainValue(chainValue)) { transformChainValue(chainValue, out, ExpUsage::Return); + return; } - return; } transformValue(singleValue, out); out.back() = indent() + s("return "sv) + out.back() + nlr(returnNode); @@ -1980,111 +1981,292 @@ private: } } - void transformColonChainClosure(ChainValue_t* chainValue, str_list& out) { - str_list temp; - temp.push_back(s("(function()"sv) + nll(chainValue)); - pushScope(); - transformColonChain(chainValue, temp, ExpUsage::Return); - popScope(); - temp.push_back(indent() + s("end)()"sv)); - out.push_back(join(temp)); + bool transformChainEndWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t*) { + auto x = chainList.front(); + if (ast_cast<existential_op_t>(chainList.back())) { + auto parens = x->new_ptr<Parens_t>(); + { + auto chainValue = x->new_ptr<ChainValue_t>(); + for (auto item : chainList) { + chainValue->items.push_back(item); + } + chainValue->items.pop_back(); + auto value = x->new_ptr<Value_t>(); + value->item.set(chainValue); + auto opValue = x->new_ptr<exp_op_value_t>(); + opValue->op.set(toAst<BinaryOperator_t>("!="sv, BinaryOperator, x)); + opValue->value.set(toAst<Value_t>("nil"sv, Value, x)); + auto exp = x->new_ptr<Exp_t>(); + exp->value.set(value); + exp->opValues.push_back(opValue); + parens->expr.set(exp); + } + transformParens(parens, out); + if (usage == ExpUsage::Return) { + out.back().insert(0, indent() + s("return "sv)); + out.back().append(nlr(x)); + } + return true; + } + return false; } - void transformColonChain(ChainValue_t* chainValue, str_list& out, ExpUsage usage = ExpUsage::Common, ExpList_t* expList = nullptr) { - auto x = chainValue; - const auto& chainList = chainValue->items.objects(); - auto baseChain = x->new_ptr<ChainValue_t>(); - switch (chainList.front()->getId()) { - case "DotChainItem"_id: - case "ColonChainItem"_id: - if (_withVars.empty()) { - throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, chainList.front())); - } else { - baseChain->items.push_back(toAst<Callable_t>(_withVars.top(), Callable, x)); - } + bool transformChainWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { + auto opIt = std::find_if(chainList.begin(), chainList.end(), [](ast_node* node) { return ast_is<existential_op_t>(node); }); + if (opIt != chainList.end()) { + auto x = chainList.front(); + str_list temp; + if (usage == ExpUsage::Closure) { + temp.push_back(s("(function()"sv) + nll(x)); + pushScope(); + } + auto partOne = x->new_ptr<ChainValue_t>(); + for (auto it = chainList.begin();it != opIt;++it) { + partOne->items.push_back(*it); + } + BLOCK_START + auto back = ast_cast<Callable_t>(partOne->items.back()); + BREAK_IF(!back); + auto selfName = ast_cast<SelfName_t>(back->item); + BREAK_IF(!selfName); + if (auto sname = ast_cast<self_name_t>(selfName->name)) { + auto colonItem = x->new_ptr<ColonChainItem_t>(); + colonItem->name.set(sname->name); + partOne->items.pop_back(); + partOne->items.push_back(toAst<Callable_t>("@"sv, Callable, x)); + partOne->items.push_back(colonItem); break; - } - auto end = --chainList.end(); - for (auto it = chainList.begin(); it != end; ++it) { - baseChain->items.push_back(*it); - } - auto colonChainItem = static_cast<ColonChainItem_t*>(chainList.back()); - auto funcName = toString(colonChainItem->name); - if (usage != ExpUsage::Return) pushScope(); - auto baseVar = getUnusedName("_base_"sv); - auto fnVar = getUnusedName("_fn_"sv); - str_list temp; - { - auto value = x->new_ptr<Value_t>(); - value->item.set(baseChain); - auto exp = x->new_ptr<Exp_t>(); - exp->value.set(value); - auto assign = x->new_ptr<Assign_t>(); - assign->values.push_back(exp); - auto assignment = x->new_ptr<ExpListAssign_t>(); - assignment->expList.set(toAst<ExpList_t>(baseVar, ExpList, x)); - assignment->action.set(assign); - transformAssignment(assignment, temp); - } - { - auto assign = x->new_ptr<Assign_t>(); - assign->values.push_back(toAst<Exp_t>(baseVar + "." + funcName, Exp, x)); - auto assignment = x->new_ptr<ExpListAssign_t>(); - assignment->expList.set(toAst<ExpList_t>(fnVar, ExpList, x)); - assignment->action.set(assign); - transformAssignment(assignment, temp); - } - auto funLit = toAst<Exp_t>(s("(...)-> "sv) + fnVar + s(" "sv) + baseVar + s(", ..."sv), Exp, x); - switch (usage) { - case ExpUsage::Return: - transformExp(funLit, temp); - _buf << temp.front(); - _buf << *(++temp.begin()); - _buf << indent() << "return " << temp.back() << nll(chainValue); + } + if (auto cname = ast_cast<self_class_name_t>(selfName->name)) { + auto colonItem = x->new_ptr<ColonChainItem_t>(); + colonItem->name.set(cname->name); + partOne->items.pop_back(); + partOne->items.push_back(toAst<Callable_t>("@@"sv, Callable, x)); + partOne->items.push_back(colonItem); break; - case ExpUsage::Assignment: { + } + BLOCK_END + auto objVar = singleVariableFrom(partOne); + if (objVar.empty()) { + objVar = getUnusedName("_obj_"sv); + if (auto colonItem = ast_cast<ColonChainItem_t>(partOne->items.back())) { + auto chainValue = x->new_ptr<ChainValue_t>(); + chainValue->items.dup(partOne->items); + chainValue->items.pop_back(); + if (chainValue->items.empty()) { + if (_withVars.empty()) { + throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, x)); + } + chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), Callable, x)); + } + auto newObj = singleVariableFrom(chainValue); + if (!newObj.empty()) { + objVar = newObj; + } else { + auto value = x->new_ptr<Value_t>(); + value->item.set(chainValue); + auto exp = x->new_ptr<Exp_t>(); + exp->value.set(value); + auto assign = x->new_ptr<Assign_t>(); + assign->values.push_back(exp); + auto expListAssign = x->new_ptr<ExpListAssign_t>(); + expListAssign->expList.set(toAst<ExpList_t>(objVar, ExpList, x)); + expListAssign->action.set(assign); + transformAssignment(expListAssign, temp); + } + auto dotItem = x->new_ptr<DotChainItem_t>(); + auto name = colonItem->name.get(); + if (auto keyword = ast_cast<LuaKeyword_t>(name)) { + name = keyword->name.get(); + } + dotItem->name.set(name); + partOne->items.clear(); + partOne->items.push_back(toAst<Callable_t>(objVar, Callable, x)); + partOne->items.push_back(dotItem); + auto it = opIt; ++it; + if (it != chainList.end() && ast_is<Invoke_t, InvokeArgs_t>(*it)) { + + if (auto invoke = ast_cast<Invoke_t>(*it)) { + invoke->args.push_front(toAst<Exp_t>(objVar, Exp, x)); + } else { + auto invokeArgs = static_cast<InvokeArgs_t*>(*it); + invokeArgs->args.push_front(toAst<Exp_t>(objVar, Exp, x)); + } + } + objVar = getUnusedName("_obj_"sv); + } + auto value = x->new_ptr<Value_t>(); + value->item.set(partOne); + auto exp = x->new_ptr<Exp_t>(); + exp->value.set(value); + auto assign = x->new_ptr<Assign_t>(); + assign->values.push_back(exp); + auto expListAssign = x->new_ptr<ExpListAssign_t>(); + expListAssign->expList.set(toAst<ExpList_t>(objVar, ExpList, x)); + expListAssign->action.set(assign); + transformAssignment(expListAssign, temp); + } + _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nll(x); + temp.push_back(clearBuf()); + pushScope(); + auto partTwo = x->new_ptr<ChainValue_t>(); + partTwo->items.push_back(toAst<Callable_t>(objVar, Callable, x)); + for (auto it = ++opIt;it != chainList.end();++it) { + partTwo->items.push_back(*it); + } + switch (usage) { + case ExpUsage::Common: + transformChainValue(partTwo, temp, ExpUsage::Common); + break; + case ExpUsage::Assignment: { + auto value = x->new_ptr<Value_t>(); + value->item.set(partTwo); + auto exp = x->new_ptr<Exp_t>(); + exp->value.set(value); + auto assign = x->new_ptr<Assign_t>(); + assign->values.push_back(exp); + auto assignment = x->new_ptr<ExpListAssign_t>(); + assignment->expList.set(assignList); + assignment->action.set(assign); + transformAssignment(assignment, temp); + break; + } + case ExpUsage::Return: + case ExpUsage::Closure: { + auto value = x->new_ptr<Value_t>(); + value->item.set(partTwo); + auto exp = x->new_ptr<Exp_t>(); + exp->value.set(value); + auto ret = x->new_ptr<Return_t>(); + auto expListLow = x->new_ptr<ExpListLow_t>(); + expListLow->exprs.push_back(exp); + ret->valueList.set(expListLow); + transformReturn(ret, temp); + break; + } + } + popScope(); + temp.push_back(indent() + s("end"sv) + nlr(x)); + switch (usage) { + case ExpUsage::Return: + temp.push_back(indent() + s("return nil"sv) + nlr(x)); + break; + case ExpUsage::Closure: + temp.push_back(indent() + s("return nil"sv) + nlr(x)); + popScope(); + temp.push_back(indent() + s("end)()"sv)); + break; + default: + break; + } + out.push_back(join(temp)); + return true; + } + return false; + } + + bool transformChainEndWithColonItem(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { + if (ast_is<ColonChainItem_t>(chainList.back())) { + auto x = chainList.front(); + str_list temp; + switch (usage) { + case ExpUsage::Assignment: + temp.push_back(indent() + s("do"sv) + nll(x)); + pushScope(); + break; + case ExpUsage::Closure: + temp.push_back(s("(function()"sv) + nll(x)); + pushScope(); + break; + default: + break; + } + auto baseChain = x->new_ptr<ChainValue_t>(); + switch (chainList.front()->getId()) { + case "DotChainItem"_id: + case "ColonChainItem"_id: + if (_withVars.empty()) { + throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, chainList.front())); + } else { + baseChain->items.push_back(toAst<Callable_t>(_withVars.top(), Callable, x)); + } + break; + } + auto end = --chainList.end(); + for (auto it = chainList.begin(); it != end; ++it) { + baseChain->items.push_back(*it); + } + auto colonChainItem = static_cast<ColonChainItem_t*>(chainList.back()); + auto funcName = toString(colonChainItem->name); + auto baseVar = getUnusedName("_base_"sv); + auto fnVar = getUnusedName("_fn_"sv); + { + auto value = x->new_ptr<Value_t>(); + value->item.set(baseChain); + auto exp = x->new_ptr<Exp_t>(); + exp->value.set(value); auto assign = x->new_ptr<Assign_t>(); - assign->values.push_back(funLit); + assign->values.push_back(exp); auto assignment = x->new_ptr<ExpListAssign_t>(); - assignment->expList.set(expList); + assignment->expList.set(toAst<ExpList_t>(baseVar, ExpList, x)); assignment->action.set(assign); transformAssignment(assignment, temp); - _buf << indent(-1) << "do"sv << nll(chainValue); - _buf << temp.front(); - _buf << *(++temp.begin()); - _buf << temp.back(); - popScope(); - _buf << indent() << "end"sv << nll(chainValue); - break; } - case ExpUsage::Common: { + { auto assign = x->new_ptr<Assign_t>(); - assign->values.push_back(funLit); + assign->values.push_back(toAst<Exp_t>(baseVar + "." + funcName, Exp, x)); auto assignment = x->new_ptr<ExpListAssign_t>(); - assignment->expList.set(toAst<ExpList_t>("_"sv, ExpList, x)); + assignment->expList.set(toAst<ExpList_t>(fnVar, ExpList, x)); assignment->action.set(assign); transformAssignment(assignment, temp); - _buf << indent(-1) << "do"sv << nll(chainValue); - _buf << temp.front(); - _buf << *(++temp.begin()); - _buf << temp.back(); - popScope(); - _buf << indent() << "end"sv << nll(chainValue); - break; } - default: break; + auto funLit = toAst<Exp_t>(s("(...)-> "sv) + fnVar + s(" "sv) + baseVar + s(", ..."sv), Exp, x); + switch (usage) { + case ExpUsage::Closure: + case ExpUsage::Return: + transformExp(funLit, temp); + _buf << temp.front(); + _buf << *(++temp.begin()); + _buf << indent() << "return " << temp.back() << nll(x); + break; + case ExpUsage::Assignment: { + auto assign = x->new_ptr<Assign_t>(); + assign->values.push_back(funLit); + auto assignment = x->new_ptr<ExpListAssign_t>(); + assignment->expList.set(assignList); + assignment->action.set(assign); + transformAssignment(assignment, temp); + break; + } + default: + break; + } + switch (usage) { + case ExpUsage::Assignment: + popScope(); + temp.push_back(indent() + s("end"sv) + nlr(x)); + break; + case ExpUsage::Closure: + popScope(); + temp.push_back(indent() + s("end)()"sv)); + break; + default: + break; + } + out.push_back(join(temp)); + return true; } - out.push_back(clearBuf()); + return false; } void transformChainList(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { auto x = chainList.front(); str_list temp; - switch (chainList.front()->getId()) { + switch (x->getId()) { case "DotChainItem"_id: case "ColonChainItem"_id: if (_withVars.empty()) { - throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, chainList.front())); + throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, x)); } else { temp.push_back(_withVars.top()); } @@ -2101,8 +2283,20 @@ private: break; case "ColonChainItem"_id: { auto colonItem = static_cast<ColonChainItem_t*>(item); - auto next = it; ++next; + auto current = it; + auto next = current; ++next; auto followItem = next != chainList.end() ? *next : nullptr; + if (current != chainList.begin()) { + --current; + if (!ast_is<existential_op_t>(*current)) { + ++current; + } + } + if (ast_is<existential_op_t>(followItem)) { + ++next; + followItem = next != chainList.end() ? *next : nullptr; + --next; + } if (!ast_is<Invoke_t, InvokeArgs_t>(followItem)) { throw std::logic_error(debugInfo("Colon chain item must be followed by invoke arguments."sv, colonItem)); } @@ -2117,7 +2311,7 @@ private: chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), Callable, x)); break; } - for (auto i = chainList.begin(); i != it; ++i) { + for (auto i = chainList.begin(); i != current; ++i) { chainValue->items.push_back(*i); } auto value = x->new_ptr<Value_t>(); @@ -2141,6 +2335,9 @@ private: auto name = toString(colonItem->name); auto chainValue = x->new_ptr<ChainValue_t>(); chainValue->items.push_back(toAst<Callable_t>(callVar, Callable, x)); + if (ast_is<existential_op_t>(*current)) { + chainValue->items.push_back(x->new_ptr<existential_op_t>()); + } chainValue->items.push_back(toAst<Exp_t>(s("\""sv) + name + s("\""sv), Exp, x)); if (auto invoke = ast_cast<Invoke_t>(followItem)) { invoke->args.push_front(toAst<Exp_t>(callVar, Exp, x)); @@ -2148,8 +2345,7 @@ private: auto invokeArgs = static_cast<InvokeArgs_t*>(followItem); invokeArgs->args.push_front(toAst<Exp_t>(callVar, Exp, x)); } - chainValue->items.push_back(followItem); - for (auto i = ++next; i != chainList.end(); ++i) { + for (auto i = next; i != chainList.end(); ++i) { chainValue->items.push_back(*i); } auto value = x->new_ptr<Value_t>(); @@ -2244,7 +2440,17 @@ private: } void transformChainValue(ChainValue_t* chainValue, str_list& out, ExpUsage usage = ExpUsage::Closure, ExpList_t* assignList = nullptr) { - transformChainList(chainValue->items.objects(), out, usage, assignList); + const auto& chainList = chainValue->items.objects(); + if (transformChainEndWithEOP(chainList, out, usage, assignList)) { + return; + } + if (transformChainWithEOP(chainList, out, usage, assignList)) { + return; + } + if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { + return; + } + transformChainList(chainList, out, usage, assignList); } void transformAssignableChain(AssignableChain_t* chain, str_list& out) { @@ -2957,7 +3163,7 @@ private: if (auto assignment = assignmentFrom(statement)) { auto names = transformAssignDefs(assignment->expList.get()); varDefs.insert(varDefs.end(), names.begin(), names.end()); - auto info = extractDestructureInfo(assignment); + auto info = extractDestructureInfo(assignment, true); if (!info.first.empty()) { for (const auto& destruct : info.first) for (const auto& item : destruct.items) @@ -3342,7 +3548,7 @@ private: if (!names.empty()) { return traversal::Stop; } - auto info = extractDestructureInfo(assignment); + auto info = extractDestructureInfo(assignment, true); if (!info.first.empty()) { for (const auto& destruct : info.first) for (const auto& item : destruct.items) diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp index 1005463..7cc4129 100644 --- a/src/MoonP/moon_parser.cpp +++ b/src/MoonP/moon_parser.cpp @@ -289,9 +289,9 @@ extern rule Value; rule exp_op_value = Space >> BinaryOperator >> *SpaceBreak >> Value; rule Exp = Value >> *exp_op_value; -extern rule Chain, Callable, InvokeArgs; +extern rule Chain, Callable, InvokeArgs, existential_op; -rule ChainValue = Seperator >> (Chain | Callable) >> -InvokeArgs; +rule ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -InvokeArgs; extern rule KeyValue, String, SimpleValue; @@ -345,9 +345,10 @@ rule FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym( extern rule ChainItems, DotChainItem, ColonChain; -rule chain_call = (Callable | String) >> ChainItems; +rule existential_op = expr('?'); +rule chain_call = (Callable | String) >> -existential_op >> ChainItems; rule chain_item = and_(set(".\\")) >> ChainItems; -rule chain_dot_chain = DotChainItem >> -ChainItems; +rule chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems; rule Chain = chain_call | chain_item | Space >> (chain_dot_chain | ColonChain); @@ -362,11 +363,11 @@ rule ChainItems = chain_with_colon | ColonChain; extern rule Invoke, Slice; rule Index = symx('[') >> Exp >> sym(']'); -rule ChainItem = Invoke | DotChainItem | Slice | Index; +rule ChainItem = Invoke >> -existential_op | DotChainItem >> -existential_op | Slice | Index >> -existential_op; rule DotChainItem = symx('.') >> Name; rule ColonChainItem = symx('\\') >> (LuaKeyword | Name); -rule invoke_chain = Invoke >> -ChainItems; -rule ColonChain = ColonChainItem >> -invoke_chain; +rule invoke_chain = Invoke >> -existential_op >> -ChainItems; +rule ColonChain = ColonChainItem >> -existential_op >> -invoke_chain; rule default_value = true_(); rule Slice = diff --git a/src/moonc.cpp b/src/moonc.cpp index 02d5275..4498bee 100644 --- a/src/moonc.cpp +++ b/src/moonc.cpp @@ -22,14 +22,13 @@ int main(int narg, const char** args) { " -p Write output to standard out\n" " -b Dump compile time (doesn't write output)\n" " -l Write line numbers from source codes\n" -" -a Allow expression list not in the end of body block\n" -" -s Use space over tab\n" " -v Print version\n"; if (narg == 0) { std::cout << help; return 0; } MoonP::MoonConfig config; + config.reserveLineNumber = false; bool writeToFile = true; bool dumpCompileTime = false; std::string targetPath; @@ -37,18 +36,9 @@ int main(int narg, const char** args) { std::list<std::string> files; for (int i = 1; i < narg; ++i) { switch (hash(args[i])) { - case "-a"_id: - config.allowExprNotInTheEndOfBody = true; - break; - case "-s"_id: - config.spaceOverTab = true; - break; case "-l"_id: config.reserveLineNumber = true; break; - case "-r"_id: - config.reuseVariable = true; - break; case "-p"_id: writeToFile = false; break; -- cgit v1.2.3-55-g6feb