aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2026-01-19 17:11:31 +0800
committerLi Jin <dragon-fly@qq.com>2026-01-19 17:11:31 +0800
commitccfe66f87663e10603e453f02894bb82dd23c93b (patch)
tree78f90066a182978bd74218440d13bd3a4dd1d269
parent8a01e9c4ec201ad7079f6863c9236851d162b864 (diff)
downloadyuescript-ccfe66f87663e10603e453f02894bb82dd23c93b.tar.gz
yuescript-ccfe66f87663e10603e453f02894bb82dd23c93b.tar.bz2
yuescript-ccfe66f87663e10603e453f02894bb82dd23c93b.zip
Made `;` work as statements separator.
-rwxr-xr-xdoc/docs/doc/README.md13
-rwxr-xr-xdoc/docs/zh/doc/README.md13
-rw-r--r--spec/inputs/syntax.yue49
-rw-r--r--spec/inputs/unicode/syntax.yue2
-rw-r--r--spec/inputs/unicode/whitespace.yue10
-rw-r--r--spec/inputs/whitespace.yue10
-rw-r--r--spec/outputs/codes_from_doc.lua6
-rw-r--r--spec/outputs/codes_from_doc_zh.lua6
-rw-r--r--spec/outputs/syntax.lua74
-rw-r--r--spec/outputs/unicode/syntax.lua4
-rw-r--r--spec/outputs/unicode/whitespace.lua8
-rw-r--r--spec/outputs/whitespace.lua8
-rw-r--r--src/yue.cpp2
-rw-r--r--src/yuescript/yue_ast.cpp7
-rw-r--r--src/yuescript/yue_ast.h16
-rw-r--r--src/yuescript/yue_compiler.cpp137
-rw-r--r--src/yuescript/yue_parser.cpp35
-rw-r--r--src/yuescript/yue_parser.h2
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
1588 1588
1589YueScript 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. 1589YueScript 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.
1590 1590
1591### Statement Separator
1592
1593A 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:
1594
1595```moonscript
1596a = 1; b = 2; print a + b
1597```
1598<YueDisplay>
1599<pre>
1600a = 1; b = 2; print a + b
1601</pre>
1602</YueDisplay>
1603
1591### Multiline Chaining 1604### Multiline Chaining
1592 1605
1593You can write multi-line chaining function calls with a same indent. 1606You 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
1586 1586
1587月之脚本是一个对空白敏感的语言。你必须在相同的缩进中使用空格 **' '** 或制表符 **'\t'** 来编写一些代码块,如函数体、值列表和一些控制块。包含不同空白的表达式可能意味着不同的事情。制表符被视为4个空格,但最好不要混合使用空格和制表符。 1587月之脚本是一个对空白敏感的语言。你必须在相同的缩进中使用空格 **' '** 或制表符 **'\t'** 来编写一些代码块,如函数体、值列表和一些控制块。包含不同空白的表达式可能意味着不同的事情。制表符被视为4个空格,但最好不要混合使用空格和制表符。
1588 1588
1589### 语句分隔符
1590
1591一条语句通常以换行结束。你也可以使用分号 `;` 显式结束一条语句,从而在同一行中编写多条语句:
1592
1593```moonscript
1594a = 1; b = 2; print a + b
1595```
1596<YueDisplay>
1597<pre>
1598a = 1; b = 2; print a + b
1599</pre>
1600</YueDisplay>
1601
1589### 多行链式调用 1602### 多行链式调用
1590 1603
1591你可以使用相同的缩进来编写多行链式函数调用。 1604你可以使用相同的缩进来编写多行链式函数调用。
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
7func arg1, arg2, another, arg3 7func arg1, arg2, another, arg3
8 8
9here, we = () ->, yeah 9here, we = () ->, yeah
10the, different = () -> approach; yeah 10the, different = (() -> approach), yeah
11 11
12dad() 12dad()
13dad(lord) 13dad(lord)
@@ -321,7 +321,7 @@ ajax url,
321 (error) -> 321 (error) ->
322 print error 322 print error
323 323
324-- 324--
325a += 3 - 5 325a += 3 - 5
326a *= 3 + 5 326a *= 3 + 5
327a *= 3 327a *= 3
@@ -480,11 +480,54 @@ do
480 480
481do 481do
482 return res if res ~= "" 482 return res if res ~= ""
483 483
484 484
485do 485do
486 return res if res ~= "" 486 return res if res ~= ""
487 -- 487 --
488 488
489do
490 a = 1; b = 2; c = a + b
491 print a; print b; print c
492
493 f = ->
494 a = 1; b = 2; a + b
495
496 a = 1;
497 b = 2;
498
499 success, result = try func!; print result if success
500
501 value = "foo"; print value; value = value .. "bar"; print value
502
503 do
504 if ok then print "ok!"; return 42
505
506 for i=1,3
507 print i; continue
508
509 n = 0
510 while n < 2
511 print "n=", n; n += 1
512
513 obj = {}
514 obj\set 10; obj\get!; print "done"
515
516 with tbl
517 \push 1; print "push"
518
519 a = 5
520 if a > 3
521 print "big"; b = a * 2; print b
522 else
523 print "small"; b = a
524
525 try
526 x = 1; y = 2; print x + y
527 catch err
528 print "error:", err
529
530 q = 1;; w = 2;;; e = 3; print q, w, e;
531
489nil 532nil
490 533
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 @@
7函数 参数1, 参数2, 另外, 参数3 7函数 参数1, 参数2, 另外, 参数3
8 8
9这里, 我们 = () ->, 是的 9这里, 我们 = () ->, 是的
10这个, 不同 = () -> 方法; 是的 10这个, 不同 = (() -> 方法), 是的
11 11
12爸爸() 12爸爸()
13爸爸(主) 13爸爸(主)
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 = ->
97 变量c -- v3 97 变量c -- v3
98 98
99v1, v2, \ 99v1, v2, \
100 v3 = -> 100 v3 = (->
101 变量a; \-- 函数结束于v1 101 变量a), \-- 函数结束于v1
102 变量b, \-- v2 102 变量b, \-- v2
103 变量c -- v3 103 变量c -- v3
104 104
105变量a, 变量b, \ 105变量a, 变量b, \
106 变量c, 变量d, \ 106 变量c, 变量d, \
107变量e, 变量f = 1, \ 107变量e, 变量f = 1, \
108 f2 108 (f2
109 :abc; \-- 参数2 109 :abc), \-- 参数2
110 3, \ 110 3, \
111 4, \ 111 4, \
112 函数5 abc; \-- 参数5 112 函数5(abc), \-- 参数5
113 6 113 6
114 114
115for 变量a, \-- 解构1 115for 变量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 = ->
128 c -- v3 128 c -- v3
129 129
130v1, v2, \ 130v1, v2, \
131 v3 = -> 131 v3 = (->
132 a; \-- end of function for v1 132 a), \-- end of function for v1
133 b, \-- v2 133 b, \-- v2
134 c -- v3 134 c -- v3
135 135
136a, b, \ 136a, b, \
137 c, d, \ 137 c, d, \
138e, f = 1, \ 138e, f = 1, \
139 f2 139 (f2
140 :abc; \-- arg2 140 :abc), \-- arg2
141 3, \ 141 3, \
142 4, \ 142 4, \
143 f5 abc; \-- arg5 143 f5(abc), \-- arg5
144 6 144 6
145 145
146for a, \-- destruct 1 146for 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
756 local first = select(1, ...) 756 local first = select(1, ...)
757 return print(ok, count, first) 757 return print(ok, count, first)
758end)(fn(true)) 758end)(fn(true))
759local a = 1
760local b = 2
761print(a + b)
759Rx.Observable.fromRange(1, 8):filter(function(x) 762Rx.Observable.fromRange(1, 8):filter(function(x)
760 return x % 2 == 0 763 return x % 2 == 0
761end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) 764end):concat(Rx.Observable.of('who do we appreciate')):map(function(value)
@@ -3283,6 +3286,9 @@ end
3283 local first = select(1, ...) 3286 local first = select(1, ...)
3284 return print(ok, count, first) 3287 return print(ok, count, first)
3285end)(fn(true)) 3288end)(fn(true))
3289local a = 1
3290local b = 2
3291print(a + b)
3286Rx.Observable.fromRange(1, 8):filter(function(x) 3292Rx.Observable.fromRange(1, 8):filter(function(x)
3287 return x % 2 == 0 3293 return x % 2 == 0
3288end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) 3294end):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
756 local first = select(1, ...) 756 local first = select(1, ...)
757 return print(ok, count, first) 757 return print(ok, count, first)
758end)(fn(true)) 758end)(fn(true))
759local a = 1
760local b = 2
761print(a + b)
759Rx.Observable.fromRange(1, 8):filter(function(x) 762Rx.Observable.fromRange(1, 8):filter(function(x)
760 return x % 2 == 0 763 return x % 2 == 0
761end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) 764end):concat(Rx.Observable.of('who do we appreciate')):map(function(value)
@@ -3277,6 +3280,9 @@ end
3277 local first = select(1, ...) 3280 local first = select(1, ...)
3278 return print(ok, count, first) 3281 return print(ok, count, first)
3279end)(fn(true)) 3282end)(fn(true))
3283local a = 1
3284local b = 2
3285print(a + b)
3280Rx.Observable.fromRange(1, 8):filter(function(x) 3286Rx.Observable.fromRange(1, 8):filter(function(x)
3281 return x % 2 == 0 3287 return x % 2 == 0
3282end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) 3288end):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)
5local we 5local we
6here, we = function() end, yeah 6here, we = function() end, yeah
7local the, different 7local the, different
8the, different = function() 8the, different = (function()
9 return approach 9 return approach
10end, yeah 10end), yeah
11dad() 11dad()
12dad(lord) 12dad(lord)
13hello(one, two)(); 13hello(one, two)();
@@ -441,4 +441,74 @@ do
441 end 441 end
442 end)()) 442 end)())
443end 443end
444do
445 a = 1
446 local b = 2
447 local c = a + b
448 print(a)
449 print(b)
450 print(c)
451 f = function()
452 a = 1
453 b = 2
454 return a + b
455 end
456 a = 1
457 b = 2
458 local success, result = pcall(function()
459 return func()
460 end)
461 if success then
462 print(result)
463 end
464 local value = "foo"
465 print(value)
466 value = value .. "bar"
467 print(value)
468 do
469 if ok then
470 print("ok!")
471 end
472 return 42
473 end
474 for i = 1, 3 do
475 print(i)
476 goto _continue_0
477 ::_continue_0::
478 end
479 local n = 0
480 while n < 2 do
481 print("n=", n)
482 n = n + 1
483 end
484 local obj = { }
485 obj:set(10)
486 obj:get()
487 print("done")
488 do
489 local _with_0 = tbl
490 _with_0:push(1)
491 print("push")
492 end
493 a = 5
494 if a > 3 then
495 print("big")
496 b = a * 2
497 print(b)
498 else
499 print("small")
500 b = a
501 end
502 xpcall(function()
503 x = 1
504 y = 2
505 return print(x + y)
506 end, function(err)
507 return print("error:", err)
508 end)
509 local q = 1
510 local w = 2
511 local e = 3
512 print(q, w, e)
513end
444return nil 514return 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)
5local _u6211_u4eec 5local _u6211_u4eec
6_u8fd9_u91cc, _u6211_u4eec = function() end, _u662f_u7684 6_u8fd9_u91cc, _u6211_u4eec = function() end, _u662f_u7684
7local _u8fd9_u4e2a, _u4e0d_u540c 7local _u8fd9_u4e2a, _u4e0d_u540c
8_u8fd9_u4e2a, _u4e0d_u540c = function() 8_u8fd9_u4e2a, _u4e0d_u540c = (function()
9 return _u65b9_u6cd5 9 return _u65b9_u6cd5
10end, _u662f_u7684 10end), _u662f_u7684
11_u7238_u7238() 11_u7238_u7238()
12_u7238_u7238(_u4e3b) 12_u7238_u7238(_u4e3b)
13_u4f60_u597d(_u4e00, _u4e8c)(); 13_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()
82 return _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc 82 return _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc
83end 83end
84local v1, v2, v3 84local v1, v2, v3
85v1, v2, v3 = function() 85v1, v2, v3 = (function()
86 return _u53d8_u91cfa 86 return _u53d8_u91cfa
87end, _u53d8_u91cfb, _u53d8_u91cfc 87end), _u53d8_u91cfb, _u53d8_u91cfc
88local _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc, _u53d8_u91cfd, _u53d8_u91cfe, _u53d8_u91cff = 1, f2({ 88local _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc, _u53d8_u91cfd, _u53d8_u91cfe, _u53d8_u91cff = 1, (f2({
89 abc = abc 89 abc = abc
90}), 3, 4, _u51fd_u65705(abc), 6 90})), 3, 4, _u51fd_u65705(abc), 6
91for _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc in pairs(_u5bf9_u8c61tb) do 91for _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc in pairs(_u5bf9_u8c61tb) do
92 _u6253_u5370(_u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc) 92 _u6253_u5370(_u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc)
93end 93end
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()
94 return a, b, c 94 return a, b, c
95end 95end
96local v1, v2, v3 96local v1, v2, v3
97v1, v2, v3 = function() 97v1, v2, v3 = (function()
98 return a 98 return a
99end, b, c 99end), b, c
100local a, b, c, d, e, f = 1, f2({ 100local a, b, c, d, e, f = 1, (f2({
101 abc = abc 101 abc = abc
102}), 3, 4, f5(abc), 6 102})), 3, 4, f5(abc), 6
103for a, b, c in pairs(tb) do 103for a, b, c in pairs(tb) do
104 print(a, b, c) 104 print(a, b, c)
105end 105end
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) {
341 " -- Read from standard in, print to standard out\n" 341 " -- Read from standard in, print to standard out\n"
342 " (Must be first and only argument)\n\n" 342 " (Must be first and only argument)\n\n"
343 " --target=version Specify the Lua version that codes will be generated to\n" 343 " --target=version Specify the Lua version that codes will be generated to\n"
344 " (version can only be 5.1, 5.2, 5.3 or 5.4)\n" 344 " (version can only be 5.1 to 5.5)\n"
345 " --path=path_str Append an extra Lua search path string to package.path\n\n" 345 " --path=path_str Append an extra Lua search path string to package.path\n\n"
346 " Execute without options to enter REPL, type symbol '$'\n" 346 " Execute without options to enter REPL, type symbol '$'\n"
347 " in a single line to start/stop multi-line mode\n" 347 " 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 {
370 } 370 }
371 return join(temp, "\n"sv); 371 return join(temp, "\n"sv);
372} 372}
373std::string ExpListLow_t::to_string(void* ud) const {
374 str_list temp;
375 for (auto exp : exprs.objects()) {
376 temp.emplace_back(exp->to_string(ud));
377 }
378 return join(temp, "; "sv);
379}
380std::string ExpList_t::to_string(void* ud) const { 373std::string ExpList_t::to_string(void* ud) const {
381 str_list temp; 374 str_list temp;
382 for (auto exp : exprs.objects()) { 375 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 {}; }
50// clang-format off 50// clang-format off
51 51
52namespace yue { 52namespace yue {
53class ExpListLow_t; 53class ExpList_t;
54class TableBlock_t; 54class TableBlock_t;
55class SimpleTable_t; 55class SimpleTable_t;
56class TableLit_t; 56class TableLit_t;
@@ -156,7 +156,7 @@ AST_END(NameList)
156 156
157AST_NODE(LocalValues) 157AST_NODE(LocalValues)
158 ast_ptr<true, NameList_t> nameList; 158 ast_ptr<true, NameList_t> nameList;
159 ast_sel<false, TableBlock_t, ExpListLow_t> valueList; 159 ast_sel<false, TableBlock_t, ExpList_t> valueList;
160 AST_MEMBER(LocalValues, &nameList, &valueList) 160 AST_MEMBER(LocalValues, &nameList, &valueList)
161AST_END(LocalValues) 161AST_END(LocalValues)
162 162
@@ -273,12 +273,6 @@ AST_NODE(Backcall)
273 AST_MEMBER(Backcall, &argsDef, &arrow, &value) 273 AST_MEMBER(Backcall, &argsDef, &arrow, &value)
274AST_END(Backcall) 274AST_END(Backcall)
275 275
276AST_NODE(ExpListLow)
277 ast_ptr<true, Seperator_t> sep;
278 ast_list<true, Exp_t> exprs;
279 AST_MEMBER(ExpListLow, &sep, &exprs)
280AST_END(ExpListLow)
281
282AST_NODE(ExpList) 276AST_NODE(ExpList)
283 ast_ptr<true, Seperator_t> sep; 277 ast_ptr<true, Seperator_t> sep;
284 ast_list<true, Exp_t> exprs; 278 ast_list<true, Exp_t> exprs;
@@ -290,7 +284,7 @@ AST_END(ExpList)
290AST_NODE(Return) 284AST_NODE(Return)
291 bool allowBlockMacroReturn = false; 285 bool allowBlockMacroReturn = false;
292 bool explicitReturn = true; 286 bool explicitReturn = true;
293 ast_sel<false, TableBlock_t, ExpListLow_t> valueList; 287 ast_sel<false, TableBlock_t, ExpList_t> valueList;
294 AST_MEMBER(Return, &valueList) 288 AST_MEMBER(Return, &valueList)
295AST_END(Return) 289AST_END(Return)
296 290
@@ -764,7 +758,7 @@ AST_END(ClassDecl)
764 758
765AST_NODE(GlobalValues) 759AST_NODE(GlobalValues)
766 ast_ptr<true, NameList_t> nameList; 760 ast_ptr<true, NameList_t> nameList;
767 ast_sel<false, TableBlock_t, ExpListLow_t> valueList; 761 ast_sel<false, TableBlock_t, ExpList_t> valueList;
768 AST_MEMBER(GlobalValues, &nameList, &valueList) 762 AST_MEMBER(GlobalValues, &nameList, &valueList)
769AST_END(GlobalValues) 763AST_END(GlobalValues)
770 764
@@ -819,7 +813,7 @@ AST_END(FnArrow)
819 813
820AST_NODE(FunLit) 814AST_NODE(FunLit)
821 ast_ptr<false, FnArgsDef_t> argsDef; 815 ast_ptr<false, FnArgsDef_t> argsDef;
822 ast_sel<false, ExpListLow_t, DefaultValue_t> defaultReturn; 816 ast_sel<false, ExpList_t, DefaultValue_t> defaultReturn;
823 ast_ptr<true, FnArrow_t> arrow; 817 ast_ptr<true, FnArrow_t> arrow;
824 ast_ptr<false, Body_t> body; 818 ast_ptr<false, Body_t> body;
825 bool noRecursion = false; 819 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<std::string> Metamethods = {
78 "close"s // Lua 5.4 78 "close"s // Lua 5.4
79}; 79};
80 80
81const std::string_view version = "0.31.1"sv; 81const std::string_view version = "0.32.0"sv;
82const std::string_view extension = "yue"sv; 82const std::string_view extension = "yue"sv;
83 83
84class CompileError : public std::logic_error { 84class CompileError : public std::logic_error {
@@ -1057,13 +1057,6 @@ private:
1057 } 1057 }
1058 break; 1058 break;
1059 } 1059 }
1060 case id<ExpListLow_t>(): {
1061 auto expList = static_cast<ExpListLow_t*>(item);
1062 if (expList->exprs.size() == 1) {
1063 exp = static_cast<Exp_t*>(expList->exprs.front());
1064 }
1065 break;
1066 }
1067 case id<SwitchList_t>(): { 1060 case id<SwitchList_t>(): {
1068 auto expList = static_cast<SwitchList_t*>(item); 1061 auto expList = static_cast<SwitchList_t*>(item);
1069 if (expList->exprs.size() == 1) { 1062 if (expList->exprs.size() == 1) {
@@ -1092,12 +1085,12 @@ private:
1092 return nullptr; 1085 return nullptr;
1093 } 1086 }
1094 1087
1095 Value_t* singleValueFrom(ast_node* item) const { 1088 Value_t* singleValueFrom(ast_node* item, bool forceUnparened = false) const {
1096 if (auto unary = singleUnaryExpFrom(item)) { 1089 if (auto unary = singleUnaryExpFrom(item)) {
1097 if (unary->ops.empty()) { 1090 if (unary->ops.empty()) {
1098 Value_t* value = static_cast<Value_t*>(unary->expos.back()); 1091 Value_t* value = static_cast<Value_t*>(unary->expos.back());
1099 if (auto chain = ast_cast<ChainValue_t>(value->item); chain && chain->items.size() == 1) { 1092 if (auto chain = ast_cast<ChainValue_t>(value->item); chain && chain->items.size() == 1) {
1100 if (auto parens = chain->get_by_path<Callable_t, Parens_t>(); parens && parens->extra) { 1093 if (auto parens = chain->get_by_path<Callable_t, Parens_t>(); parens && (forceUnparened || parens->extra)) {
1101 if (auto insideValue = singleValueFrom(parens->expr)) { 1094 if (auto insideValue = singleValueFrom(parens->expr)) {
1102 return insideValue; 1095 return insideValue;
1103 } 1096 }
@@ -1157,6 +1150,22 @@ private:
1157 return exp; 1150 return exp;
1158 } 1151 }
1159 1152
1153 ast_ptr<false, Return_t> newReturn(Exp_t* value) {
1154 auto returnNode = value->new_ptr<Return_t>();
1155 returnNode->explicitReturn = false;
1156 auto expList = value->new_ptr<ExpList_t>();
1157 expList->exprs.push_back(value);
1158 returnNode->valueList.set(expList);
1159 return returnNode;
1160 }
1161
1162 ast_ptr<false, Return_t> newReturn(ExpList_t* valueList) {
1163 auto returnNode = valueList->new_ptr<Return_t>();
1164 returnNode->explicitReturn = false;
1165 returnNode->valueList.set(valueList);
1166 return returnNode;
1167 }
1168
1160 SimpleValue_t* simpleSingleValueFrom(ast_node* node) const { 1169 SimpleValue_t* simpleSingleValueFrom(ast_node* node) const {
1161 auto value = singleValueFrom(node); 1170 auto value = singleValueFrom(node);
1162 if (value && value->item.is<SimpleValue_t>()) { 1171 if (value && value->item.is<SimpleValue_t>()) {
@@ -1264,7 +1273,7 @@ private:
1264 } 1273 }
1265 case id<Local_t>(): { 1274 case id<Local_t>(): {
1266 if (auto localValues = static_cast<Local_t*>(stmt->content.get())->item.as<LocalValues_t>()) { 1275 if (auto localValues = static_cast<Local_t*>(stmt->content.get())->item.as<LocalValues_t>()) {
1267 if (auto expList = localValues->valueList.as<ExpListLow_t>()) { 1276 if (auto expList = localValues->valueList.as<ExpList_t>()) {
1268 return static_cast<Exp_t*>(expList->exprs.back()); 1277 return static_cast<Exp_t*>(expList->exprs.back());
1269 } 1278 }
1270 } 1279 }
@@ -1272,7 +1281,7 @@ private:
1272 } 1281 }
1273 case id<Global_t>(): { 1282 case id<Global_t>(): {
1274 if (auto globalValues = static_cast<Global_t*>(stmt->content.get())->item.as<GlobalValues_t>()) { 1283 if (auto globalValues = static_cast<Global_t*>(stmt->content.get())->item.as<GlobalValues_t>()) {
1275 if (auto expList = globalValues->valueList.as<ExpListLow_t>()) { 1284 if (auto expList = globalValues->valueList.as<ExpList_t>()) {
1276 return static_cast<Exp_t*>(expList->exprs.back()); 1285 return static_cast<Exp_t*>(expList->exprs.back());
1277 } 1286 }
1278 } 1287 }
@@ -3717,7 +3726,7 @@ private:
3717 bool oneLined = defs.size() == expList->exprs.objects().size(); 3726 bool oneLined = defs.size() == expList->exprs.objects().size();
3718 bool nonRecursionFunLit = false; 3727 bool nonRecursionFunLit = false;
3719 for (auto val : assign->values.objects()) { 3728 for (auto val : assign->values.objects()) {
3720 if (auto value = singleValueFrom(val)) { 3729 if (auto value = singleValueFrom(val, true)) {
3721 if (auto spValue = value->item.as<SimpleValue_t>()) { 3730 if (auto spValue = value->item.as<SimpleValue_t>()) {
3722 if (auto funLit = spValue->value.as<FunLit_t>()) { 3731 if (auto funLit = spValue->value.as<FunLit_t>()) {
3723 if (funLit->noRecursion) { 3732 if (funLit->noRecursion) {
@@ -3981,14 +3990,6 @@ private:
3981 out.push_back(join(temp, ", "sv)); 3990 out.push_back(join(temp, ", "sv));
3982 } 3991 }
3983 3992
3984 void transformExpListLow(ExpListLow_t* expListLow, str_list& out) {
3985 str_list temp;
3986 for (auto exp : expListLow->exprs.objects()) {
3987 transformExp(static_cast<Exp_t*>(exp), temp, ExpUsage::Closure);
3988 }
3989 out.push_back(join(temp, ", "sv));
3990 }
3991
3992 void transform_pipe_exp(const node_container& values, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 3993 void transform_pipe_exp(const node_container& values, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
3993 if (values.size() == 1 && usage == ExpUsage::Closure) { 3994 if (values.size() == 1 && usage == ExpUsage::Closure) {
3994 transformUnaryExp(static_cast<UnaryExp_t*>(values.front()), out, ExpUsage::Closure); 3995 transformUnaryExp(static_cast<UnaryExp_t*>(values.front()), out, ExpUsage::Closure);
@@ -4060,11 +4061,7 @@ private:
4060 return; 4061 return;
4061 } 4062 }
4062 case ExpUsage::Return: { 4063 case ExpUsage::Return: {
4063 auto ret = x->new_ptr<Return_t>(); 4064 auto ret = newReturn(arg);
4064 ret->explicitReturn = false;
4065 auto expListLow = x->new_ptr<ExpListLow_t>();
4066 expListLow->exprs.push_back(arg);
4067 ret->valueList.set(expListLow);
4068 transformReturn(ret, out); 4065 transformReturn(ret, out);
4069 return; 4066 return;
4070 } 4067 }
@@ -4289,11 +4286,7 @@ private:
4289 break; 4286 break;
4290 } 4287 }
4291 case ExpUsage::Return: { 4288 case ExpUsage::Return: {
4292 auto expListLow = exp->new_ptr<ExpListLow_t>(); 4289 auto returnNode = newReturn(e);
4293 expListLow->exprs.push_back(e);
4294 auto returnNode = exp->new_ptr<Return_t>();
4295 returnNode->explicitReturn = false;
4296 returnNode->valueList.set(expListLow);
4297 transformReturn(returnNode, out); 4290 transformReturn(returnNode, out);
4298 break; 4291 break;
4299 } 4292 }
@@ -4470,11 +4463,7 @@ private:
4470 return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false, blockRewrite); 4463 return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false, blockRewrite);
4471 } 4464 }
4472 } 4465 }
4473 auto returnNode = exp->new_ptr<Return_t>(); 4466 auto returnNode = newReturn(exp);
4474 returnNode->explicitReturn = false;
4475 auto returnList = exp->new_ptr<ExpListLow_t>();
4476 returnList->exprs.push_back(exp);
4477 returnNode->valueList.set(returnList);
4478 auto stmt = exp->new_ptr<Statement_t>(); 4467 auto stmt = exp->new_ptr<Statement_t>();
4479 stmt->content.set(returnNode); 4468 stmt->content.set(returnNode);
4480 block->statementOrComments.push_back(stmt); 4469 block->statementOrComments.push_back(stmt);
@@ -4561,12 +4550,8 @@ private:
4561 _buf << indent(1) << "return "s << objVar << nl(x); 4550 _buf << indent(1) << "return "s << objVar << nl(x);
4562 _buf << indent() << "else"s << nl(x); 4551 _buf << indent() << "else"s << nl(x);
4563 temp.push_back(clearBuf()); 4552 temp.push_back(clearBuf());
4564 auto ret = x->new_ptr<Return_t>();
4565 ret->explicitReturn = false;
4566 auto retList = x->new_ptr<ExpListLow_t>();
4567 retList->exprs.push_back(exp->nilCoalesed);
4568 ret->valueList.set(retList);
4569 incIndentOffset(); 4553 incIndentOffset();
4554 auto ret = newReturn(exp->nilCoalesed);
4570 transformReturn(ret, temp); 4555 transformReturn(ret, temp);
4571 decIndentOffset(); 4556 decIndentOffset();
4572 temp.push_back(indent() + "end"s + nl(x)); 4557 temp.push_back(indent() + "end"s + nl(x));
@@ -4727,10 +4712,8 @@ private:
4727 default: YUEE("AST node mismatch", content); break; 4712 default: YUEE("AST node mismatch", content); break;
4728 } 4713 }
4729 } 4714 }
4730 if (funLit->defaultReturn.is<ExpListLow_t>()) { 4715 if (auto defaultReturn = funLit->defaultReturn.as<ExpList_t>()) {
4731 auto returnNode = newBlock->new_ptr<Return_t>(); 4716 auto returnNode = newReturn(defaultReturn);
4732 returnNode->explicitReturn = false;
4733 returnNode->valueList.set(funLit->defaultReturn);
4734 auto stmt = newBlock->new_ptr<Statement_t>(); 4717 auto stmt = newBlock->new_ptr<Statement_t>();
4735 stmt->content.set(returnNode); 4718 stmt->content.set(returnNode);
4736 newBlock->statementOrComments.push_back(stmt); 4719 newBlock->statementOrComments.push_back(stmt);
@@ -5264,11 +5247,9 @@ private:
5264 auto expList = expListFrom(last); 5247 auto expList = expListFrom(last);
5265 BREAK_IF(!expList); 5248 BREAK_IF(!expList);
5266 BREAK_IF(last->appendix && !last->appendix->item.is<IfLine_t>()); 5249 BREAK_IF(last->appendix && !last->appendix->item.is<IfLine_t>());
5267 auto expListLow = x->new_ptr<ExpListLow_t>();
5268 expListLow->exprs.dup(expList->exprs);
5269 auto returnNode = x->new_ptr<Return_t>(); 5250 auto returnNode = x->new_ptr<Return_t>();
5270 returnNode->explicitReturn = false; 5251 returnNode->explicitReturn = false;
5271 returnNode->valueList.set(expListLow); 5252 returnNode->valueList.set(expList);
5272 returnNode->allowBlockMacroReturn = true; 5253 returnNode->allowBlockMacroReturn = true;
5273 last->content.set(returnNode); 5254 last->content.set(returnNode);
5274 BLOCK_END 5255 BLOCK_END
@@ -5713,7 +5694,7 @@ private:
5713 if (!target) target = returnNode; 5694 if (!target) target = returnNode;
5714 throw CompileError("explicit return statement is not allowed in this context"sv, target); 5695 throw CompileError("explicit return statement is not allowed in this context"sv, target);
5715 } 5696 }
5716 if (auto valueList = returnNode->valueList.as<ExpListLow_t>()) { 5697 if (auto valueList = returnNode->valueList.as<ExpList_t>()) {
5717 if (valueList->exprs.size() == 1) { 5698 if (valueList->exprs.size() == 1) {
5718 auto exp = static_cast<Exp_t*>(valueList->exprs.back()); 5699 auto exp = static_cast<Exp_t*>(valueList->exprs.back());
5719 if (isPurePipeChain(exp)) { 5700 if (isPurePipeChain(exp)) {
@@ -5783,7 +5764,7 @@ private:
5783 return; 5764 return;
5784 } else { 5765 } else {
5785 str_list temp; 5766 str_list temp;
5786 transformExpListLow(valueList, temp); 5767 transformExpList(valueList, temp);
5787 out.push_back(indent() + "return "s + temp.back() + nl(returnNode)); 5768 out.push_back(indent() + "return "s + temp.back() + nl(returnNode));
5788 } 5769 }
5789 } else if (auto tableBlock = returnNode->valueList.as<TableBlock_t>()) { 5770 } else if (auto tableBlock = returnNode->valueList.as<TableBlock_t>()) {
@@ -6250,11 +6231,7 @@ private:
6250 case ExpUsage::Return: 6231 case ExpUsage::Return:
6251 case ExpUsage::Closure: { 6232 case ExpUsage::Closure: {
6252 auto exp = newExp(partTwo, x); 6233 auto exp = newExp(partTwo, x);
6253 auto ret = x->new_ptr<Return_t>(); 6234 auto ret = newReturn(exp);
6254 ret->explicitReturn = false;
6255 auto expListLow = x->new_ptr<ExpListLow_t>();
6256 expListLow->exprs.push_back(exp);
6257 ret->valueList.set(expListLow);
6258 transformReturn(ret, temp); 6235 transformReturn(ret, temp);
6259 break; 6236 break;
6260 } 6237 }
@@ -6349,11 +6326,7 @@ private:
6349 switch (usage) { 6326 switch (usage) {
6350 case ExpUsage::Closure: 6327 case ExpUsage::Closure:
6351 case ExpUsage::Return: { 6328 case ExpUsage::Return: {
6352 auto returnNode = x->new_ptr<Return_t>(); 6329 auto returnNode = newReturn(funLit);
6353 returnNode->explicitReturn = false;
6354 auto expListLow = x->new_ptr<ExpListLow_t>();
6355 expListLow->exprs.push_back(funLit);
6356 returnNode->valueList.set(expListLow);
6357 transformReturn(returnNode, temp); 6330 transformReturn(returnNode, temp);
6358 break; 6331 break;
6359 } 6332 }
@@ -6484,11 +6457,7 @@ private:
6484 } 6457 }
6485 switch (usage) { 6458 switch (usage) {
6486 case ExpUsage::Closure: { 6459 case ExpUsage::Closure: {
6487 auto returnNode = x->new_ptr<Return_t>(); 6460 auto returnNode = newReturn(newChainExp);
6488 returnNode->explicitReturn = false;
6489 auto values = x->new_ptr<ExpListLow_t>();
6490 values->exprs.push_back(newChainExp);
6491 returnNode->valueList.set(values);
6492 transformReturn(returnNode, temp); 6461 transformReturn(returnNode, temp);
6493 popScope(); 6462 popScope();
6494 *funcStart = anonFuncStart() + nl(x); 6463 *funcStart = anonFuncStart() + nl(x);
@@ -6498,11 +6467,7 @@ private:
6498 break; 6467 break;
6499 } 6468 }
6500 case ExpUsage::Return: { 6469 case ExpUsage::Return: {
6501 auto returnNode = x->new_ptr<Return_t>(); 6470 auto returnNode = newReturn(newChainExp);
6502 returnNode->explicitReturn = false;
6503 auto values = x->new_ptr<ExpListLow_t>();
6504 values->exprs.push_back(newChainExp);
6505 returnNode->valueList.set(values);
6506 transformReturn(returnNode, temp); 6471 transformReturn(returnNode, temp);
6507 break; 6472 break;
6508 } 6473 }
@@ -7361,11 +7326,7 @@ private:
7361 break; 7326 break;
7362 } 7327 }
7363 case ExpUsage::Return: { 7328 case ExpUsage::Return: {
7364 auto expListLow = x->new_ptr<ExpListLow_t>(); 7329 auto returnNode = newReturn(node.to<Exp_t>());
7365 expListLow->exprs.push_back(node);
7366 auto returnNode = x->new_ptr<Return_t>();
7367 returnNode->explicitReturn = false;
7368 returnNode->valueList.set(expListLow);
7369 transformReturn(returnNode, out); 7330 transformReturn(returnNode, out);
7370 break; 7331 break;
7371 } 7332 }
@@ -8377,11 +8338,7 @@ private:
8377 auto simpleValue = x->new_ptr<SimpleValue_t>(); 8338 auto simpleValue = x->new_ptr<SimpleValue_t>();
8378 simpleValue->value.set(tableLit); 8339 simpleValue->value.set(tableLit);
8379 auto exp = newExp(simpleValue, x); 8340 auto exp = newExp(simpleValue, x);
8380 auto returnNode = x->new_ptr<Return_t>(); 8341 auto returnNode = newReturn(exp);
8381 returnNode->explicitReturn = false;
8382 auto expList = x->new_ptr<ExpListLow_t>();
8383 expList->exprs.push_back(exp);
8384 returnNode->valueList.set(expList);
8385 transformReturn(returnNode, out); 8342 transformReturn(returnNode, out);
8386 break; 8343 break;
8387 } 8344 }
@@ -9190,10 +9147,7 @@ private:
9190 } 9147 }
9191 } else { 9148 } else {
9192 auto accum = transformForNumInner(forNum, temp); 9149 auto accum = transformForNumInner(forNum, temp);
9193 auto returnNode = x->new_ptr<Return_t>(); 9150 auto returnNode = newReturn(toAst<Exp_t>(accum, forNum));
9194 returnNode->explicitReturn = false;
9195 auto expListLow = toAst<ExpListLow_t>(accum, x);
9196 returnNode->valueList.set(expListLow);
9197 transformReturn(returnNode, temp); 9151 transformReturn(returnNode, temp);
9198 } 9152 }
9199 out.push_back(join(temp)); 9153 out.push_back(join(temp));
@@ -9304,10 +9258,7 @@ private:
9304 } 9258 }
9305 } else { 9259 } else {
9306 auto accum = transformForEachInner(forEach, temp); 9260 auto accum = transformForEachInner(forEach, temp);
9307 auto returnNode = x->new_ptr<Return_t>(); 9261 auto returnNode = newReturn(toAst<Exp_t>(accum, forEach));
9308 returnNode->explicitReturn = false;
9309 auto expListLow = toAst<ExpListLow_t>(accum, x);
9310 returnNode->valueList.set(expListLow);
9311 transformReturn(returnNode, temp); 9262 transformReturn(returnNode, temp);
9312 } 9263 }
9313 out.push_back(join(temp)); 9264 out.push_back(join(temp));
@@ -10393,8 +10344,8 @@ private:
10393 auto assignment = x->new_ptr<ExpListAssign_t>(); 10344 auto assignment = x->new_ptr<ExpListAssign_t>();
10394 assignment->expList.set(expList); 10345 assignment->expList.set(expList);
10395 auto assign = x->new_ptr<Assign_t>(); 10346 auto assign = x->new_ptr<Assign_t>();
10396 if (auto expListLow = values->valueList.as<ExpListLow_t>()) { 10347 if (auto expList = values->valueList.as<ExpList_t>()) {
10397 assign->values.dup(expListLow->exprs); 10348 assign->values.dup(expList->exprs);
10398 } else { 10349 } else {
10399 auto tableBlock = values->valueList.to<TableBlock_t>(); 10350 auto tableBlock = values->valueList.to<TableBlock_t>();
10400 assign->values.push_back(tableBlock); 10351 assign->values.push_back(tableBlock);
@@ -11897,8 +11848,8 @@ private:
11897 auto assignment = x->new_ptr<ExpListAssign_t>(); 11848 auto assignment = x->new_ptr<ExpListAssign_t>();
11898 assignment->expList.set(expList); 11849 assignment->expList.set(expList);
11899 auto assign = x->new_ptr<Assign_t>(); 11850 auto assign = x->new_ptr<Assign_t>();
11900 if (auto expListLow = values->valueList.as<ExpListLow_t>()) { 11851 if (auto expList = values->valueList.as<ExpList_t>()) {
11901 assign->values.dup(expListLow->exprs); 11852 assign->values.dup(expList->exprs);
11902 } else { 11853 } else {
11903 auto tableBlock = values->valueList.to<TableBlock_t>(); 11854 auto tableBlock = values->valueList.to<TableBlock_t>();
11904 assign->values.push_back(tableBlock); 11855 assign->values.push_back(tableBlock);
@@ -11906,7 +11857,7 @@ private:
11906 assignment->action.set(assign); 11857 assignment->action.set(assign);
11907 bool oneLined = transformAssignment(assignment, temp); 11858 bool oneLined = transformAssignment(assignment, temp);
11908 for (auto val : assign->values.objects()) { 11859 for (auto val : assign->values.objects()) {
11909 if (auto value = singleValueFrom(val)) { 11860 if (auto value = singleValueFrom(val, true)) {
11910 if (auto spValue = value->item.as<SimpleValue_t>()) { 11861 if (auto spValue = value->item.as<SimpleValue_t>()) {
11911 if (auto funLit = spValue->value.as<FunLit_t>()) { 11862 if (auto funLit = spValue->value.as<FunLit_t>()) {
11912 if (!funLit->noRecursion) { 11863 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() {
393 in_block = space_break >> *(*set(" \t") >> line_break) >> advance_match >> ensure(Block, pop_indent); 393 in_block = space_break >> *(*set(" \t") >> line_break) >> advance_match >> ensure(Block, pop_indent);
394 394
395 LocalFlag = expr('*') | '^'; 395 LocalFlag = expr('*') | '^';
396 LocalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow | expected_expression_error)); 396 LocalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpList | expected_expression_error));
397 Local = key("local") >> space >> (LocalFlag | LocalValues | invalid_local_declaration_error); 397 Local = key("local") >> space >> (LocalFlag | LocalValues | invalid_local_declaration_error);
398 398
399 ConstAttrib = key("const"); 399 ConstAttrib = key("const");
@@ -478,7 +478,7 @@ YueParser::YueParser() {
478 Continue = key("continue"); 478 Continue = key("continue");
479 BreakLoop = (Break >> -(space >> Exp) | Continue) >> not_alpha_num; 479 BreakLoop = (Break >> -(space >> Exp) | Continue) >> not_alpha_num;
480 480
481 Return = key("return") >> -(space >> (TableBlock | ExpListLow)); 481 Return = key("return") >> -(space >> (TableBlock | ExpList));
482 482
483 must_exp = Exp | expected_expression_error; 483 must_exp = Exp | expected_expression_error;
484 484
@@ -674,7 +674,7 @@ YueParser::YueParser() {
674 674
675 Assign = '=' >> space >> Seperator >> ( 675 Assign = '=' >> space >> Seperator >> (
676 With | If | Switch | TableBlock | 676 With | If | Switch | TableBlock |
677 (SpreadListExp | Exp) >> *(space >> set(",;") >> space >> (SpreadListExp | Exp)) | 677 (SpreadListExp | Exp) >> *(space >> set(",") >> space >> (SpreadListExp | Exp)) |
678 expected_expression_error 678 expected_expression_error
679 ); 679 );
680 680
@@ -927,7 +927,7 @@ YueParser::YueParser() {
927 -(space >> key("using") >> prevent_indent >> space >> ensure(ExpList | expected_expression_error, pop_indent)) 927 -(space >> key("using") >> prevent_indent >> space >> ensure(ExpList | expected_expression_error, pop_indent))
928 ) >> -ClassBlock; 928 ) >> -ClassBlock;
929 929
930 GlobalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow | expected_expression_error)); 930 GlobalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpList | expected_expression_error));
931 GlobalOp = expr('*') | '^'; 931 GlobalOp = expr('*') | '^';
932 Global = key("global") >> space >> ( 932 Global = key("global") >> space >> (
933 -(ConstAttrib >> space) >> ClassDecl | 933 -(ConstAttrib >> space) >> ClassDecl |
@@ -1056,7 +1056,7 @@ YueParser::YueParser() {
1056 return st->fnArrowAvailable; 1056 return st->fnArrowAvailable;
1057 }) >> -(FnArgsDef >> 1057 }) >> -(FnArgsDef >>
1058 -(':' >> space >> 1058 -(':' >> space >>
1059 disable_fun_lit >> ensure(ExpListLow | DefaultValue, enable_fun_lit) 1059 disable_fun_lit >> ensure(ExpList | DefaultValue, enable_fun_lit)
1060 ) 1060 )
1061 ) >> space >> FnArrow >> -(space >> Body); 1061 ) >> space >> FnArrow >> -(space >> Body);
1062 1062
@@ -1087,7 +1087,6 @@ YueParser::YueParser() {
1087 *(+space_break >> check_indent_match >> space >> pipe_operator >> space >> must_unary_exp); 1087 *(+space_break >> check_indent_match >> space >> pipe_operator >> space >> must_unary_exp);
1088 1088
1089 ExpList = Seperator >> Exp >> *(space >> ',' >> space >> Exp); 1089 ExpList = Seperator >> Exp >> *(space >> ',' >> space >> Exp);
1090 ExpListLow = Seperator >> Exp >> *(space >> set(",;") >> space >> Exp);
1091 1090
1092 arg_line = check_indent_match >> space >> Exp >> *(space >> ',' >> space >> Exp); 1091 arg_line = check_indent_match >> space >> Exp >> *(space >> ',' >> space >> Exp);
1093 arg_block = arg_line >> *(space >> ',' >> space_break >> arg_line) >> pop_indent; 1092 arg_block = arg_line >> *(space >> ',' >> space_break >> arg_line) >> pop_indent;
@@ -1124,17 +1123,18 @@ YueParser::YueParser() {
1124 1123
1125 ChainAssign = Seperator >> Exp >> +(space >> '=' >> space >> Exp >> space >> and_('=')) >> space >> Assign; 1124 ChainAssign = Seperator >> Exp >> +(space >> '=' >> space >> Exp >> space >> and_('=')) >> space >> Assign;
1126 1125
1127 StatementAppendix = (IfLine | WhileLine | CompFor) >> space; 1126 StatementAppendix = IfLine | WhileLine | CompFor;
1128 Statement = 1127 Statement = (
1129 ( 1128 (
1130 Import | Export | Global | Macro | MacroInPlace | Label 1129 Import | Export | Global | Macro | MacroInPlace | Label
1131 ) >> space | ( 1130 ) | (
1132 Local | While | Repeat | For | Return | 1131 Local | While | Repeat | For | Return |
1133 BreakLoop | Goto | ShortTabAppending | 1132 BreakLoop | Goto | ShortTabAppending |
1134 LocalAttrib | Backcall | PipeBody | ExpListAssign | ChainAssign | 1133 LocalAttrib | Backcall | PipeBody | ExpListAssign | ChainAssign |
1135 StatementAppendix >> empty_block_error | 1134 StatementAppendix >> empty_block_error |
1136 and_(key("else") | key("elseif") | key("when")) >> dangling_clause_error 1135 and_(key("else") | key("elseif") | key("when")) >> dangling_clause_error
1137 ) >> space >> -StatementAppendix; 1136 ) >> space >> -StatementAppendix
1137 ) >> space;
1138 1138
1139 StatementSep = white >> (set("('\"") | "[[" | "[="); 1139 StatementSep = white >> (set("('\"") | "[[" | "[=");
1140 1140
@@ -1158,15 +1158,20 @@ YueParser::YueParser() {
1158 return false; 1158 return false;
1159 }); 1159 });
1160 1160
1161 is_lax = pl::user(true_(), [](const item_t& item) {
1162 State* st = reinterpret_cast<State*>(item.user_data);
1163 return st->lax;
1164 });
1165
1161 line = *(EmptyLine >> line_break) >> ( 1166 line = *(EmptyLine >> line_break) >> (
1162 check_indent_match >> space >> Statement | 1167 check_indent_match >> space >> Statement >> *(';' >> -(space >> Statement)) |
1163 YueComment | 1168 YueComment |
1164 advance_match >> ensure(space >> (indentation_error | Statement), pop_indent) 1169 advance_match >> ensure(space >> (indentation_error | Statement), pop_indent)
1165 ); 1170 );
1166 Block = Seperator >> (pl::user(true_(), [](const item_t& item) { 1171 Block = Seperator >> (
1167 State* st = reinterpret_cast<State*>(item.user_data); 1172 is_lax >> lax_line >> *(line_break >> lax_line) |
1168 return st->lax; 1173 line >> *(line_break >> line)
1169 }) >> lax_line >> *(line_break >> lax_line) | line >> *(line_break >> line)); 1174 );
1170 1175
1171 shebang = "#!" >> *(not_(stop) >> any_char); 1176 shebang = "#!" >> *(not_(stop) >> any_char);
1172 BlockEnd = Block >> plain_white >> stop; 1177 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:
319 NONE_AST_RULE(yue_multiline_comment); 319 NONE_AST_RULE(yue_multiline_comment);
320 NONE_AST_RULE(line); 320 NONE_AST_RULE(line);
321 NONE_AST_RULE(shebang); 321 NONE_AST_RULE(shebang);
322 NONE_AST_RULE(is_lax);
322 NONE_AST_RULE(lax_line); 323 NONE_AST_RULE(lax_line);
323 324
324 AST_RULE(Num); 325 AST_RULE(Num);
@@ -361,7 +362,6 @@ private:
361 AST_RULE(Backcall); 362 AST_RULE(Backcall);
362 AST_RULE(SubBackcall); 363 AST_RULE(SubBackcall);
363 AST_RULE(PipeBody); 364 AST_RULE(PipeBody);
364 AST_RULE(ExpListLow);
365 AST_RULE(ExpList); 365 AST_RULE(ExpList);
366 AST_RULE(Return); 366 AST_RULE(Return);
367 AST_RULE(With); 367 AST_RULE(With);