aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2025-05-28 18:20:16 +0800
committerLi Jin <dragon-fly@qq.com>2025-05-28 18:20:16 +0800
commit5604bbbb80bfcedb4a9085b90864e221f8104b33 (patch)
tree8828cddb1b0fe0ca734d6209507bdbda3133f48d
parent87267ca9e93606b70bdc0397349b176b8d142514 (diff)
downloadyuescript-5604bbbb80bfcedb4a9085b90864e221f8104b33.tar.gz
yuescript-5604bbbb80bfcedb4a9085b90864e221f8104b33.tar.bz2
yuescript-5604bbbb80bfcedb4a9085b90864e221f8104b33.zip
Added `try!` syntax.
-rwxr-xr-xdoc/docs/doc/README.md65
-rwxr-xr-xdoc/docs/zh/doc/README.md41
-rw-r--r--spec/inputs/try_catch.yue122
-rw-r--r--spec/outputs/5.1/try_catch.lua265
-rw-r--r--spec/outputs/assign.lua6
-rw-r--r--spec/outputs/codes_from_doc.lua100
-rw-r--r--spec/outputs/codes_from_doc_zh.lua100
-rw-r--r--spec/outputs/try_catch.lua266
-rw-r--r--spec/outputs/unicode/assign.lua6
-rw-r--r--spec/outputs/unicode/macro.lua46
-rw-r--r--spec/outputs/unicode/multiline_chain.lua6
-rw-r--r--spec/outputs/unicode/syntax.lua6
-rw-r--r--spec/outputs/unicode/vararg.lua28
-rw-r--r--spec/outputs/upvalue_func.lua48
-rw-r--r--spec/outputs/vararg.lua28
-rw-r--r--src/yuescript/yue_ast.cpp10
-rw-r--r--src/yuescript/yue_ast.h6
-rw-r--r--src/yuescript/yue_compiler.cpp155
-rw-r--r--src/yuescript/yue_compiler.h1
-rw-r--r--src/yuescript/yue_parser.cpp25
-rw-r--r--src/yuescript/yue_parser.h13
-rw-r--r--src/yuescript/yuescript.cpp15
22 files changed, 1169 insertions, 189 deletions
diff --git a/doc/docs/doc/README.md b/doc/docs/doc/README.md
index a970baa..1d9c8ad 100755
--- a/doc/docs/doc/README.md
+++ b/doc/docs/doc/README.md
@@ -1243,7 +1243,7 @@ If the destructuring statement is complicated, feel free to spread it out over a
1243</pre> 1243</pre>
1244</YueDisplay> 1244</YueDisplay>
1245 1245
1246It’s common to extract values from at table and assign them the local variables that have the same name as the key. In order to avoid repetition we can use the **:** prefix operator: 1246It's common to extract values from at table and assign them the local variables that have the same name as the key. In order to avoid repetition we can use the **:** prefix operator:
1247 1247
1248```moonscript 1248```moonscript
1249{:concat, :insert} = table 1249{:concat, :insert} = table
@@ -1516,6 +1516,47 @@ catch err
1516</pre> 1516</pre>
1517</YueDisplay> 1517</YueDisplay>
1518 1518
1519### Try!
1520
1521`try!` is a more concise error handling syntax that omit the boolean status from the `try` statement, and it will return the result from the try block when success, otherwise return nil instead of error object.
1522
1523```moonscript
1524a, b, c = try! func!
1525
1526-- with nil coalescing operator
1527a = (try! func!) ?? "default"
1528
1529-- as function argument
1530f try! func!
1531
1532-- with catch block
1533f try!
1534 print 123
1535 func!
1536catch e
1537 print e
1538 e
1539```
1540<YueDisplay>
1541<pre>
1542a, b, c = try! func!
1543
1544-- with nil coalescing operator
1545a = (try! func!) ?? "default"
1546
1547-- as function argument
1548f try! func!
1549
1550-- with catch block
1551f try!
1552 print 123
1553 func!
1554catch e
1555 print e
1556 e
1557</pre>
1558</YueDisplay>
1559
1519## Attributes 1560## Attributes
1520 1561
1521Syntax support for Lua 5.4 attributes. And you can still use both the `const` and `close` declaration and get constant check and scoped callback working when targeting Lua versions below 5.4. 1562Syntax support for Lua 5.4 attributes. And you can still use both the `const` and `close` declaration and get constant check and scoped callback working when targeting Lua versions below 5.4.
@@ -2417,7 +2458,7 @@ print func_b! -- prints table object
2417</pre> 2458</pre>
2418</YueDisplay> 2459</YueDisplay>
2419 2460
2420This is done to avoid the needless creation of tables for functions that dont need to return the results of the loop. 2461This is done to avoid the needless creation of tables for functions that don't need to return the results of the loop.
2421 2462
2422## Repeat Loop 2463## Repeat Loop
2423 2464
@@ -2746,7 +2787,7 @@ next_number = switch b
2746</pre> 2787</pre>
2747</YueDisplay> 2788</YueDisplay>
2748 2789
2749We can use the then keyword to write a switch’s when block on a single line. No extra keyword is needed to write the else block on a single line. 2790We can use the then keyword to write a switch's when block on a single line. No extra keyword is needed to write the else block on a single line.
2750 2791
2751```moonscript 2792```moonscript
2752msg = switch math.random(1, 5) 2793msg = switch math.random(1, 5)
@@ -2792,7 +2833,7 @@ else
2792</pre> 2833</pre>
2793</YueDisplay> 2834</YueDisplay>
2794 2835
2795It is worth noting the order of the case comparison expression. The case’s expression is on the left hand side. This can be useful if the case’s expression wants to overwrite how the comparison is done by defining an eq metamethod. 2836It is worth noting the order of the case comparison expression. The case's expression is on the left hand side. This can be useful if the case's expression wants to overwrite how the comparison is done by defining an eq metamethod.
2796 2837
2797### Table Matching 2838### Table Matching
2798 2839
@@ -3079,7 +3120,7 @@ class BackPack extends Inventory
3079 3120
3080Here we extend our Inventory class, and limit the amount of items it can carry. 3121Here we extend our Inventory class, and limit the amount of items it can carry.
3081 3122
3082In this example, we don’t define a constructor on the subclass, so the parent class' constructor is called when we make a new instance. If we did define a constructor then we can use the super method to call the parent constructor. 3123In this example, we don't define a constructor on the subclass, so the parent class' constructor is called when we make a new instance. If we did define a constructor then we can use the super method to call the parent constructor.
3083 3124
3084Whenever a class inherits from another, it sends a message to the parent class by calling the method __inherited on the parent class if it exists. The function receives two arguments, the class that is being inherited and the child class. 3125Whenever a class inherits from another, it sends a message to the parent class by calling the method __inherited on the parent class if it exists. The function receives two arguments, the class that is being inherited and the child class.
3085 3126
@@ -3166,13 +3207,13 @@ print BackPack.size -- prints 10
3166 3207
3167The class object is what we create when we use a class statement. The class object is stored in a variable of the same name of the class. 3208The class object is what we create when we use a class statement. The class object is stored in a variable of the same name of the class.
3168 3209
3169The class object can be called like a function in order to create new instances. That’s how we created instances of classes in the examples above. 3210The class object can be called like a function in order to create new instances. That's how we created instances of classes in the examples above.
3170 3211
3171A class is made up of two tables. The class table itself, and the base table. The base is used as the metatable for all the instances. All properties listed in the class declaration are placed in the base. 3212A class is made up of two tables. The class table itself, and the base table. The base is used as the metatable for all the instances. All properties listed in the class declaration are placed in the base.
3172 3213
3173The class object’s metatable reads properties from the base if they don’t exist in the class object. This means we can access functions and properties directly from the class. 3214The class object's metatable reads properties from the base if they don't exist in the class object. This means we can access functions and properties directly from the class.
3174 3215
3175It is important to note that assigning to the class object does not assign into the base, so it’s not a valid way to add new methods to instances. Instead the base must explicitly be changed. See the __base field below. 3216It is important to note that assigning to the class object does not assign into the base, so it's not a valid way to add new methods to instances. Instead the base must explicitly be changed. See the __base field below.
3176 3217
3177The class object has a couple special properties: 3218The class object has a couple special properties:
3178 3219
@@ -3245,7 +3286,7 @@ print Counter.count -- prints 2
3245</pre> 3286</pre>
3246</YueDisplay> 3287</YueDisplay>
3247 3288
3248The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua’s colon syntax. 3289The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua's colon syntax.
3249 3290
3250```moonscript 3291```moonscript
3251@@hello 1,2,3,4 3292@@hello 1,2,3,4
@@ -3260,7 +3301,7 @@ The calling semantics of @@ are similar to @. Calling a @@ name will pass the cl
3260 3301
3261In the body of a class declaration, we can have normal expressions in addition to key/value pairs. In this context, self is equal to the class object. 3302In the body of a class declaration, we can have normal expressions in addition to key/value pairs. In this context, self is equal to the class object.
3262 3303
3263Here is an alternative way to create a class variable compared to whats described above: 3304Here is an alternative way to create a class variable compared to what's described above:
3264 3305
3265```moonscript 3306```moonscript
3266class Things 3307class Things
@@ -3593,7 +3634,7 @@ print var -- nil here
3593</pre> 3634</pre>
3594</YueDisplay> 3635</YueDisplay>
3595 3636
3596YueScript’s **do** can also be used an expression . Allowing you to combine multiple lines into one. The result of the do expression is the last statement in its body. 3637YueScript's **do** can also be used an expression . Allowing you to combine multiple lines into one. The result of the do expression is the last statement in its body.
3597 3638
3598```moonscript 3639```moonscript
3599counter = do 3640counter = do
@@ -3719,7 +3760,7 @@ print i -- will print 0
3719</pre> 3760</pre>
3720</YueDisplay> 3761</YueDisplay>
3721 3762
3722In my_func, we've overwritten the value of i mistakenly. In this example it is quite obvious, but consider a large, or foreign code base where it isn’t clear what names have already been declared. 3763In my_func, we've overwritten the value of i mistakenly. In this example it is quite obvious, but consider a large, or foreign code base where it isn't clear what names have already been declared.
3723 3764
3724It would be helpful to say which variables from the enclosing scope we intend on change, in order to prevent us from changing others by accident. 3765It would be helpful to say which variables from the enclosing scope we intend on change, in order to prevent us from changing others by accident.
3725 3766
diff --git a/doc/docs/zh/doc/README.md b/doc/docs/zh/doc/README.md
index 2d4af18..0fa1fed 100755
--- a/doc/docs/zh/doc/README.md
+++ b/doc/docs/zh/doc/README.md
@@ -1514,6 +1514,47 @@ catch err
1514</pre> 1514</pre>
1515</YueDisplay> 1515</YueDisplay>
1516 1516
1517### 错误处理简化
1518
1519`try!` 是 `try` 的简化语法,它不再返回 `try` 语句的布尔状态,并在成功时直接返回 `try` 代码块的结果,失败时返回 `nil` 值而非错误对象。
1520
1521```moonscript
1522a, b, c = try! func!
1523
1524-- 与空值合并运算符一起使用
1525a = (try! func!) ?? "default"
1526
1527-- 作为函数参数
1528f try! func!
1529
1530-- 带 catch 块的 try!
1531f try!
1532 print 123
1533 func!
1534catch e
1535 print e
1536 e
1537```
1538<YueDisplay>
1539<pre>
1540a, b, c = try! func!
1541
1542-- 与空值合并运算符一起使用
1543a = (try! func!) ?? "default"
1544
1545-- 作为函数参数
1546f try! func!
1547
1548-- 带 catch 块的 try!
1549f try!
1550 print 123
1551 func!
1552catch e
1553 print e
1554 e
1555</pre>
1556</YueDisplay>
1557
1517## 属性 1558## 属性
1518 1559
1519月之脚本现在提供了Lua 5.4新增的叫做属性的语法支持。在月之脚本编译到的Lua目标版本低于5.4时,你仍然可以同时使用`const`和`close`的属性声明语法,并获得常量检查和作用域回调的功能。 1560月之脚本现在提供了Lua 5.4新增的叫做属性的语法支持。在月之脚本编译到的Lua目标版本低于5.4时,你仍然可以同时使用`const`和`close`的属性声明语法,并获得常量检查和作用域回调的功能。
diff --git a/spec/inputs/try_catch.yue b/spec/inputs/try_catch.yue
index 4e05bc6..f2583b7 100644
--- a/spec/inputs/try_catch.yue
+++ b/spec/inputs/try_catch.yue
@@ -62,6 +62,126 @@ f = ->
62 do 62 do
63 <- x 63 <- x
64 local tb, a, b, c 64 local tb, a, b, c
65 f = -> try tb.f a, b, c 65 f1 = -> try tb.f a, b, c
66
67 do
68 f1 = -> do
69 ok, ... = try func!
70 ...
71
72 do
73 local func
74 a, b, c = try! func!
75
76 do
77 a, b, c = try! func!
78
79 do
80 a = (try! func!) ?? "default"
81
82 do
83 f try! func!
84
85 do
86 f try!
87 print 123
88 func!
89 catch e
90 print e
91 e
66 92
67 nil 93 nil
94
95do
96 try
97 func 1, 2, 3
98 catch err
99 print err
100
101 try func 1, 2, 3
102 catch err
103 print err
104
105 try
106 print "trying"
107 func 1, 2, 3
108
109 do
110 success, result = try
111 func 1, 2, 3
112 catch err
113 print err
114
115 success, result = try func 1, 2, 3
116
117 tb = {}
118
119 try tb.func
120 try tb.func!
121 try tb.func()
122 try (tb.func!)
123 try (tb\func(1, 2, 3))
124
125 try tb.func 1
126 try tb.func(1)
127
128 if (try func 1
129 catch err
130 print err)
131 print "OK"
132
133 if try (func 1)
134 catch err
135 print err
136 print "OK"
137
138 do
139 if success, result := try func "abc", 123
140 print result
141
142 success, result = try func "abc", 123
143 catch err
144 print err
145
146 print result if success, result := try func "abc", 123
147 catch err
148 print err
149
150 do
151 try
152 func 1, 2, 3
153
154 try func 1, 2, 3
155
156 do
157 <- x
158 local tb, a, b, c
159 f1 = -> try tb.f a, b, c
160
161 do
162 f1 = -> do
163 ok, ... = try func!
164 ...
165
166 do
167 local func
168 a, b, c = try! func!
169
170 do
171 a, b, c = try! func!
172
173 do
174 a = (try! func!) ?? "default"
175
176 do
177 f try! func!
178
179 do
180 f try!
181 print 123
182 func!
183 catch e
184 print e
185 e
186
187nil
diff --git a/spec/outputs/5.1/try_catch.lua b/spec/outputs/5.1/try_catch.lua
index efd92c6..d2b58bc 100644
--- a/spec/outputs/5.1/try_catch.lua
+++ b/spec/outputs/5.1/try_catch.lua
@@ -22,6 +22,43 @@ end
22local _anon_func_7 = function(a, b, c, tb) 22local _anon_func_7 = function(a, b, c, tb)
23 return tb.f(a, b, c) 23 return tb.f(a, b, c)
24end 24end
25local _anon_func_8 = function(_arg_0, ...)
26 local ok = _arg_0
27 return ...
28end
29local _anon_func_10 = function(_arg_0, ...)
30 local _ok_0 = _arg_0
31 if _ok_0 then
32 return ...
33 end
34end
35local _anon_func_9 = function(func, pcall)
36 return _anon_func_10(pcall(func))
37end
38local _anon_func_12 = function(_arg_0, ...)
39 local _ok_0 = _arg_0
40 if _ok_0 then
41 return ...
42 end
43end
44local _anon_func_11 = function(func, pcall)
45 return _anon_func_12(pcall(func))
46end
47local _anon_func_14 = function(_arg_0, ...)
48 local _ok_0 = _arg_0
49 if _ok_0 then
50 return ...
51 end
52end
53local _anon_func_13 = function(func, print, xpcall)
54 return _anon_func_14(xpcall(function()
55 print(123)
56 return func()
57 end, function(e)
58 print(e)
59 return e
60 end))
61end
25local f 62local f
26f = function() 63f = function()
27 xpcall(function() 64 xpcall(function()
@@ -104,10 +141,236 @@ f = function()
104 do 141 do
105 x(function() 142 x(function()
106 local tb, a, b, c 143 local tb, a, b, c
107 f = function() 144 local f1
145 f1 = function()
108 return pcall(_anon_func_7, a, b, c, tb) 146 return pcall(_anon_func_7, a, b, c, tb)
109 end 147 end
110 end) 148 end)
111 end 149 end
150 do
151 local f1
152 f1 = function()
153 do
154 return _anon_func_8(pcall(function()
155 return func()
156 end))
157 end
158 end
159 end
160 do
161 local func
162 local a, b, c
163 local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(func)
164 if _ok_0 then
165 a, b, c = _ret_0, _ret_1, _ret_2
166 end
167 end
168 do
169 local a, b, c
170 local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function()
171 return func()
172 end)
173 if _ok_0 then
174 a, b, c = _ret_0, _ret_1, _ret_2
175 end
176 end
177 do
178 local a
179 local _exp_0 = (_anon_func_9(func, pcall))
180 if _exp_0 ~= nil then
181 a = _exp_0
182 else
183 a = "default"
184 end
185 end
186 do
187 f(_anon_func_11(func, pcall))
188 end
189 do
190 f(_anon_func_13(func, print, xpcall))
191 end
112 return nil 192 return nil
113end 193end
194local _anon_func_15 = function(a, b, c, tb)
195 return tb.f(a, b, c)
196end
197local _anon_func_16 = function(_arg_0, ...)
198 local ok = _arg_0
199 return ...
200end
201do
202 xpcall(function()
203 return func(1, 2, 3)
204 end, function(err)
205 return print(err)
206 end)
207 xpcall(function()
208 return func(1, 2, 3)
209 end, function(err)
210 return print(err)
211 end)
212 pcall(function()
213 print("trying")
214 return func(1, 2, 3)
215 end)
216 do
217 local success, result = xpcall(function()
218 return func(1, 2, 3)
219 end, function(err)
220 return print(err)
221 end)
222 success, result = pcall(function()
223 return func(1, 2, 3)
224 end)
225 end
226 local tb = { }
227 pcall(function()
228 return tb.func
229 end)
230 pcall(function()
231 return tb.func()
232 end)
233 pcall(function()
234 return tb.func()
235 end)
236 pcall(function()
237 return (tb.func())
238 end)
239 pcall(function()
240 return (tb:func(1, 2, 3))
241 end)
242 pcall(function()
243 return tb.func(1)
244 end)
245 pcall(function()
246 return tb.func(1)
247 end)
248 if (xpcall(function()
249 return func(1)
250 end, function(err)
251 return print(err)
252 end)) then
253 print("OK")
254 end
255 if xpcall(function()
256 return (func(1))
257 end, function(err)
258 return print(err)
259 end) then
260 print("OK")
261 end
262 do
263 do
264 local success, result = pcall(function()
265 return func("abc", 123)
266 end)
267 if success then
268 print(result)
269 end
270 end
271 local success, result = xpcall(function()
272 return func("abc", 123)
273 end, function(err)
274 return print(err)
275 end)
276 success, result = xpcall(function()
277 return func("abc", 123)
278 end, function(err)
279 return print(err)
280 end)
281 if success then
282 print(result)
283 end
284 end
285 do
286 pcall(function()
287 return func(1, 2, 3)
288 end)
289 pcall(function()
290 return func(1, 2, 3)
291 end)
292 end
293 do
294 x(function()
295 local tb, a, b, c
296 local f1
297 f1 = function()
298 return pcall(_anon_func_15, a, b, c, tb)
299 end
300 end)
301 end
302 do
303 local f1
304 f1 = function()
305 do
306 return _anon_func_16(pcall(function()
307 return func()
308 end))
309 end
310 end
311 end
312 do
313 local func
314 local a, b, c
315 local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(func)
316 if _ok_0 then
317 a, b, c = _ret_0, _ret_1, _ret_2
318 end
319 end
320 do
321 local a, b, c
322 local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function()
323 return func()
324 end)
325 if _ok_0 then
326 a, b, c = _ret_0, _ret_1, _ret_2
327 end
328 end
329 do
330 local a
331 local _exp_0 = ((function()
332 return (function(_arg_0, ...)
333 local _ok_0 = _arg_0
334 if _ok_0 then
335 return ...
336 end
337 end)(pcall(function()
338 return func()
339 end))
340 end)())
341 if _exp_0 ~= nil then
342 a = _exp_0
343 else
344 a = "default"
345 end
346 end
347 do
348 f((function()
349 return (function(_arg_0, ...)
350 local _ok_0 = _arg_0
351 if _ok_0 then
352 return ...
353 end
354 end)(pcall(function()
355 return func()
356 end))
357 end)())
358 end
359 do
360 f((function()
361 return (function(_arg_0, ...)
362 local _ok_0 = _arg_0
363 if _ok_0 then
364 return ...
365 end
366 end)(xpcall(function()
367 print(123)
368 return func()
369 end, function(e)
370 print(e)
371 return e
372 end))
373 end)())
374 end
375end
376return nil
diff --git a/spec/outputs/assign.lua b/spec/outputs/assign.lua
index 162c5a8..89c5f8a 100644
--- a/spec/outputs/assign.lua
+++ b/spec/outputs/assign.lua
@@ -43,10 +43,8 @@ do
43 end 43 end
44end 44end
45local _anon_func_0 = function(print) 45local _anon_func_0 = function(print)
46 do 46 print(123)
47 print(123) 47 return { }
48 return { }
49 end
50end 48end
51return _(function() 49return _(function()
52 setmetatable(a, _anon_func_0(print)) 50 setmetatable(a, _anon_func_0(print))
diff --git a/spec/outputs/codes_from_doc.lua b/spec/outputs/codes_from_doc.lua
index 55be7df..cce0516 100644
--- a/spec/outputs/codes_from_doc.lua
+++ b/spec/outputs/codes_from_doc.lua
@@ -688,6 +688,56 @@ end)
688if success then 688if success then
689 print(result) 689 print(result)
690end 690end
691local a, b, c
692do
693 local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function()
694 return func()
695 end)
696 if _ok_0 then
697 a, b, c = _ret_0, _ret_1, _ret_2
698 end
699end
700do
701 local _exp_0 = ((function()
702 return (function(_arg_0, ...)
703 local _ok_0 = _arg_0
704 if _ok_0 then
705 return ...
706 end
707 end)(pcall(function()
708 return func()
709 end))
710 end)())
711 if _exp_0 ~= nil then
712 a = _exp_0
713 else
714 a = "default"
715 end
716end
717f((function()
718 return (function(_arg_0, ...)
719 local _ok_0 = _arg_0
720 if _ok_0 then
721 return ...
722 end
723 end)(pcall(function()
724 return func()
725 end))
726end)())
727f((function()
728 return (function(_arg_0, ...)
729 local _ok_0 = _arg_0
730 if _ok_0 then
731 return ...
732 end
733 end)(xpcall(function()
734 print(123)
735 return func()
736 end, function(e)
737 print(e)
738 return e
739 end))
740end)())
691local a <const> = 123 741local a <const> = 123
692local _ <close> = setmetatable({ }, { 742local _ <close> = setmetatable({ }, {
693 __close = function() 743 __close = function()
@@ -2909,6 +2959,56 @@ end)
2909if success then 2959if success then
2910 print(result) 2960 print(result)
2911end 2961end
2962local a, b, c
2963do
2964 local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function()
2965 return func()
2966 end)
2967 if _ok_0 then
2968 a, b, c = _ret_0, _ret_1, _ret_2
2969 end
2970end
2971do
2972 local _exp_0 = ((function()
2973 return (function(_arg_0, ...)
2974 local _ok_0 = _arg_0
2975 if _ok_0 then
2976 return ...
2977 end
2978 end)(pcall(function()
2979 return func()
2980 end))
2981 end)())
2982 if _exp_0 ~= nil then
2983 a = _exp_0
2984 else
2985 a = "default"
2986 end
2987end
2988f((function()
2989 return (function(_arg_0, ...)
2990 local _ok_0 = _arg_0
2991 if _ok_0 then
2992 return ...
2993 end
2994 end)(pcall(function()
2995 return func()
2996 end))
2997end)())
2998f((function()
2999 return (function(_arg_0, ...)
3000 local _ok_0 = _arg_0
3001 if _ok_0 then
3002 return ...
3003 end
3004 end)(xpcall(function()
3005 print(123)
3006 return func()
3007 end, function(e)
3008 print(e)
3009 return e
3010 end))
3011end)())
2912local a <const> = 123 3012local a <const> = 123
2913local _ <close> = setmetatable({ }, { 3013local _ <close> = setmetatable({ }, {
2914 __close = function() 3014 __close = function()
diff --git a/spec/outputs/codes_from_doc_zh.lua b/spec/outputs/codes_from_doc_zh.lua
index 399f8c1..e267709 100644
--- a/spec/outputs/codes_from_doc_zh.lua
+++ b/spec/outputs/codes_from_doc_zh.lua
@@ -688,6 +688,56 @@ end)
688if success then 688if success then
689 print(result) 689 print(result)
690end 690end
691local a, b, c
692do
693 local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function()
694 return func()
695 end)
696 if _ok_0 then
697 a, b, c = _ret_0, _ret_1, _ret_2
698 end
699end
700do
701 local _exp_0 = ((function()
702 return (function(_arg_0, ...)
703 local _ok_0 = _arg_0
704 if _ok_0 then
705 return ...
706 end
707 end)(pcall(function()
708 return func()
709 end))
710 end)())
711 if _exp_0 ~= nil then
712 a = _exp_0
713 else
714 a = "default"
715 end
716end
717f((function()
718 return (function(_arg_0, ...)
719 local _ok_0 = _arg_0
720 if _ok_0 then
721 return ...
722 end
723 end)(pcall(function()
724 return func()
725 end))
726end)())
727f((function()
728 return (function(_arg_0, ...)
729 local _ok_0 = _arg_0
730 if _ok_0 then
731 return ...
732 end
733 end)(xpcall(function()
734 print(123)
735 return func()
736 end, function(e)
737 print(e)
738 return e
739 end))
740end)())
691local a <const> = 123 741local a <const> = 123
692local _ <close> = setmetatable({ }, { 742local _ <close> = setmetatable({ }, {
693 __close = function() 743 __close = function()
@@ -2903,6 +2953,56 @@ end)
2903if success then 2953if success then
2904 print(result) 2954 print(result)
2905end 2955end
2956local a, b, c
2957do
2958 local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function()
2959 return func()
2960 end)
2961 if _ok_0 then
2962 a, b, c = _ret_0, _ret_1, _ret_2
2963 end
2964end
2965do
2966 local _exp_0 = ((function()
2967 return (function(_arg_0, ...)
2968 local _ok_0 = _arg_0
2969 if _ok_0 then
2970 return ...
2971 end
2972 end)(pcall(function()
2973 return func()
2974 end))
2975 end)())
2976 if _exp_0 ~= nil then
2977 a = _exp_0
2978 else
2979 a = "default"
2980 end
2981end
2982f((function()
2983 return (function(_arg_0, ...)
2984 local _ok_0 = _arg_0
2985 if _ok_0 then
2986 return ...
2987 end
2988 end)(pcall(function()
2989 return func()
2990 end))
2991end)())
2992f((function()
2993 return (function(_arg_0, ...)
2994 local _ok_0 = _arg_0
2995 if _ok_0 then
2996 return ...
2997 end
2998 end)(xpcall(function()
2999 print(123)
3000 return func()
3001 end, function(e)
3002 print(e)
3003 return e
3004 end))
3005end)())
2906local a <const> = 123 3006local a <const> = 123
2907local _ <close> = setmetatable({ }, { 3007local _ <close> = setmetatable({ }, {
2908 __close = function() 3008 __close = function()
diff --git a/spec/outputs/try_catch.lua b/spec/outputs/try_catch.lua
index efd92c6..edb2341 100644
--- a/spec/outputs/try_catch.lua
+++ b/spec/outputs/try_catch.lua
@@ -22,6 +22,44 @@ end
22local _anon_func_7 = function(a, b, c, tb) 22local _anon_func_7 = function(a, b, c, tb)
23 return tb.f(a, b, c) 23 return tb.f(a, b, c)
24end 24end
25local _anon_func_8 = function(_arg_0, ...)
26 local ok = _arg_0
27 return ...
28end
29local _anon_func_10 = function(_arg_0, ...)
30 local _ok_0 = _arg_0
31 if _ok_0 then
32 return ...
33 end
34end
35local _anon_func_9 = function(func, pcall)
36 return _anon_func_10(pcall(func))
37end
38local _anon_func_12 = function(_arg_0, ...)
39 local _ok_0 = _arg_0
40 if _ok_0 then
41 return ...
42 end
43end
44local _anon_func_11 = function(func, pcall)
45 return _anon_func_12(pcall(func))
46end
47local _anon_func_14 = function(_arg_0, ...)
48 local _ok_0 = _arg_0
49 if _ok_0 then
50 return ...
51 end
52end
53local _anon_func_15 = function(func, print)
54 print(123)
55 return func()
56end
57local _anon_func_13 = function(func, print, xpcall)
58 return _anon_func_14(xpcall(_anon_func_15, function(e)
59 print(e)
60 return e
61 end, func, print))
62end
25local f 63local f
26f = function() 64f = function()
27 xpcall(function() 65 xpcall(function()
@@ -104,10 +142,236 @@ f = function()
104 do 142 do
105 x(function() 143 x(function()
106 local tb, a, b, c 144 local tb, a, b, c
107 f = function() 145 local f1
146 f1 = function()
108 return pcall(_anon_func_7, a, b, c, tb) 147 return pcall(_anon_func_7, a, b, c, tb)
109 end 148 end
110 end) 149 end)
111 end 150 end
151 do
152 local f1
153 f1 = function()
154 do
155 return _anon_func_8(pcall(function()
156 return func()
157 end))
158 end
159 end
160 end
161 do
162 local func
163 local a, b, c
164 local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(func)
165 if _ok_0 then
166 a, b, c = _ret_0, _ret_1, _ret_2
167 end
168 end
169 do
170 local a, b, c
171 local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function()
172 return func()
173 end)
174 if _ok_0 then
175 a, b, c = _ret_0, _ret_1, _ret_2
176 end
177 end
178 do
179 local a
180 local _exp_0 = (_anon_func_9(func, pcall))
181 if _exp_0 ~= nil then
182 a = _exp_0
183 else
184 a = "default"
185 end
186 end
187 do
188 f(_anon_func_11(func, pcall))
189 end
190 do
191 f(_anon_func_13(func, print, xpcall))
192 end
112 return nil 193 return nil
113end 194end
195local _anon_func_16 = function(a, b, c, tb)
196 return tb.f(a, b, c)
197end
198local _anon_func_17 = function(_arg_0, ...)
199 local ok = _arg_0
200 return ...
201end
202do
203 xpcall(function()
204 return func(1, 2, 3)
205 end, function(err)
206 return print(err)
207 end)
208 xpcall(function()
209 return func(1, 2, 3)
210 end, function(err)
211 return print(err)
212 end)
213 pcall(function()
214 print("trying")
215 return func(1, 2, 3)
216 end)
217 do
218 local success, result = xpcall(function()
219 return func(1, 2, 3)
220 end, function(err)
221 return print(err)
222 end)
223 success, result = pcall(function()
224 return func(1, 2, 3)
225 end)
226 end
227 local tb = { }
228 pcall(function()
229 return tb.func
230 end)
231 pcall(function()
232 return tb.func()
233 end)
234 pcall(function()
235 return tb.func()
236 end)
237 pcall(function()
238 return (tb.func())
239 end)
240 pcall(function()
241 return (tb:func(1, 2, 3))
242 end)
243 pcall(function()
244 return tb.func(1)
245 end)
246 pcall(function()
247 return tb.func(1)
248 end)
249 if (xpcall(function()
250 return func(1)
251 end, function(err)
252 return print(err)
253 end)) then
254 print("OK")
255 end
256 if xpcall(function()
257 return (func(1))
258 end, function(err)
259 return print(err)
260 end) then
261 print("OK")
262 end
263 do
264 do
265 local success, result = pcall(function()
266 return func("abc", 123)
267 end)
268 if success then
269 print(result)
270 end
271 end
272 local success, result = xpcall(function()
273 return func("abc", 123)
274 end, function(err)
275 return print(err)
276 end)
277 success, result = xpcall(function()
278 return func("abc", 123)
279 end, function(err)
280 return print(err)
281 end)
282 if success then
283 print(result)
284 end
285 end
286 do
287 pcall(function()
288 return func(1, 2, 3)
289 end)
290 pcall(function()
291 return func(1, 2, 3)
292 end)
293 end
294 do
295 x(function()
296 local tb, a, b, c
297 local f1
298 f1 = function()
299 return pcall(_anon_func_16, a, b, c, tb)
300 end
301 end)
302 end
303 do
304 local f1
305 f1 = function()
306 do
307 return _anon_func_17(pcall(function()
308 return func()
309 end))
310 end
311 end
312 end
313 do
314 local func
315 local a, b, c
316 local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(func)
317 if _ok_0 then
318 a, b, c = _ret_0, _ret_1, _ret_2
319 end
320 end
321 do
322 local a, b, c
323 local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function()
324 return func()
325 end)
326 if _ok_0 then
327 a, b, c = _ret_0, _ret_1, _ret_2
328 end
329 end
330 do
331 local a
332 local _exp_0 = ((function()
333 return (function(_arg_0, ...)
334 local _ok_0 = _arg_0
335 if _ok_0 then
336 return ...
337 end
338 end)(pcall(function()
339 return func()
340 end))
341 end)())
342 if _exp_0 ~= nil then
343 a = _exp_0
344 else
345 a = "default"
346 end
347 end
348 do
349 f((function()
350 return (function(_arg_0, ...)
351 local _ok_0 = _arg_0
352 if _ok_0 then
353 return ...
354 end
355 end)(pcall(function()
356 return func()
357 end))
358 end)())
359 end
360 do
361 f((function()
362 return (function(_arg_0, ...)
363 local _ok_0 = _arg_0
364 if _ok_0 then
365 return ...
366 end
367 end)(xpcall(function()
368 print(123)
369 return func()
370 end, function(e)
371 print(e)
372 return e
373 end))
374 end)())
375 end
376end
377return nil
diff --git a/spec/outputs/unicode/assign.lua b/spec/outputs/unicode/assign.lua
index d4ad56a..e00d016 100644
--- a/spec/outputs/unicode/assign.lua
+++ b/spec/outputs/unicode/assign.lua
@@ -43,10 +43,8 @@ do
43 end 43 end
44end 44end
45local _anon_func_0 = function(_u6253_u5370) 45local _anon_func_0 = function(_u6253_u5370)
46 do 46 _u6253_u5370(123)
47 _u6253_u5370(123) 47 return { }
48 return { }
49 end
50end 48end
51return __u65e0_u6548_u53d8_u91cf(function() 49return __u65e0_u6548_u53d8_u91cf(function()
52 setmetatable(a_u53d8_u91cf, _anon_func_0(_u6253_u5370)) 50 setmetatable(a_u53d8_u91cf, _anon_func_0(_u6253_u5370))
diff --git a/spec/outputs/unicode/macro.lua b/spec/outputs/unicode/macro.lua
index 3b9327a..b4e78cd 100644
--- a/spec/outputs/unicode/macro.lua
+++ b/spec/outputs/unicode/macro.lua
@@ -216,17 +216,15 @@ do
216end 216end
217local _ = require('下划线') 217local _ = require('下划线')
218local _anon_func_0 = function(_) 218local _anon_func_0 = function(_)
219 do 219 local _call_0 = (_({
220 local _call_0 = (_({ 220 1,
221 1, 221 2,
222 2, 222 3,
223 3, 223 4,
224 4, 224 -2,
225 -2, 225 3
226 3 226 }))
227 })) 227 return _call_0["链"](_call_0)
228 return _call_0["链"](_call_0)
229 end
230end 228end
231local _call_0 = ((function() 229local _call_0 = ((function()
232 local _call_0 = ((function() 230 local _call_0 = ((function()
@@ -241,17 +239,15 @@ local _call_0 = ((function()
241end)()) 239end)())
242local _u7ed3_u679ca = _call_0["取值"](_call_0) 240local _u7ed3_u679ca = _call_0["取值"](_call_0)
243local _anon_func_1 = function(_) 241local _anon_func_1 = function(_)
244 do 242 local _call_1 = (_({
245 local _call_1 = (_({ 243 1,
246 1, 244 2,
247 2, 245 3,
248 3, 246 4,
249 4, 247 -2,
250 -2, 248 3
251 3 249 }))
252 })) 250 return _call_1["链"](_call_1)
253 return _call_1["链"](_call_1)
254 end
255end 251end
256do 252do
257 local _call_1 = ((function() 253 local _call_1 = ((function()
@@ -270,10 +266,8 @@ do
270 end) 266 end)
271end 267end
272local _anon_func_2 = function(_u539f_u70b9) 268local _anon_func_2 = function(_u539f_u70b9)
273 do 269 local _call_1 = _u539f_u70b9["变换"]["根节点"]["游戏对象"]
274 local _call_1 = _u539f_u70b9["变换"]["根节点"]["游戏对象"] 270 return _call_1["父节点"](_call_1)
275 return _call_1["父节点"](_call_1)
276 end
277end 271end
278local _call_1 = ((function() 272local _call_1 = ((function()
279 local _call_1 = ((function() 273 local _call_1 = ((function()
diff --git a/spec/outputs/unicode/multiline_chain.lua b/spec/outputs/unicode/multiline_chain.lua
index c1da13f..61e7057 100644
--- a/spec/outputs/unicode/multiline_chain.lua
+++ b/spec/outputs/unicode/multiline_chain.lua
@@ -59,10 +59,8 @@ _u51fd_u6570 = function()
59 return _accum_0 59 return _accum_0
60end 60end
61local _anon_func_0 = function(_u53d8_u91cfa) 61local _anon_func_0 = function(_u53d8_u91cfa)
62 do 62 local _call_1 = _u53d8_u91cfa
63 local _call_1 = _u53d8_u91cfa 63 return (_call_1["变量b"](_call_1, 123))["变量c"]("abc")
64 return (_call_1["变量b"](_call_1, 123))["变量c"]("abc")
65 end
66end 64end
67local _u51fd_u65701 65local _u51fd_u65701
68_u51fd_u65701 = function() 66_u51fd_u65701 = function()
diff --git a/spec/outputs/unicode/syntax.lua b/spec/outputs/unicode/syntax.lua
index 1984f40..a13302b 100644
--- a/spec/outputs/unicode/syntax.lua
+++ b/spec/outputs/unicode/syntax.lua
@@ -286,10 +286,8 @@ _ = 5 - _u4ec0_u4e48(_u65e0_u804a)
286_u4ec0_u4e48(_u65e0_u804a - 5) 286_u4ec0_u4e48(_u65e0_u804a - 5)
287_u53d8_u91cfx = _u4f60_u597d - _u4e16_u754c - _u67d0_u7269 287_u53d8_u91cfx = _u4f60_u597d - _u4e16_u754c - _u67d0_u7269
288local _anon_func_0 = function(_u4ec0_u4e48) 288local _anon_func_0 = function(_u4ec0_u4e48)
289 do 289 local _call_8 = _u4ec0_u4e48
290 local _call_8 = _u4ec0_u4e48 290 return _call_8["酷"](_call_8, 100)
291 return _call_8["酷"](_call_8, 100)
292 end
293end 291end
294(function(_u67d0_u7269) 292(function(_u67d0_u7269)
295 if _u67d0_u7269 == nil then 293 if _u67d0_u7269 == nil then
diff --git a/spec/outputs/unicode/vararg.lua b/spec/outputs/unicode/vararg.lua
index b837006..fc894ff 100644
--- a/spec/outputs/unicode/vararg.lua
+++ b/spec/outputs/unicode/vararg.lua
@@ -125,14 +125,10 @@ local _anon_func_11 = function(_u9879_u76ee, ...)
125 return _tbl_0 125 return _tbl_0
126end 126end
127local _anon_func_12 = function(_u51fd_u6570) 127local _anon_func_12 = function(_u51fd_u6570)
128 do 128 return _u51fd_u6570()
129 return _u51fd_u6570()
130 end
131end 129end
132local _anon_func_13 = function(_u51fd_u6570, ...) 130local _anon_func_13 = function(_u51fd_u6570, ...)
133 do 131 return _u51fd_u6570(...)
134 return _u51fd_u6570(...)
135 end
136end 132end
137local _anon_func_14 = function(_u51fd_u6570) 133local _anon_func_14 = function(_u51fd_u6570)
138 local _accum_0 = { } 134 local _accum_0 = { }
@@ -195,15 +191,11 @@ local _anon_func_23 = function(_u51fd_u6570, ...)
195 return nil 191 return nil
196end 192end
197local _anon_func_24 = function(_u6253_u5370, select, ...) 193local _anon_func_24 = function(_u6253_u5370, select, ...)
198 do 194 _u6253_u5370(select("#", ...))
199 _u6253_u5370(select("#", ...)) 195 return _u6253_u5370(...)
200 return _u6253_u5370(...)
201 end
202end 196end
203local _anon_func_25 = function(_u6253_u5370, ...) 197local _anon_func_25 = function(_u6253_u5370, ...)
204 do 198 return _u6253_u5370(...)
205 return _u6253_u5370(...)
206 end
207end 199end
208local _anon_func_26 = function(_u53d8_u91cfx, _u8868, _u88682) 200local _anon_func_26 = function(_u53d8_u91cfx, _u8868, _u88682)
209 if 1 == _u53d8_u91cfx then 201 if 1 == _u53d8_u91cfx then
@@ -214,9 +206,7 @@ local _anon_func_26 = function(_u53d8_u91cfx, _u8868, _u88682)
214 end 206 end
215end 207end
216local _anon_func_27 = function(_u6253_u5370, ...) 208local _anon_func_27 = function(_u6253_u5370, ...)
217 do 209 return _u6253_u5370(...)
218 return _u6253_u5370(...)
219 end
220end 210end
221local _anon_func_28 = function(_u6761_u4ef6) 211local _anon_func_28 = function(_u6761_u4ef6)
222 if _u6761_u4ef6 then 212 if _u6761_u4ef6 then
@@ -224,10 +214,8 @@ local _anon_func_28 = function(_u6761_u4ef6)
224 end 214 end
225end 215end
226local _anon_func_29 = function(_u6253_u5370, _arg_0, ...) 216local _anon_func_29 = function(_u6253_u5370, _arg_0, ...)
227 do 217 local _u8868 = _arg_0
228 local _u8868 = _arg_0 218 return _u6253_u5370(...)
229 return _u6253_u5370(...)
230 end
231end 219end
232local _u8fde_u63a5 220local _u8fde_u63a5
233_u8fde_u63a5 = function(...) 221_u8fde_u63a5 = function(...)
diff --git a/spec/outputs/upvalue_func.lua b/spec/outputs/upvalue_func.lua
index 3181adf..3e088be 100644
--- a/spec/outputs/upvalue_func.lua
+++ b/spec/outputs/upvalue_func.lua
@@ -214,10 +214,8 @@ local _anon_func_1 = function(valueB)
214 end 214 end
215end 215end
216local _anon_func_2 = function(print, select, _arg_0, ...) 216local _anon_func_2 = function(print, select, _arg_0, ...)
217 do 217 local ok = _arg_0
218 local ok = _arg_0 218 return print(select(3, ...))
219 return print(select(3, ...))
220 end
221end 219end
222local _anon_func_3 = function(tb) 220local _anon_func_3 = function(tb)
223 if tb ~= nil then 221 if tb ~= nil then
@@ -242,11 +240,9 @@ local _anon_func_5 = function(getmetatable, tb)
242 return _obj_0[1 + 1](_obj_0, "abc") 240 return _obj_0[1 + 1](_obj_0, "abc")
243end 241end
244local _anon_func_6 = function(tb) 242local _anon_func_6 = function(tb)
245 do 243 local _call_0 = tb
246 local _call_0 = tb 244 local _call_1 = _call_0["end"](_call_0)
247 local _call_1 = _call_0["end"](_call_0) 245 return _call_1["🤣"](_call_1, 123)
248 return _call_1["🤣"](_call_1, 123)
249 end
250end 246end
251local _anon_func_7 = function(itemA, listA) 247local _anon_func_7 = function(itemA, listA)
252 for _index_0 = 1, #listA do 248 for _index_0 = 1, #listA do
@@ -354,17 +350,13 @@ local _anon_func_16 = function(pairs, tb, tostring)
354 return _tbl_0 350 return _tbl_0
355end 351end
356local _anon_func_17 = function(print) 352local _anon_func_17 = function(print)
357 do 353 print(123)
358 print(123) 354 return "abc"
359 return "abc"
360 end
361end 355end
362local _anon_func_18 = function(print, select, _arg_0, ...) 356local _anon_func_18 = function(print, select, _arg_0, ...)
363 do 357 local success = _arg_0
364 local success = _arg_0 358 if success then
365 if success then 359 return print(select('#', ...))
366 return print(select('#', ...))
367 end
368 end 360 end
369end 361end
370local _anon_func_19 = function(cond, i) 362local _anon_func_19 = function(cond, i)
@@ -459,11 +451,9 @@ local _anon_func_25 = function(itemA, listA)
459 return false 451 return false
460end 452end
461local _anon_func_24 = function(itemA, listA, tb) 453local _anon_func_24 = function(itemA, listA, tb)
462 do 454 local _call_0 = tb
463 local _call_0 = tb 455 local _call_1 = _call_0["end"](_call_0)
464 local _call_1 = _call_0["end"](_call_0) 456 return _call_1["🤣"](_call_1, 123 and (#listA > 0 and _anon_func_25(itemA, listA)))
465 return _call_1["🤣"](_call_1, 123 and (#listA > 0 and _anon_func_25(itemA, listA)))
466 end
467end 457end
468GameEngine:onEvent("SomeEvent", function() 458GameEngine:onEvent("SomeEvent", function()
469 return func(value + (_anon_func_21(cond)) + (_anon_func_22(valueB)) > _anon_func_23(tb) + _anon_func_24(itemA, listA, tb)) 459 return func(value + (_anon_func_21(cond)) + (_anon_func_22(valueB)) > _anon_func_23(tb) + _anon_func_24(itemA, listA, tb))
@@ -503,13 +493,11 @@ local _anon_func_27 = function(char)
503 return nil 493 return nil
504end 494end
505local _anon_func_28 = function(os, _arg_0, ...) 495local _anon_func_28 = function(os, _arg_0, ...)
506 do 496 local ok = _arg_0
507 local ok = _arg_0 497 if ok then
508 if ok then 498 return ...
509 return ... 499 else
510 else 500 return os.exit(1)
511 return os.exit(1)
512 end
513 end 501 end
514end 502end
515local _anon_func_29 = function(debug_env_after, debug_env_before, env, func) 503local _anon_func_29 = function(debug_env_after, debug_env_before, env, func)
diff --git a/spec/outputs/vararg.lua b/spec/outputs/vararg.lua
index dabba44..254aa6a 100644
--- a/spec/outputs/vararg.lua
+++ b/spec/outputs/vararg.lua
@@ -125,14 +125,10 @@ local _anon_func_11 = function(items, ...)
125 return _tbl_0 125 return _tbl_0
126end 126end
127local _anon_func_12 = function(func) 127local _anon_func_12 = function(func)
128 do 128 return func()
129 return func()
130 end
131end 129end
132local _anon_func_13 = function(func, ...) 130local _anon_func_13 = function(func, ...)
133 do 131 return func(...)
134 return func(...)
135 end
136end 132end
137local _anon_func_14 = function(func) 133local _anon_func_14 = function(func)
138 local _accum_0 = { } 134 local _accum_0 = { }
@@ -195,15 +191,11 @@ local _anon_func_23 = function(func, ...)
195 return nil 191 return nil
196end 192end
197local _anon_func_24 = function(print, select, ...) 193local _anon_func_24 = function(print, select, ...)
198 do 194 print(select("#", ...))
199 print(select("#", ...)) 195 return print(...)
200 return print(...)
201 end
202end 196end
203local _anon_func_25 = function(print, ...) 197local _anon_func_25 = function(print, ...)
204 do 198 return print(...)
205 return print(...)
206 end
207end 199end
208local _anon_func_26 = function(tb, tb2, x) 200local _anon_func_26 = function(tb, tb2, x)
209 if 1 == x then 201 if 1 == x then
@@ -214,9 +206,7 @@ local _anon_func_26 = function(tb, tb2, x)
214 end 206 end
215end 207end
216local _anon_func_27 = function(print, ...) 208local _anon_func_27 = function(print, ...)
217 do 209 return print(...)
218 return print(...)
219 end
220end 210end
221local _anon_func_28 = function(cond) 211local _anon_func_28 = function(cond)
222 if cond then 212 if cond then
@@ -224,10 +214,8 @@ local _anon_func_28 = function(cond)
224 end 214 end
225end 215end
226local _anon_func_29 = function(print, _arg_0, ...) 216local _anon_func_29 = function(print, _arg_0, ...)
227 do 217 local tb = _arg_0
228 local tb = _arg_0 218 return print(...)
229 return print(...)
230 end
231end 219end
232local join 220local join
233join = function(...) 221join = function(...)
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp
index 9d68161..be10859 100644
--- a/src/yuescript/yue_ast.cpp
+++ b/src/yuescript/yue_ast.cpp
@@ -609,13 +609,19 @@ std::string CatchBlock_t::to_string(void* ud) const {
609 info->popScope(); 609 info->popScope();
610 return line + '\n' + blockStr; 610 return line + '\n' + blockStr;
611} 611}
612std::string Omit_t::to_string(void*) const {
613 return "!"s;
614}
612std::string Try_t::to_string(void* ud) const { 615std::string Try_t::to_string(void* ud) const {
613 auto info = reinterpret_cast<YueFormat*>(ud); 616 auto info = reinterpret_cast<YueFormat*>(ud);
614 str_list temp; 617 str_list temp;
618 temp.emplace_back("try"s);
619 if (omit) {
620 temp.back() += '!';
621 }
615 if (func.is<Exp_t>()) { 622 if (func.is<Exp_t>()) {
616 temp.emplace_back("try "s + func->to_string(ud)); 623 temp.back() += (" "s + func->to_string(ud));
617 } else { 624 } else {
618 temp.emplace_back("try"s);
619 info->pushScope(); 625 info->pushScope();
620 temp.emplace_back(func->to_string(ud)); 626 temp.emplace_back(func->to_string(ud));
621 if (temp.back().empty()) { 627 if (temp.back().empty()) {
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index d3e6368..393f374 100644
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -383,10 +383,14 @@ AST_NODE(CatchBlock)
383 AST_MEMBER(CatchBlock, &err, &block) 383 AST_MEMBER(CatchBlock, &err, &block)
384AST_END(CatchBlock) 384AST_END(CatchBlock)
385 385
386AST_LEAF(Omit)
387AST_END(Omit)
388
386AST_NODE(Try) 389AST_NODE(Try)
390 ast_ptr<false, Omit_t> omit;
387 ast_sel<true, Block_t, Exp_t> func; 391 ast_sel<true, Block_t, Exp_t> func;
388 ast_ptr<false, CatchBlock_t> catchBlock; 392 ast_ptr<false, CatchBlock_t> catchBlock;
389 AST_MEMBER(Try, &func, &catchBlock) 393 AST_MEMBER(Try, &omit, &func, &catchBlock)
390AST_END(Try) 394AST_END(Try)
391 395
392AST_NODE(Comprehension) 396AST_NODE(Comprehension)
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 2312025..35745f2 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.28.5"sv; 81const std::string_view version = "0.28.6"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 {
@@ -165,12 +165,12 @@ public:
165 double compileTime = 0.0; 165 double compileTime = 0.0;
166 if (config.profiling) { 166 if (config.profiling) {
167 auto start = std::chrono::high_resolution_clock::now(); 167 auto start = std::chrono::high_resolution_clock::now();
168 _info = _parser.parse<File_t>(codes); 168 _info = _parser.parse<File_t>(codes, config.lax);
169 auto stop = std::chrono::high_resolution_clock::now(); 169 auto stop = std::chrono::high_resolution_clock::now();
170 std::chrono::duration<double> diff = stop - start; 170 std::chrono::duration<double> diff = stop - start;
171 parseTime = diff.count(); 171 parseTime = diff.count();
172 } else { 172 } else {
173 _info = _parser.parse<File_t>(codes); 173 _info = _parser.parse<File_t>(codes, config.lax);
174 } 174 }
175 std::unique_ptr<GlobalVars> globals; 175 std::unique_ptr<GlobalVars> globals;
176 std::unique_ptr<Options> options; 176 std::unique_ptr<Options> options;
@@ -1258,7 +1258,7 @@ private:
1258 1258
1259 template <class T> 1259 template <class T>
1260 ast_ptr<false, T> toAst(std::string_view codes, ast_node* parent) { 1260 ast_ptr<false, T> toAst(std::string_view codes, ast_node* parent) {
1261 auto res = _parser.parse<T>(std::string(codes)); 1261 auto res = _parser.parse<T>(std::string(codes), false);
1262 if (res.error) { 1262 if (res.error) {
1263 throw CompileError(res.error.value().msg, parent); 1263 throw CompileError(res.error.value().msg, parent);
1264 } 1264 }
@@ -2330,6 +2330,17 @@ private:
2330 out.back().insert(0, preDefine); 2330 out.back().insert(0, preDefine);
2331 return false; 2331 return false;
2332 } 2332 }
2333 case id<Try_t>(): {
2334 auto tryNode = static_cast<Try_t*>(value);
2335 if (tryNode->omit) {
2336 auto assignList = assignment->expList.get();
2337 std::string preDefine = getPreDefineLine(assignment);
2338 transformTry(tryNode, out, ExpUsage::Assignment, assignList);
2339 out.back().insert(0, preDefine);
2340 return false;
2341 }
2342 break;
2343 }
2333 case id<Switch_t>(): { 2344 case id<Switch_t>(): {
2334 auto switchNode = static_cast<Switch_t*>(value); 2345 auto switchNode = static_cast<Switch_t*>(value);
2335 auto assignList = assignment->expList.get(); 2346 auto assignList = assignment->expList.get();
@@ -4272,12 +4283,22 @@ private:
4272 4283
4273 std::optional<std::pair<std::string, str_list>> upValueFuncFromExp(Exp_t* exp, str_list* ensureArgListInTheEnd, bool blockRewrite) { 4284 std::optional<std::pair<std::string, str_list>> upValueFuncFromExp(Exp_t* exp, str_list* ensureArgListInTheEnd, bool blockRewrite) {
4274 if (checkUpValueFuncAvailable(exp)) { 4285 if (checkUpValueFuncAvailable(exp)) {
4286 auto block = exp->new_ptr<Block_t>();
4287 if (auto sVal = simpleSingleValueFrom(exp)) {
4288 if (auto doNode = sVal->value.as<Do_t>()) {
4289 if (auto blk = doNode->body->content.as<Block_t>()) {
4290 block->statements.dup(blk->statements);
4291 } else {
4292 block->statements.push_back(doNode->body->content.to<Statement_t>());
4293 }
4294 return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false, blockRewrite);
4295 }
4296 }
4275 auto returnNode = exp->new_ptr<Return_t>(); 4297 auto returnNode = exp->new_ptr<Return_t>();
4276 returnNode->explicitReturn = false; 4298 returnNode->explicitReturn = false;
4277 auto returnList = exp->new_ptr<ExpListLow_t>(); 4299 auto returnList = exp->new_ptr<ExpListLow_t>();
4278 returnList->exprs.push_back(exp); 4300 returnList->exprs.push_back(exp);
4279 returnNode->valueList.set(returnList); 4301 returnNode->valueList.set(returnList);
4280 auto block = exp->new_ptr<Block_t>();
4281 auto stmt = exp->new_ptr<Statement_t>(); 4302 auto stmt = exp->new_ptr<Statement_t>();
4282 stmt->content.set(returnNode); 4303 stmt->content.set(returnNode);
4283 block->statements.push_back(stmt); 4304 block->statements.push_back(stmt);
@@ -4799,11 +4820,7 @@ private:
4799 auto newBody = x->new_ptr<Body_t>(); 4820 auto newBody = x->new_ptr<Body_t>();
4800 newBody->content.set(followingBlock); 4821 newBody->content.set(followingBlock);
4801 { 4822 {
4802 auto doNode = x->new_ptr<Do_t>(); 4823 if (auto result = upValueFuncFromBlock(followingBlock.get(), &argNames, false, true)) {
4803 doNode->body.set(newBody);
4804 auto simpleValue = x->new_ptr<SimpleValue_t>();
4805 simpleValue->value.set(doNode);
4806 if (auto result = upValueFuncFromExp(newExp(simpleValue, x), &argNames, true)) {
4807 auto [funcName, args] = std::move(*result); 4824 auto [funcName, args] = std::move(*result);
4808 str_list finalArgs; 4825 str_list finalArgs;
4809 for (const auto& arg : args) { 4826 for (const auto& arg : args) {
@@ -4811,9 +4828,13 @@ private:
4811 finalArgs.push_back(arg); 4828 finalArgs.push_back(arg);
4812 } 4829 }
4813 } 4830 }
4814 newBlock->statements.push_back(toAst<Statement_t>(funcName + ' ' + join(finalArgs, ","sv), x)); 4831 newBlock->statements.push_back(toAst<Statement_t>(funcName + ' ' + (finalArgs.empty() ? "nil"s : join(finalArgs, ","sv)), x));
4815 auto sVal = singleValueFrom(static_cast<Statement_t*>(newBlock->statements.back())->content.to<ExpListAssign_t>()->expList); 4832 auto sVal = singleValueFrom(static_cast<Statement_t*>(newBlock->statements.back())->content.to<ExpListAssign_t>()->expList);
4816 ast_to<InvokeArgs_t>(sVal->item.to<ChainValue_t>()->items.back())->args.dup(newInvoke->args); 4833 auto invokArgs = ast_to<InvokeArgs_t>(sVal->item.to<ChainValue_t>()->items.back());
4834 if (finalArgs.empty()) {
4835 invokArgs->args.clear();
4836 }
4837 invokArgs->args.dup(newInvoke->args);
4817 transformBlock(newBlock, out, usage, assignList, isRoot); 4838 transformBlock(newBlock, out, usage, assignList, isRoot);
4818 return; 4839 return;
4819 } 4840 }
@@ -5093,36 +5114,45 @@ private:
5093 if (!nodes.empty()) { 5114 if (!nodes.empty()) {
5094 str_list temp; 5115 str_list temp;
5095 for (auto node : nodes) { 5116 for (auto node : nodes) {
5096 currentScope().lastStatement = (node == nodes.back()) && currentScope().mode == GlobalMode::None; 5117 auto transformNode = [&]() {
5097 transformStatement(static_cast<Statement_t*>(node), temp); 5118 currentScope().lastStatement = (node == nodes.back()) && currentScope().mode == GlobalMode::None;
5098 if (isRoot && !_rootDefs.empty()) { 5119 transformStatement(static_cast<Statement_t*>(node), temp);
5099 auto last = std::move(temp.back()); 5120 if (isRoot && !_rootDefs.empty()) {
5100 temp.pop_back(); 5121 auto last = std::move(temp.back());
5101 temp.insert(temp.end(), _rootDefs.begin(), _rootDefs.end()); 5122 temp.pop_back();
5102 _rootDefs.clear(); 5123 temp.insert(temp.end(), _rootDefs.begin(), _rootDefs.end());
5103 temp.push_back(std::move(last)); 5124 _rootDefs.clear();
5104 } 5125 temp.push_back(std::move(last));
5105 if (!temp.empty() && _parser.startWith<StatementSep_t>(temp.back())) { 5126 }
5106 auto rit = ++temp.rbegin(); 5127 if (!temp.empty() && _parser.startWith<StatementSep_t>(temp.back())) {
5107 if (rit != temp.rend() && !rit->empty()) { 5128 auto rit = ++temp.rbegin();
5108 auto index = std::string::npos; 5129 if (rit != temp.rend() && !rit->empty()) {
5109 if (_config.reserveLineNumber) { 5130 auto index = std::string::npos;
5110 index = rit->rfind(" -- "sv); 5131 if (_config.reserveLineNumber) {
5111 } else { 5132 index = rit->rfind(" -- "sv);
5112 index = rit->find_last_not_of('\n'); 5133 } else {
5113 if (index != std::string::npos) index++; 5134 index = rit->find_last_not_of('\n');
5114 } 5135 if (index != std::string::npos) index++;
5115 if (index != std::string::npos) {
5116 auto ending = rit->substr(0, index);
5117 auto ind = ending.find_last_of(" \t\n"sv);
5118 if (ind != std::string::npos) {
5119 ending = ending.substr(ind + 1);
5120 } 5136 }
5121 if (LuaKeywords.find(ending) == LuaKeywords.end()) { 5137 if (index != std::string::npos) {
5122 rit->insert(index, ";"sv); 5138 auto ending = rit->substr(0, index);
5139 auto ind = ending.find_last_of(" \t\n"sv);
5140 if (ind != std::string::npos) {
5141 ending = ending.substr(ind + 1);
5142 }
5143 if (LuaKeywords.find(ending) == LuaKeywords.end()) {
5144 rit->insert(index, ";"sv);
5145 }
5123 } 5146 }
5124 } 5147 }
5125 } 5148 }
5149 };
5150 if (_config.lax) {
5151 try {
5152 transformNode();
5153 } catch (const CompileError&) { }
5154 } else {
5155 transformNode();
5126 } 5156 }
5127 } 5157 }
5128 out.push_back(join(temp)); 5158 out.push_back(join(temp));
@@ -6193,7 +6223,7 @@ private:
6193 case id<ColonChainItem_t>(): 6223 case id<ColonChainItem_t>():
6194 case id<Exp_t>(): 6224 case id<Exp_t>():
6195 if (_withVars.empty()) { 6225 if (_withVars.empty()) {
6196 throw CompileError("short dot/colon and indexing syntax must be called within a with block"sv, x); 6226 throw CompileError("short dot/colon/indexing syntax must be called within a with block"sv, x);
6197 } else { 6227 } else {
6198 temp.push_back(_withVars.top()); 6228 temp.push_back(_withVars.top());
6199 } 6229 }
@@ -6714,14 +6744,14 @@ private:
6714 } else { 6744 } else {
6715 if (!codes.empty()) { 6745 if (!codes.empty()) {
6716 if (isBlock) { 6746 if (isBlock) {
6717 info = _parser.parse<BlockEnd_t>(codes); 6747 info = _parser.parse<BlockEnd_t>(codes, false);
6718 if (info.error) { 6748 if (info.error) {
6719 throw CompileError("failed to expand macro as block: "s + info.error.value().msg, x); 6749 throw CompileError("failed to expand macro as block: "s + info.error.value().msg, x);
6720 } 6750 }
6721 } else { 6751 } else {
6722 info = _parser.parse<Exp_t>(codes); 6752 info = _parser.parse<Exp_t>(codes, false);
6723 if (!info.node && allowBlockMacroReturn) { 6753 if (!info.node && allowBlockMacroReturn) {
6724 info = _parser.parse<BlockEnd_t>(codes); 6754 info = _parser.parse<BlockEnd_t>(codes, false);
6725 if (info.error) { 6755 if (info.error) {
6726 throw CompileError("failed to expand macro as expr or block: "s + info.error.value().msg, x); 6756 throw CompileError("failed to expand macro as expr or block: "s + info.error.value().msg, x);
6727 } 6757 }
@@ -10023,8 +10053,47 @@ private:
10023 out.push_back(join(temp)); 10053 out.push_back(join(temp));
10024 } 10054 }
10025 10055
10026 void transformTry(Try_t* tryNode, str_list& out, ExpUsage usage) { 10056 void transformTry(Try_t* tryNode, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
10027 auto x = tryNode; 10057 auto x = tryNode;
10058 if (tryNode->omit && usage == ExpUsage::Assignment) {
10059 str_list rets;
10060 pushScope();
10061 auto okVar = getUnusedName("_ok_"sv);
10062 for (size_t i = 0; i < assignList->exprs.size(); i++) {
10063 auto retVar = getUnusedName("_ret_"sv);
10064 rets.emplace_back(retVar);
10065 addToScope(retVar);
10066 }
10067 popScope();
10068 auto varList = join(rets, ","sv);
10069 auto ifNode = toAst<If_t>("if "s + okVar + ',' + varList + ":=try nil then "s + varList, x);
10070 auto exp = ast_to<IfCond_t>(ifNode->nodes.front())->assignment->assign->values.front();
10071 auto sVal = simpleSingleValueFrom(exp);
10072 auto newTry = sVal->value.to<Try_t>();
10073 newTry->func.set(tryNode->func);
10074 newTry->catchBlock.set(tryNode->catchBlock);
10075 auto assignment = x->new_ptr<ExpListAssign_t>();
10076 assignment->expList.set(assignList);
10077 auto assign = x->new_ptr<Assign_t>();
10078 assign->values.push_back(ifNode);
10079 assignment->action.set(assign);
10080 transformAssignment(assignment, out);
10081 return;
10082 }
10083 if (tryNode->omit && usage != ExpUsage::Common) {
10084 auto okVar = getUnusedName("_ok_"sv);
10085 auto code = "do\n\t"s + okVar + ", ... = try nil\n\t... if "s + okVar;
10086 auto doNode = toAst<Do_t>(code, x);
10087 auto block = doNode->body->content.to<Block_t>();
10088 auto asmt = static_cast<Statement_t*>(block->statements.front())->content.to<ExpListAssign_t>();
10089 auto assign = asmt->action.to<Assign_t>();
10090 auto sVal = simpleSingleValueFrom(assign->values.back());
10091 auto newTry = sVal->value.to<Try_t>();
10092 newTry->func.set(tryNode->func);
10093 newTry->catchBlock.set(tryNode->catchBlock);
10094 transformDo(doNode, out, usage);
10095 return;
10096 }
10028 ast_ptr<true, Exp_t> errHandler; 10097 ast_ptr<true, Exp_t> errHandler;
10029 if (tryNode->catchBlock) { 10098 if (tryNode->catchBlock) {
10030 auto catchBlock = tryNode->catchBlock.get(); 10099 auto catchBlock = tryNode->catchBlock.get();
diff --git a/src/yuescript/yue_compiler.h b/src/yuescript/yue_compiler.h
index d352636..aff5978 100644
--- a/src/yuescript/yue_compiler.h
+++ b/src/yuescript/yue_compiler.h
@@ -31,6 +31,7 @@ struct YueConfig {
31 bool reserveLineNumber = true; 31 bool reserveLineNumber = true;
32 bool useSpaceOverTab = false; 32 bool useSpaceOverTab = false;
33 bool reserveComment = false; 33 bool reserveComment = false;
34 bool lax = false;
34 // internal options 35 // internal options
35 bool exporting = false; 36 bool exporting = false;
36 bool profiling = false; 37 bool profiling = false;
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index e5bdc26..2b0aea8 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -332,7 +332,7 @@ YueParser::YueParser() {
332 Exp; 332 Exp;
333 import_tab_list = import_tab_item >> *(space >> ',' >> space >> import_tab_item); 333 import_tab_list = import_tab_item >> *(space >> ',' >> space >> import_tab_item);
334 import_tab_line = ( 334 import_tab_line = (
335 push_indent_match >> (space >> import_tab_list >> pop_indent | pop_indent) 335 push_indent_match >> ensure(space >> import_tab_list, pop_indent)
336 ) | space; 336 ) | space;
337 import_tab_lines = space_break >> import_tab_line >> *(-(space >> ',') >> space_break >> import_tab_line) >> -(space >> ','); 337 import_tab_lines = space_break >> import_tab_line >> *(-(space >> ',') >> space_break >> import_tab_line) >> -(space >> ',');
338 import_tab_key_value = key_value | ':' >> MacroName | MacroNamePair | ImportAllMacro; 338 import_tab_key_value = key_value | ':' >> MacroName | MacroNamePair | ImportAllMacro;
@@ -501,8 +501,9 @@ YueParser::YueParser() {
501 return true; 501 return true;
502 }); 502 });
503 503
504 Omit = expr('!');
504 CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> Variable >> space >> in_block; 505 CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> Variable >> space >> in_block;
505 Try = key("try") >> space >> (in_block | Exp) >> -CatchBlock; 506 Try = key("try") >> -Omit >> space >> (in_block | Exp) >> -CatchBlock;
506 507
507 list_value = 508 list_value =
508 and_( 509 and_(
@@ -667,7 +668,7 @@ YueParser::YueParser() {
667 fn_args_value_list = Exp >> *(space >> ',' >> space >> Exp); 668 fn_args_value_list = Exp >> *(space >> ',' >> space >> Exp);
668 669
669 fn_args_lit_line = ( 670 fn_args_lit_line = (
670 push_indent_match >> (space >> fn_args_value_list >> pop_indent | pop_indent) 671 push_indent_match >> ensure(space >> fn_args_value_list, pop_indent)
671 ) | ( 672 ) | (
672 space 673 space
673 ); 674 );
@@ -875,7 +876,7 @@ YueParser::YueParser() {
875 fn_arg_def_list = FnArgDef >> *(space >> ',' >> space >> FnArgDef); 876 fn_arg_def_list = FnArgDef >> *(space >> ',' >> space >> FnArgDef);
876 877
877 fn_arg_def_lit_line = ( 878 fn_arg_def_lit_line = (
878 push_indent_match >> (space >> fn_arg_def_list >> pop_indent | pop_indent) 879 push_indent_match >> ensure(space >> fn_arg_def_list, pop_indent)
879 ) | ( 880 ) | (
880 space 881 space
881 ); 882 );
@@ -1030,11 +1031,16 @@ YueParser::YueParser() {
1030 empty_line_break | 1031 empty_line_break |
1031 advance_match >> ensure(space >> (indentation_error | Statement), pop_indent) 1032 advance_match >> ensure(space >> (indentation_error | Statement), pop_indent)
1032 ); 1033 );
1033 Block = Seperator >> line >> *(+line_break >> line); 1034 Block = Seperator >> (pl::user(true_(), [](const item_t& item) {
1035 State* st = reinterpret_cast<State*>(item.user_data);
1036 return st->lax;
1037 }) >> lax_line >> *(+line_break >> lax_line) | line >> *(+line_break >> line));
1034 1038
1035 shebang = "#!" >> *(not_(stop) >> any_char); 1039 shebang = "#!" >> *(not_(stop) >> any_char);
1036 BlockEnd = Block >> white >> stop; 1040 BlockEnd = Block >> white >> stop;
1037 File = -shebang >> -Block >> white >> stop; 1041 File = -shebang >> -Block >> white >> stop;
1042
1043 lax_line = advance_match >> ensure(*(not_(stop) >> any()), pop_indent) | line >> and_(stop) | check_indent_match >> *(not_(stop) >> any());
1038} 1044}
1039// clang-format on 1045// clang-format on
1040 1046
@@ -1064,7 +1070,7 @@ bool YueParser::startWith(std::string_view codes, rule& r) {
1064 return true; 1070 return true;
1065} 1071}
1066 1072
1067ParseInfo YueParser::parse(std::string_view codes, rule& r) { 1073ParseInfo YueParser::parse(std::string_view codes, rule& r, bool lax) {
1068 ParseInfo res; 1074 ParseInfo res;
1069 if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) { 1075 if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) {
1070 codes = codes.substr(3); 1076 codes = codes.substr(3);
@@ -1082,6 +1088,7 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) {
1082 error_list errors; 1088 error_list errors;
1083 try { 1089 try {
1084 State state; 1090 State state;
1091 state.lax = lax;
1085 res.node.set(::yue::parse(*(res.codes), r, errors, &state)); 1092 res.node.set(::yue::parse(*(res.codes), r, errors, &state));
1086 if (state.exportCount > 0) { 1093 if (state.exportCount > 0) {
1087 int index = 0; 1094 int index = 0;
@@ -1119,10 +1126,10 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) {
1119 return res; 1126 return res;
1120} 1127}
1121 1128
1122ParseInfo YueParser::parse(std::string_view astName, std::string_view codes) { 1129ParseInfo YueParser::parse(std::string_view astName, std::string_view codes, bool lax) {
1123 auto it = _rules.find(astName); 1130 auto it = _rules.find(astName);
1124 if (it != _rules.end()) { 1131 if (it != _rules.end()) {
1125 return parse(codes, *it->second); 1132 return parse(codes, *it->second, lax);
1126 } 1133 }
1127 return {}; 1134 return {};
1128} 1135}
@@ -1131,7 +1138,7 @@ bool YueParser::match(std::string_view astName, std::string_view codes) {
1131 auto it = _rules.find(astName); 1138 auto it = _rules.find(astName);
1132 if (it != _rules.end()) { 1139 if (it != _rules.end()) {
1133 auto rEnd = rule(*it->second >> eof()); 1140 auto rEnd = rule(*it->second >> eof());
1134 return parse(codes, rEnd).node; 1141 return parse(codes, rEnd, false).node;
1135 } 1142 }
1136 return false; 1143 return false;
1137} 1144}
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h
index 773bdbe..99f3d45 100644
--- a/src/yuescript/yue_parser.h
+++ b/src/yuescript/yue_parser.h
@@ -74,16 +74,16 @@ extern std::unordered_set<std::string> Keywords;
74class YueParser { 74class YueParser {
75public: 75public:
76 template <class AST> 76 template <class AST>
77 ParseInfo parse(std::string_view codes) { 77 ParseInfo parse(std::string_view codes, bool lax) {
78 return parse(codes, getRule<AST>()); 78 return parse(codes, getRule<AST>(), lax);
79 } 79 }
80 80
81 ParseInfo parse(std::string_view astName, std::string_view codes); 81 ParseInfo parse(std::string_view astName, std::string_view codes, bool lax);
82 82
83 template <class AST> 83 template <class AST>
84 bool match(std::string_view codes) { 84 bool match(std::string_view codes) {
85 auto rEnd = rule(getRule<AST>() >> eof()); 85 auto rEnd = rule(getRule<AST>() >> eof());
86 return parse(codes, rEnd).node; 86 return parse(codes, rEnd, false).node;
87 } 87 }
88 88
89 bool match(std::string_view astName, std::string_view codes); 89 bool match(std::string_view astName, std::string_view codes);
@@ -102,13 +102,14 @@ public:
102 102
103protected: 103protected:
104 YueParser(); 104 YueParser();
105 ParseInfo parse(std::string_view codes, rule& r); 105 ParseInfo parse(std::string_view codes, rule& r, bool lax);
106 bool startWith(std::string_view codes, rule& r); 106 bool startWith(std::string_view codes, rule& r);
107 107
108 struct State { 108 struct State {
109 State() { 109 State() {
110 indents.push(0); 110 indents.push(0);
111 } 111 }
112 bool lax = false;
112 bool exportDefault = false; 113 bool exportDefault = false;
113 bool exportMacro = false; 114 bool exportMacro = false;
114 bool exportMetatable = false; 115 bool exportMetatable = false;
@@ -287,6 +288,7 @@ private:
287 NONE_AST_RULE(yue_line_comment); 288 NONE_AST_RULE(yue_line_comment);
288 NONE_AST_RULE(line); 289 NONE_AST_RULE(line);
289 NONE_AST_RULE(shebang); 290 NONE_AST_RULE(shebang);
291 NONE_AST_RULE(lax_line);
290 292
291 AST_RULE(Num); 293 AST_RULE(Num);
292 AST_RULE(Name); 294 AST_RULE(Name);
@@ -345,6 +347,7 @@ private:
345 AST_RULE(ForEach); 347 AST_RULE(ForEach);
346 AST_RULE(Do); 348 AST_RULE(Do);
347 AST_RULE(CatchBlock); 349 AST_RULE(CatchBlock);
350 AST_RULE(Omit);
348 AST_RULE(Try); 351 AST_RULE(Try);
349 AST_RULE(Comprehension); 352 AST_RULE(Comprehension);
350 AST_RULE(CompValue); 353 AST_RULE(CompValue);
diff --git a/src/yuescript/yuescript.cpp b/src/yuescript/yuescript.cpp
index 7e8e8b7..aa19b70 100644
--- a/src/yuescript/yuescript.cpp
+++ b/src/yuescript/yuescript.cpp
@@ -93,6 +93,12 @@ static void get_config(lua_State* L, yue::YueConfig& config) {
93 config.useSpaceOverTab = lua_toboolean(L, -1) != 0; 93 config.useSpaceOverTab = lua_toboolean(L, -1) != 0;
94 } 94 }
95 lua_pop(L, 1); 95 lua_pop(L, 1);
96 lua_pushliteral(L, "lax");
97 lua_gettable(L, -2);
98 if (lua_isboolean(L, -1) != 0) {
99 config.lax = lua_toboolean(L, -1) != 0;
100 }
101 lua_pop(L, 1);
96 lua_pushliteral(L, "options"); 102 lua_pushliteral(L, "options");
97 lua_gettable(L, -2); 103 lua_gettable(L, -2);
98 if (lua_istable(L, -1) != 0) { 104 if (lua_istable(L, -1) != 0) {
@@ -180,7 +186,7 @@ static int yueformat(lua_State* L) {
180 tabSize = static_cast<int>(luaL_checkinteger(L, 2)); 186 tabSize = static_cast<int>(luaL_checkinteger(L, 2));
181 } 187 }
182 std::string_view codes(input, len); 188 std::string_view codes(input, len);
183 auto info = yue::YueParser::shared().parse<yue::File_t>(codes); 189 auto info = yue::YueParser::shared().parse<yue::File_t>(codes, false);
184 if (info.error) { 190 if (info.error) {
185 const auto& error = info.error.value(); 191 const auto& error = info.error.value();
186 if (!info.codes) { 192 if (!info.codes) {
@@ -282,8 +288,13 @@ static int yuetoast(lua_State* L) {
282 ruleName = {name, nameSize}; 288 ruleName = {name, nameSize};
283 } 289 }
284 } 290 }
291 bool lax = false;
292 if (!lua_isnoneornil(L, 4)) {
293 luaL_checktype(L, 4, LUA_TBOOLEAN);
294 lax = lua_toboolean(L, 4) != 0;
295 }
285 auto& yueParser = yue::YueParser::shared(); 296 auto& yueParser = yue::YueParser::shared();
286 auto info = ruleName.empty() ? yueParser.parse<yue::File_t>({input, size}) : yueParser.parse(ruleName, {input, size}); 297 auto info = ruleName.empty() ? yueParser.parse<yue::File_t>({input, size}, lax) : yueParser.parse(ruleName, {input, size}, lax);
287 if (!info.error) { 298 if (!info.error) {
288 lua_createtable(L, 0, 0); 299 lua_createtable(L, 0, 0);
289 int tableIndex = lua_gettop(L); 300 int tableIndex = lua_gettop(L);