From ccfe66f87663e10603e453f02894bb82dd23c93b Mon Sep 17 00:00:00 2001 From: Li Jin Date: Mon, 19 Jan 2026 17:11:31 +0800 Subject: Made `;` work as statements separator. --- doc/docs/doc/README.md | 13 ++++ doc/docs/zh/doc/README.md | 13 ++++ spec/inputs/syntax.yue | 49 ++++++++++++- spec/inputs/unicode/syntax.yue | 2 +- spec/inputs/unicode/whitespace.yue | 10 +-- spec/inputs/whitespace.yue | 10 +-- spec/outputs/codes_from_doc.lua | 6 ++ spec/outputs/codes_from_doc_zh.lua | 6 ++ spec/outputs/syntax.lua | 74 ++++++++++++++++++- spec/outputs/unicode/syntax.lua | 4 +- spec/outputs/unicode/whitespace.lua | 8 +-- spec/outputs/whitespace.lua | 8 +-- src/yue.cpp | 2 +- src/yuescript/yue_ast.cpp | 7 -- src/yuescript/yue_ast.h | 16 ++--- src/yuescript/yue_compiler.cpp | 137 ++++++++++++------------------------ src/yuescript/yue_parser.cpp | 35 +++++---- src/yuescript/yue_parser.h | 2 +- 18 files changed, 248 insertions(+), 154 deletions(-) diff --git a/doc/docs/doc/README.md b/doc/docs/doc/README.md index d862777..b5051d4 100755 --- a/doc/docs/doc/README.md +++ b/doc/docs/doc/README.md @@ -1588,6 +1588,19 @@ print ok, count, first YueScript is a whitespace significant language. You have to write some code block in the same indent with space **' '** or tab **'\t'** like function body, value list and some control blocks. And expressions containing different whitespaces might mean different things. Tab is treated like 4 space, but it's better not mix the use of spaces and tabs. +### Statement Separator + +A statement normally ends at a line break. You can also use a semicolon `;` to explicitly terminate a statement, which allows writing multiple statements on the same line: + +```moonscript +a = 1; b = 2; print a + b +``` + +
+a = 1; b = 2; print a + b
+
+
+ ### Multiline Chaining You can write multi-line chaining function calls with a same indent. diff --git a/doc/docs/zh/doc/README.md b/doc/docs/zh/doc/README.md index 786892d..43713fe 100755 --- a/doc/docs/zh/doc/README.md +++ b/doc/docs/zh/doc/README.md @@ -1586,6 +1586,19 @@ print ok, count, first 月之脚本是一个对空白敏感的语言。你必须在相同的缩进中使用空格 **' '** 或制表符 **'\t'** 来编写一些代码块,如函数体、值列表和一些控制块。包含不同空白的表达式可能意味着不同的事情。制表符被视为4个空格,但最好不要混合使用空格和制表符。 +### 语句分隔符 + +一条语句通常以换行结束。你也可以使用分号 `;` 显式结束一条语句,从而在同一行中编写多条语句: + +```moonscript +a = 1; b = 2; print a + b +``` + +
+a = 1; b = 2; print a + b
+
+
+ ### 多行链式调用 你可以使用相同的缩进来编写多行链式函数调用。 diff --git a/spec/inputs/syntax.yue b/spec/inputs/syntax.yue index eee518a..cef3e3d 100644 --- a/spec/inputs/syntax.yue +++ b/spec/inputs/syntax.yue @@ -7,7 +7,7 @@ a, bunch, go, here = another, world, nil, nil func arg1, arg2, another, arg3 here, we = () ->, yeah -the, different = () -> approach; yeah +the, different = (() -> approach), yeah dad() dad(lord) @@ -321,7 +321,7 @@ ajax url, (error) -> print error --- +-- a += 3 - 5 a *= 3 + 5 a *= 3 @@ -480,11 +480,54 @@ do do return res if res ~= "" - + do return res if res ~= "" -- +do + a = 1; b = 2; c = a + b + print a; print b; print c + + f = -> + a = 1; b = 2; a + b + + a = 1; + b = 2; + + success, result = try func!; print result if success + + value = "foo"; print value; value = value .. "bar"; print value + + do + if ok then print "ok!"; return 42 + + for i=1,3 + print i; continue + + n = 0 + while n < 2 + print "n=", n; n += 1 + + obj = {} + obj\set 10; obj\get!; print "done" + + with tbl + \push 1; print "push" + + a = 5 + if a > 3 + print "big"; b = a * 2; print b + else + print "small"; b = a + + try + x = 1; y = 2; print x + y + catch err + print "error:", err + + q = 1;; w = 2;;; e = 3; print q, w, e; + nil diff --git a/spec/inputs/unicode/syntax.yue b/spec/inputs/unicode/syntax.yue index 01d5c87..939579b 100644 --- a/spec/inputs/unicode/syntax.yue +++ b/spec/inputs/unicode/syntax.yue @@ -7,7 +7,7 @@ 函数 参数1, 参数2, 另外, 参数3 这里, 我们 = () ->, 是的 -这个, 不同 = () -> 方法; 是的 +这个, 不同 = (() -> 方法), 是的 爸爸() 爸爸(主) diff --git a/spec/inputs/unicode/whitespace.yue b/spec/inputs/unicode/whitespace.yue index efe55ce..151789a 100644 --- a/spec/inputs/unicode/whitespace.yue +++ b/spec/inputs/unicode/whitespace.yue @@ -97,19 +97,19 @@ v = -> 变量c -- v3 v1, v2, \ - v3 = -> - 变量a; \-- 函数结束于v1 + v3 = (-> + 变量a), \-- 函数结束于v1 变量b, \-- v2 变量c -- v3 变量a, 变量b, \ 变量c, 变量d, \ 变量e, 变量f = 1, \ - f2 - :abc; \-- 参数2 + (f2 + :abc), \-- 参数2 3, \ 4, \ - 函数5 abc; \-- 参数5 + 函数5(abc), \-- 参数5 6 for 变量a, \-- 解构1 diff --git a/spec/inputs/whitespace.yue b/spec/inputs/whitespace.yue index 2655961..e501d3d 100644 --- a/spec/inputs/whitespace.yue +++ b/spec/inputs/whitespace.yue @@ -128,19 +128,19 @@ v = -> c -- v3 v1, v2, \ - v3 = -> - a; \-- end of function for v1 + v3 = (-> + a), \-- end of function for v1 b, \-- v2 c -- v3 a, b, \ c, d, \ e, f = 1, \ - f2 - :abc; \-- arg2 + (f2 + :abc), \-- arg2 3, \ 4, \ - f5 abc; \-- arg5 + f5(abc), \-- arg5 6 for a, \-- destruct 1 diff --git a/spec/outputs/codes_from_doc.lua b/spec/outputs/codes_from_doc.lua index 1df7cef..3b0724a 100644 --- a/spec/outputs/codes_from_doc.lua +++ b/spec/outputs/codes_from_doc.lua @@ -756,6 +756,9 @@ end local first = select(1, ...) return print(ok, count, first) end)(fn(true)) +local a = 1 +local b = 2 +print(a + b) Rx.Observable.fromRange(1, 8):filter(function(x) return x % 2 == 0 end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) @@ -3283,6 +3286,9 @@ end local first = select(1, ...) return print(ok, count, first) end)(fn(true)) +local a = 1 +local b = 2 +print(a + b) Rx.Observable.fromRange(1, 8):filter(function(x) return x % 2 == 0 end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) diff --git a/spec/outputs/codes_from_doc_zh.lua b/spec/outputs/codes_from_doc_zh.lua index b407895..89335c9 100644 --- a/spec/outputs/codes_from_doc_zh.lua +++ b/spec/outputs/codes_from_doc_zh.lua @@ -756,6 +756,9 @@ end local first = select(1, ...) return print(ok, count, first) end)(fn(true)) +local a = 1 +local b = 2 +print(a + b) Rx.Observable.fromRange(1, 8):filter(function(x) return x % 2 == 0 end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) @@ -3277,6 +3280,9 @@ end local first = select(1, ...) return print(ok, count, first) end)(fn(true)) +local a = 1 +local b = 2 +print(a + b) Rx.Observable.fromRange(1, 8):filter(function(x) return x % 2 == 0 end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) diff --git a/spec/outputs/syntax.lua b/spec/outputs/syntax.lua index 2df3473..d975ef7 100644 --- a/spec/outputs/syntax.lua +++ b/spec/outputs/syntax.lua @@ -5,9 +5,9 @@ func(arg1, arg2, another, arg3) local we here, we = function() end, yeah local the, different -the, different = function() +the, different = (function() return approach -end, yeah +end), yeah dad() dad(lord) hello(one, two)(); @@ -441,4 +441,74 @@ do end end)()) end +do + a = 1 + local b = 2 + local c = a + b + print(a) + print(b) + print(c) + f = function() + a = 1 + b = 2 + return a + b + end + a = 1 + b = 2 + local success, result = pcall(function() + return func() + end) + if success then + print(result) + end + local value = "foo" + print(value) + value = value .. "bar" + print(value) + do + if ok then + print("ok!") + end + return 42 + end + for i = 1, 3 do + print(i) + goto _continue_0 + ::_continue_0:: + end + local n = 0 + while n < 2 do + print("n=", n) + n = n + 1 + end + local obj = { } + obj:set(10) + obj:get() + print("done") + do + local _with_0 = tbl + _with_0:push(1) + print("push") + end + a = 5 + if a > 3 then + print("big") + b = a * 2 + print(b) + else + print("small") + b = a + end + xpcall(function() + x = 1 + y = 2 + return print(x + y) + end, function(err) + return print("error:", err) + end) + local q = 1 + local w = 2 + local e = 3 + print(q, w, e) +end return nil diff --git a/spec/outputs/unicode/syntax.lua b/spec/outputs/unicode/syntax.lua index a13302b..f5d5d8a 100644 --- a/spec/outputs/unicode/syntax.lua +++ b/spec/outputs/unicode/syntax.lua @@ -5,9 +5,9 @@ _u51fd_u6570(_u53c2_u65701, _u53c2_u65702, _u53e6_u5916, _u53c2_u65703) local _u6211_u4eec _u8fd9_u91cc, _u6211_u4eec = function() end, _u662f_u7684 local _u8fd9_u4e2a, _u4e0d_u540c -_u8fd9_u4e2a, _u4e0d_u540c = function() +_u8fd9_u4e2a, _u4e0d_u540c = (function() return _u65b9_u6cd5 -end, _u662f_u7684 +end), _u662f_u7684 _u7238_u7238() _u7238_u7238(_u4e3b) _u4f60_u597d(_u4e00, _u4e8c)(); diff --git a/spec/outputs/unicode/whitespace.lua b/spec/outputs/unicode/whitespace.lua index d026abb..7a83d9f 100644 --- a/spec/outputs/unicode/whitespace.lua +++ b/spec/outputs/unicode/whitespace.lua @@ -82,12 +82,12 @@ v = function() return _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc end local v1, v2, v3 -v1, v2, v3 = function() +v1, v2, v3 = (function() return _u53d8_u91cfa -end, _u53d8_u91cfb, _u53d8_u91cfc -local _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc, _u53d8_u91cfd, _u53d8_u91cfe, _u53d8_u91cff = 1, f2({ +end), _u53d8_u91cfb, _u53d8_u91cfc +local _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc, _u53d8_u91cfd, _u53d8_u91cfe, _u53d8_u91cff = 1, (f2({ abc = abc -}), 3, 4, _u51fd_u65705(abc), 6 +})), 3, 4, _u51fd_u65705(abc), 6 for _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc in pairs(_u5bf9_u8c61tb) do _u6253_u5370(_u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc) end diff --git a/spec/outputs/whitespace.lua b/spec/outputs/whitespace.lua index 0251968..864f085 100644 --- a/spec/outputs/whitespace.lua +++ b/spec/outputs/whitespace.lua @@ -94,12 +94,12 @@ v = function() return a, b, c end local v1, v2, v3 -v1, v2, v3 = function() +v1, v2, v3 = (function() return a -end, b, c -local a, b, c, d, e, f = 1, f2({ +end), b, c +local a, b, c, d, e, f = 1, (f2({ abc = abc -}), 3, 4, f5(abc), 6 +})), 3, 4, f5(abc), 6 for a, b, c in pairs(tb) do print(a, b, c) end diff --git a/src/yue.cpp b/src/yue.cpp index b93f75e..2722c55 100644 --- a/src/yue.cpp +++ b/src/yue.cpp @@ -341,7 +341,7 @@ int main(int narg, const char** args) { " -- Read from standard in, print to standard out\n" " (Must be first and only argument)\n\n" " --target=version Specify the Lua version that codes will be generated to\n" - " (version can only be 5.1, 5.2, 5.3 or 5.4)\n" + " (version can only be 5.1 to 5.5)\n" " --path=path_str Append an extra Lua search path string to package.path\n\n" " Execute without options to enter REPL, type symbol '$'\n" " in a single line to start/stop multi-line mode\n" diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp index c9fd23f..bcea4d5 100644 --- a/src/yuescript/yue_ast.cpp +++ b/src/yuescript/yue_ast.cpp @@ -370,13 +370,6 @@ std::string PipeBody_t::to_string(void* ud) const { } return join(temp, "\n"sv); } -std::string ExpListLow_t::to_string(void* ud) const { - str_list temp; - for (auto exp : exprs.objects()) { - temp.emplace_back(exp->to_string(ud)); - } - return join(temp, "; "sv); -} std::string ExpList_t::to_string(void* ud) const { str_list temp; for (auto exp : exprs.objects()) { diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index af2355a..5043526 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h @@ -50,7 +50,7 @@ std::string_view ast_name() { return {}; } // clang-format off namespace yue { -class ExpListLow_t; +class ExpList_t; class TableBlock_t; class SimpleTable_t; class TableLit_t; @@ -156,7 +156,7 @@ AST_END(NameList) AST_NODE(LocalValues) ast_ptr nameList; - ast_sel valueList; + ast_sel valueList; AST_MEMBER(LocalValues, &nameList, &valueList) AST_END(LocalValues) @@ -273,12 +273,6 @@ AST_NODE(Backcall) AST_MEMBER(Backcall, &argsDef, &arrow, &value) AST_END(Backcall) -AST_NODE(ExpListLow) - ast_ptr sep; - ast_list exprs; - AST_MEMBER(ExpListLow, &sep, &exprs) -AST_END(ExpListLow) - AST_NODE(ExpList) ast_ptr sep; ast_list exprs; @@ -290,7 +284,7 @@ AST_END(ExpList) AST_NODE(Return) bool allowBlockMacroReturn = false; bool explicitReturn = true; - ast_sel valueList; + ast_sel valueList; AST_MEMBER(Return, &valueList) AST_END(Return) @@ -764,7 +758,7 @@ AST_END(ClassDecl) AST_NODE(GlobalValues) ast_ptr nameList; - ast_sel valueList; + ast_sel valueList; AST_MEMBER(GlobalValues, &nameList, &valueList) AST_END(GlobalValues) @@ -819,7 +813,7 @@ AST_END(FnArrow) AST_NODE(FunLit) ast_ptr argsDef; - ast_sel defaultReturn; + ast_sel defaultReturn; ast_ptr arrow; ast_ptr body; bool noRecursion = false; diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index a2d49af..c7802b6 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -78,7 +78,7 @@ static std::unordered_set Metamethods = { "close"s // Lua 5.4 }; -const std::string_view version = "0.31.1"sv; +const std::string_view version = "0.32.0"sv; const std::string_view extension = "yue"sv; class CompileError : public std::logic_error { @@ -1057,13 +1057,6 @@ private: } break; } - case id(): { - auto expList = static_cast(item); - if (expList->exprs.size() == 1) { - exp = static_cast(expList->exprs.front()); - } - break; - } case id(): { auto expList = static_cast(item); if (expList->exprs.size() == 1) { @@ -1092,12 +1085,12 @@ private: return nullptr; } - Value_t* singleValueFrom(ast_node* item) const { + Value_t* singleValueFrom(ast_node* item, bool forceUnparened = false) const { if (auto unary = singleUnaryExpFrom(item)) { if (unary->ops.empty()) { Value_t* value = static_cast(unary->expos.back()); if (auto chain = ast_cast(value->item); chain && chain->items.size() == 1) { - if (auto parens = chain->get_by_path(); parens && parens->extra) { + if (auto parens = chain->get_by_path(); parens && (forceUnparened || parens->extra)) { if (auto insideValue = singleValueFrom(parens->expr)) { return insideValue; } @@ -1157,6 +1150,22 @@ private: return exp; } + ast_ptr newReturn(Exp_t* value) { + auto returnNode = value->new_ptr(); + returnNode->explicitReturn = false; + auto expList = value->new_ptr(); + expList->exprs.push_back(value); + returnNode->valueList.set(expList); + return returnNode; + } + + ast_ptr newReturn(ExpList_t* valueList) { + auto returnNode = valueList->new_ptr(); + returnNode->explicitReturn = false; + returnNode->valueList.set(valueList); + return returnNode; + } + SimpleValue_t* simpleSingleValueFrom(ast_node* node) const { auto value = singleValueFrom(node); if (value && value->item.is()) { @@ -1264,7 +1273,7 @@ private: } case id(): { if (auto localValues = static_cast(stmt->content.get())->item.as()) { - if (auto expList = localValues->valueList.as()) { + if (auto expList = localValues->valueList.as()) { return static_cast(expList->exprs.back()); } } @@ -1272,7 +1281,7 @@ private: } case id(): { if (auto globalValues = static_cast(stmt->content.get())->item.as()) { - if (auto expList = globalValues->valueList.as()) { + if (auto expList = globalValues->valueList.as()) { return static_cast(expList->exprs.back()); } } @@ -3717,7 +3726,7 @@ private: bool oneLined = defs.size() == expList->exprs.objects().size(); bool nonRecursionFunLit = false; for (auto val : assign->values.objects()) { - if (auto value = singleValueFrom(val)) { + if (auto value = singleValueFrom(val, true)) { if (auto spValue = value->item.as()) { if (auto funLit = spValue->value.as()) { if (funLit->noRecursion) { @@ -3981,14 +3990,6 @@ private: out.push_back(join(temp, ", "sv)); } - void transformExpListLow(ExpListLow_t* expListLow, str_list& out) { - str_list temp; - for (auto exp : expListLow->exprs.objects()) { - transformExp(static_cast(exp), temp, ExpUsage::Closure); - } - out.push_back(join(temp, ", "sv)); - } - void transform_pipe_exp(const node_container& values, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { if (values.size() == 1 && usage == ExpUsage::Closure) { transformUnaryExp(static_cast(values.front()), out, ExpUsage::Closure); @@ -4060,11 +4061,7 @@ private: return; } case ExpUsage::Return: { - auto ret = x->new_ptr(); - ret->explicitReturn = false; - auto expListLow = x->new_ptr(); - expListLow->exprs.push_back(arg); - ret->valueList.set(expListLow); + auto ret = newReturn(arg); transformReturn(ret, out); return; } @@ -4289,11 +4286,7 @@ private: break; } case ExpUsage::Return: { - auto expListLow = exp->new_ptr(); - expListLow->exprs.push_back(e); - auto returnNode = exp->new_ptr(); - returnNode->explicitReturn = false; - returnNode->valueList.set(expListLow); + auto returnNode = newReturn(e); transformReturn(returnNode, out); break; } @@ -4470,11 +4463,7 @@ private: return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false, blockRewrite); } } - auto returnNode = exp->new_ptr(); - returnNode->explicitReturn = false; - auto returnList = exp->new_ptr(); - returnList->exprs.push_back(exp); - returnNode->valueList.set(returnList); + auto returnNode = newReturn(exp); auto stmt = exp->new_ptr(); stmt->content.set(returnNode); block->statementOrComments.push_back(stmt); @@ -4561,12 +4550,8 @@ private: _buf << indent(1) << "return "s << objVar << nl(x); _buf << indent() << "else"s << nl(x); temp.push_back(clearBuf()); - auto ret = x->new_ptr(); - ret->explicitReturn = false; - auto retList = x->new_ptr(); - retList->exprs.push_back(exp->nilCoalesed); - ret->valueList.set(retList); incIndentOffset(); + auto ret = newReturn(exp->nilCoalesed); transformReturn(ret, temp); decIndentOffset(); temp.push_back(indent() + "end"s + nl(x)); @@ -4727,10 +4712,8 @@ private: default: YUEE("AST node mismatch", content); break; } } - if (funLit->defaultReturn.is()) { - auto returnNode = newBlock->new_ptr(); - returnNode->explicitReturn = false; - returnNode->valueList.set(funLit->defaultReturn); + if (auto defaultReturn = funLit->defaultReturn.as()) { + auto returnNode = newReturn(defaultReturn); auto stmt = newBlock->new_ptr(); stmt->content.set(returnNode); newBlock->statementOrComments.push_back(stmt); @@ -5264,11 +5247,9 @@ private: auto expList = expListFrom(last); BREAK_IF(!expList); BREAK_IF(last->appendix && !last->appendix->item.is()); - auto expListLow = x->new_ptr(); - expListLow->exprs.dup(expList->exprs); auto returnNode = x->new_ptr(); returnNode->explicitReturn = false; - returnNode->valueList.set(expListLow); + returnNode->valueList.set(expList); returnNode->allowBlockMacroReturn = true; last->content.set(returnNode); BLOCK_END @@ -5713,7 +5694,7 @@ private: if (!target) target = returnNode; throw CompileError("explicit return statement is not allowed in this context"sv, target); } - if (auto valueList = returnNode->valueList.as()) { + if (auto valueList = returnNode->valueList.as()) { if (valueList->exprs.size() == 1) { auto exp = static_cast(valueList->exprs.back()); if (isPurePipeChain(exp)) { @@ -5783,7 +5764,7 @@ private: return; } else { str_list temp; - transformExpListLow(valueList, temp); + transformExpList(valueList, temp); out.push_back(indent() + "return "s + temp.back() + nl(returnNode)); } } else if (auto tableBlock = returnNode->valueList.as()) { @@ -6250,11 +6231,7 @@ private: case ExpUsage::Return: case ExpUsage::Closure: { auto exp = newExp(partTwo, x); - auto ret = x->new_ptr(); - ret->explicitReturn = false; - auto expListLow = x->new_ptr(); - expListLow->exprs.push_back(exp); - ret->valueList.set(expListLow); + auto ret = newReturn(exp); transformReturn(ret, temp); break; } @@ -6349,11 +6326,7 @@ private: switch (usage) { case ExpUsage::Closure: case ExpUsage::Return: { - auto returnNode = x->new_ptr(); - returnNode->explicitReturn = false; - auto expListLow = x->new_ptr(); - expListLow->exprs.push_back(funLit); - returnNode->valueList.set(expListLow); + auto returnNode = newReturn(funLit); transformReturn(returnNode, temp); break; } @@ -6484,11 +6457,7 @@ private: } switch (usage) { case ExpUsage::Closure: { - auto returnNode = x->new_ptr(); - returnNode->explicitReturn = false; - auto values = x->new_ptr(); - values->exprs.push_back(newChainExp); - returnNode->valueList.set(values); + auto returnNode = newReturn(newChainExp); transformReturn(returnNode, temp); popScope(); *funcStart = anonFuncStart() + nl(x); @@ -6498,11 +6467,7 @@ private: break; } case ExpUsage::Return: { - auto returnNode = x->new_ptr(); - returnNode->explicitReturn = false; - auto values = x->new_ptr(); - values->exprs.push_back(newChainExp); - returnNode->valueList.set(values); + auto returnNode = newReturn(newChainExp); transformReturn(returnNode, temp); break; } @@ -7361,11 +7326,7 @@ private: break; } case ExpUsage::Return: { - auto expListLow = x->new_ptr(); - expListLow->exprs.push_back(node); - auto returnNode = x->new_ptr(); - returnNode->explicitReturn = false; - returnNode->valueList.set(expListLow); + auto returnNode = newReturn(node.to()); transformReturn(returnNode, out); break; } @@ -8377,11 +8338,7 @@ private: auto simpleValue = x->new_ptr(); simpleValue->value.set(tableLit); auto exp = newExp(simpleValue, x); - auto returnNode = x->new_ptr(); - returnNode->explicitReturn = false; - auto expList = x->new_ptr(); - expList->exprs.push_back(exp); - returnNode->valueList.set(expList); + auto returnNode = newReturn(exp); transformReturn(returnNode, out); break; } @@ -9190,10 +9147,7 @@ private: } } else { auto accum = transformForNumInner(forNum, temp); - auto returnNode = x->new_ptr(); - returnNode->explicitReturn = false; - auto expListLow = toAst(accum, x); - returnNode->valueList.set(expListLow); + auto returnNode = newReturn(toAst(accum, forNum)); transformReturn(returnNode, temp); } out.push_back(join(temp)); @@ -9304,10 +9258,7 @@ private: } } else { auto accum = transformForEachInner(forEach, temp); - auto returnNode = x->new_ptr(); - returnNode->explicitReturn = false; - auto expListLow = toAst(accum, x); - returnNode->valueList.set(expListLow); + auto returnNode = newReturn(toAst(accum, forEach)); transformReturn(returnNode, temp); } out.push_back(join(temp)); @@ -10393,8 +10344,8 @@ private: auto assignment = x->new_ptr(); assignment->expList.set(expList); auto assign = x->new_ptr(); - if (auto expListLow = values->valueList.as()) { - assign->values.dup(expListLow->exprs); + if (auto expList = values->valueList.as()) { + assign->values.dup(expList->exprs); } else { auto tableBlock = values->valueList.to(); assign->values.push_back(tableBlock); @@ -11897,8 +11848,8 @@ private: auto assignment = x->new_ptr(); assignment->expList.set(expList); auto assign = x->new_ptr(); - if (auto expListLow = values->valueList.as()) { - assign->values.dup(expListLow->exprs); + if (auto expList = values->valueList.as()) { + assign->values.dup(expList->exprs); } else { auto tableBlock = values->valueList.to(); assign->values.push_back(tableBlock); @@ -11906,7 +11857,7 @@ private: assignment->action.set(assign); bool oneLined = transformAssignment(assignment, temp); for (auto val : assign->values.objects()) { - if (auto value = singleValueFrom(val)) { + if (auto value = singleValueFrom(val, true)) { if (auto spValue = value->item.as()) { if (auto funLit = spValue->value.as()) { if (!funLit->noRecursion) { diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index ab1ba7a..b032826 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -393,7 +393,7 @@ YueParser::YueParser() { in_block = space_break >> *(*set(" \t") >> line_break) >> advance_match >> ensure(Block, pop_indent); LocalFlag = expr('*') | '^'; - LocalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow | expected_expression_error)); + LocalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpList | expected_expression_error)); Local = key("local") >> space >> (LocalFlag | LocalValues | invalid_local_declaration_error); ConstAttrib = key("const"); @@ -478,7 +478,7 @@ YueParser::YueParser() { Continue = key("continue"); BreakLoop = (Break >> -(space >> Exp) | Continue) >> not_alpha_num; - Return = key("return") >> -(space >> (TableBlock | ExpListLow)); + Return = key("return") >> -(space >> (TableBlock | ExpList)); must_exp = Exp | expected_expression_error; @@ -674,7 +674,7 @@ YueParser::YueParser() { Assign = '=' >> space >> Seperator >> ( With | If | Switch | TableBlock | - (SpreadListExp | Exp) >> *(space >> set(",;") >> space >> (SpreadListExp | Exp)) | + (SpreadListExp | Exp) >> *(space >> set(",") >> space >> (SpreadListExp | Exp)) | expected_expression_error ); @@ -927,7 +927,7 @@ YueParser::YueParser() { -(space >> key("using") >> prevent_indent >> space >> ensure(ExpList | expected_expression_error, pop_indent)) ) >> -ClassBlock; - GlobalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow | expected_expression_error)); + GlobalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpList | expected_expression_error)); GlobalOp = expr('*') | '^'; Global = key("global") >> space >> ( -(ConstAttrib >> space) >> ClassDecl | @@ -1056,7 +1056,7 @@ YueParser::YueParser() { return st->fnArrowAvailable; }) >> -(FnArgsDef >> -(':' >> space >> - disable_fun_lit >> ensure(ExpListLow | DefaultValue, enable_fun_lit) + disable_fun_lit >> ensure(ExpList | DefaultValue, enable_fun_lit) ) ) >> space >> FnArrow >> -(space >> Body); @@ -1087,7 +1087,6 @@ YueParser::YueParser() { *(+space_break >> check_indent_match >> space >> pipe_operator >> space >> must_unary_exp); ExpList = Seperator >> Exp >> *(space >> ',' >> space >> Exp); - ExpListLow = Seperator >> Exp >> *(space >> set(",;") >> space >> Exp); arg_line = check_indent_match >> space >> Exp >> *(space >> ',' >> space >> Exp); arg_block = arg_line >> *(space >> ',' >> space_break >> arg_line) >> pop_indent; @@ -1124,17 +1123,18 @@ YueParser::YueParser() { ChainAssign = Seperator >> Exp >> +(space >> '=' >> space >> Exp >> space >> and_('=')) >> space >> Assign; - StatementAppendix = (IfLine | WhileLine | CompFor) >> space; - Statement = + StatementAppendix = IfLine | WhileLine | CompFor; + Statement = ( ( Import | Export | Global | Macro | MacroInPlace | Label - ) >> space | ( + ) | ( Local | While | Repeat | For | Return | BreakLoop | Goto | ShortTabAppending | LocalAttrib | Backcall | PipeBody | ExpListAssign | ChainAssign | StatementAppendix >> empty_block_error | and_(key("else") | key("elseif") | key("when")) >> dangling_clause_error - ) >> space >> -StatementAppendix; + ) >> space >> -StatementAppendix + ) >> space; StatementSep = white >> (set("('\"") | "[[" | "[="); @@ -1158,15 +1158,20 @@ YueParser::YueParser() { return false; }); + is_lax = pl::user(true_(), [](const item_t& item) { + State* st = reinterpret_cast(item.user_data); + return st->lax; + }); + line = *(EmptyLine >> line_break) >> ( - check_indent_match >> space >> Statement | + check_indent_match >> space >> Statement >> *(';' >> -(space >> Statement)) | YueComment | advance_match >> ensure(space >> (indentation_error | Statement), pop_indent) ); - Block = Seperator >> (pl::user(true_(), [](const item_t& item) { - State* st = reinterpret_cast(item.user_data); - return st->lax; - }) >> lax_line >> *(line_break >> lax_line) | line >> *(line_break >> line)); + Block = Seperator >> ( + is_lax >> lax_line >> *(line_break >> lax_line) | + line >> *(line_break >> line) + ); shebang = "#!" >> *(not_(stop) >> any_char); BlockEnd = Block >> plain_white >> stop; diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index c516ccd..df9f39c 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h @@ -319,6 +319,7 @@ private: NONE_AST_RULE(yue_multiline_comment); NONE_AST_RULE(line); NONE_AST_RULE(shebang); + NONE_AST_RULE(is_lax); NONE_AST_RULE(lax_line); AST_RULE(Num); @@ -361,7 +362,6 @@ private: AST_RULE(Backcall); AST_RULE(SubBackcall); AST_RULE(PipeBody); - AST_RULE(ExpListLow); AST_RULE(ExpList); AST_RULE(Return); AST_RULE(With); -- cgit v1.2.3-55-g6feb