diff options
-rw-r--r-- | spec/inputs/test/format_spec.yue | 126 | ||||
-rw-r--r-- | spec/outputs/test/format_spec.lua | 133 | ||||
-rw-r--r-- | src/yue_wasm.cpp | 2 | ||||
-rw-r--r-- | src/yuescript/yue_ast.cpp | 260 | ||||
-rw-r--r-- | src/yuescript/yue_compiler.cpp | 2 | ||||
-rw-r--r-- | src/yuescript/yue_parser.cpp | 42 | ||||
-rw-r--r-- | src/yuescript/yue_parser.h | 3 | ||||
-rw-r--r-- | src/yuescript/yuescript.cpp | 43 |
8 files changed, 535 insertions, 76 deletions
diff --git a/spec/inputs/test/format_spec.yue b/spec/inputs/test/format_spec.yue new file mode 100644 index 0000000..5076445 --- /dev/null +++ b/spec/inputs/test/format_spec.yue | |||
@@ -0,0 +1,126 @@ | |||
1 | files = [ | ||
2 | "spec/inputs/macro_export.yue" | ||
3 | "spec/inputs/attrib.yue" | ||
4 | "spec/inputs/macro.yue" | ||
5 | "spec/inputs/using.yue" | ||
6 | "spec/inputs/whitespace.yue" | ||
7 | "spec/inputs/nil_coalescing.yue" | ||
8 | "spec/inputs/stub.yue" | ||
9 | "spec/inputs/pipe.yue" | ||
10 | "spec/inputs/teal_lang.yue" | ||
11 | "spec/inputs/string.yue" | ||
12 | "spec/inputs/local.yue" | ||
13 | "spec/inputs/tables.yue" | ||
14 | "spec/inputs/operators.yue" | ||
15 | "spec/inputs/lists.yue" | ||
16 | "spec/inputs/compile_doc.yue" | ||
17 | "spec/inputs/switch.yue" | ||
18 | "spec/inputs/multiline_chain.yue" | ||
19 | "spec/inputs/existential.yue" | ||
20 | "spec/inputs/export_default.yue" | ||
21 | "spec/inputs/assign.yue" | ||
22 | "spec/inputs/literals.yue" | ||
23 | "spec/inputs/luarocks_upload.yue" | ||
24 | "spec/inputs/ambiguous.yue" | ||
25 | "spec/inputs/bubbling.yue" | ||
26 | "spec/inputs/try_catch.yue" | ||
27 | "spec/inputs/funcs.yue" | ||
28 | "spec/inputs/do.yue" | ||
29 | "spec/inputs/with.yue" | ||
30 | "spec/inputs/export.yue" | ||
31 | "spec/inputs/macro_todo.yue" | ||
32 | "spec/inputs/backcall.yue" | ||
33 | "spec/inputs/cond.yue" | ||
34 | "spec/inputs/in_expression.yue" | ||
35 | "spec/inputs/comprehension.yue" | ||
36 | "spec/inputs/macro_teal.yue" | ||
37 | "spec/inputs/import.yue" | ||
38 | "spec/inputs/unless_else.yue" | ||
39 | "spec/inputs/destructure.yue" | ||
40 | "spec/inputs/return.yue" | ||
41 | "spec/inputs/loops.yue" | ||
42 | "spec/inputs/class.yue" | ||
43 | "spec/inputs/vararg.yue" | ||
44 | "spec/inputs/goto.yue" | ||
45 | "spec/inputs/metatable.yue" | ||
46 | "spec/inputs/syntax.yue" | ||
47 | "spec/inputs/global.yue" | ||
48 | "spec/inputs/plus.yue" | ||
49 | "spec/inputs/test/class_spec.yue" | ||
50 | "spec/inputs/test/table_spreading_spec.yue" | ||
51 | "spec/inputs/test/loops_spec.yue" | ||
52 | "spec/inputs/test/format_spec.yue" | ||
53 | "spec/inputs/unicode/macro_export.yue" | ||
54 | "spec/inputs/unicode/attrib.yue" | ||
55 | "spec/inputs/unicode/macro.yue" | ||
56 | "spec/inputs/unicode/using.yue" | ||
57 | "spec/inputs/unicode/whitespace.yue" | ||
58 | "spec/inputs/unicode/nil_coalescing.yue" | ||
59 | "spec/inputs/unicode/stub.yue" | ||
60 | "spec/inputs/unicode/pipe.yue" | ||
61 | "spec/inputs/unicode/string.yue" | ||
62 | "spec/inputs/unicode/local.yue" | ||
63 | "spec/inputs/unicode/tables.yue" | ||
64 | "spec/inputs/unicode/operators.yue" | ||
65 | "spec/inputs/unicode/lists.yue" | ||
66 | "spec/inputs/unicode/switch.yue" | ||
67 | "spec/inputs/unicode/multiline_chain.yue" | ||
68 | "spec/inputs/unicode/existential.yue" | ||
69 | "spec/inputs/unicode/export_default.yue" | ||
70 | "spec/inputs/unicode/assign.yue" | ||
71 | "spec/inputs/unicode/literals.yue" | ||
72 | "spec/inputs/unicode/ambiguous.yue" | ||
73 | "spec/inputs/unicode/bubbling.yue" | ||
74 | "spec/inputs/unicode/try_catch.yue" | ||
75 | "spec/inputs/unicode/funcs.yue" | ||
76 | "spec/inputs/unicode/do.yue" | ||
77 | "spec/inputs/unicode/with.yue" | ||
78 | "spec/inputs/unicode/export.yue" | ||
79 | "spec/inputs/unicode/macro_todo.yue" | ||
80 | "spec/inputs/unicode/backcall.yue" | ||
81 | "spec/inputs/unicode/cond.yue" | ||
82 | "spec/inputs/unicode/in_expression.yue" | ||
83 | "spec/inputs/unicode/comprehension.yue" | ||
84 | "spec/inputs/unicode/import.yue" | ||
85 | "spec/inputs/unicode/unless_else.yue" | ||
86 | "spec/inputs/unicode/destructure.yue" | ||
87 | "spec/inputs/unicode/return.yue" | ||
88 | "spec/inputs/unicode/loops.yue" | ||
89 | "spec/inputs/unicode/class.yue" | ||
90 | "spec/inputs/unicode/vararg.yue" | ||
91 | "spec/inputs/unicode/goto.yue" | ||
92 | "spec/inputs/unicode/metatable.yue" | ||
93 | "spec/inputs/unicode/syntax.yue" | ||
94 | "spec/inputs/unicode/global.yue" | ||
95 | "spec/inputs/unicode/plus.yue" | ||
96 | ] | ||
97 | |||
98 | import "yue" | ||
99 | |||
100 | rewriteLineCol = (item)-> | ||
101 | item[2] = 0 | ||
102 | item[3] = 0 | ||
103 | for i = 4, #item | ||
104 | switch type item[i] when "table" | ||
105 | if item[i][1] == "comment" | ||
106 | table.remove item, i | ||
107 | rewriteLineCol item | ||
108 | return | ||
109 | rewriteLineCol item[i] | ||
110 | |||
111 | <- describe "format" | ||
112 | for file in *files | ||
113 | <- it file | ||
114 | f = io.open file | ||
115 | code = f\read "a*" | ||
116 | f\close! | ||
117 | |||
118 | original_ast = yue.to_ast code | ||
119 | assert.is_not_nil original_ast | ||
120 | rewriteLineCol original_ast | ||
121 | formated = yue.format code | ||
122 | ast = yue.to_ast formated | ||
123 | assert.is_not_nil ast | ||
124 | rewriteLineCol ast | ||
125 | assert.same original_ast, ast | ||
126 | |||
diff --git a/spec/outputs/test/format_spec.lua b/spec/outputs/test/format_spec.lua new file mode 100644 index 0000000..b12fb04 --- /dev/null +++ b/spec/outputs/test/format_spec.lua | |||
@@ -0,0 +1,133 @@ | |||
1 | local files = { | ||
2 | "spec/inputs/macro_export.yue", | ||
3 | "spec/inputs/attrib.yue", | ||
4 | "spec/inputs/macro.yue", | ||
5 | "spec/inputs/using.yue", | ||
6 | "spec/inputs/whitespace.yue", | ||
7 | "spec/inputs/nil_coalescing.yue", | ||
8 | "spec/inputs/stub.yue", | ||
9 | "spec/inputs/pipe.yue", | ||
10 | "spec/inputs/teal_lang.yue", | ||
11 | "spec/inputs/string.yue", | ||
12 | "spec/inputs/local.yue", | ||
13 | "spec/inputs/tables.yue", | ||
14 | "spec/inputs/operators.yue", | ||
15 | "spec/inputs/lists.yue", | ||
16 | "spec/inputs/compile_doc.yue", | ||
17 | "spec/inputs/switch.yue", | ||
18 | "spec/inputs/multiline_chain.yue", | ||
19 | "spec/inputs/existential.yue", | ||
20 | "spec/inputs/export_default.yue", | ||
21 | "spec/inputs/assign.yue", | ||
22 | "spec/inputs/literals.yue", | ||
23 | "spec/inputs/luarocks_upload.yue", | ||
24 | "spec/inputs/ambiguous.yue", | ||
25 | "spec/inputs/bubbling.yue", | ||
26 | "spec/inputs/try_catch.yue", | ||
27 | "spec/inputs/funcs.yue", | ||
28 | "spec/inputs/do.yue", | ||
29 | "spec/inputs/with.yue", | ||
30 | "spec/inputs/export.yue", | ||
31 | "spec/inputs/macro_todo.yue", | ||
32 | "spec/inputs/backcall.yue", | ||
33 | "spec/inputs/cond.yue", | ||
34 | "spec/inputs/in_expression.yue", | ||
35 | "spec/inputs/comprehension.yue", | ||
36 | "spec/inputs/macro_teal.yue", | ||
37 | "spec/inputs/import.yue", | ||
38 | "spec/inputs/unless_else.yue", | ||
39 | "spec/inputs/destructure.yue", | ||
40 | "spec/inputs/return.yue", | ||
41 | "spec/inputs/loops.yue", | ||
42 | "spec/inputs/class.yue", | ||
43 | "spec/inputs/vararg.yue", | ||
44 | "spec/inputs/goto.yue", | ||
45 | "spec/inputs/metatable.yue", | ||
46 | "spec/inputs/syntax.yue", | ||
47 | "spec/inputs/global.yue", | ||
48 | "spec/inputs/plus.yue", | ||
49 | "spec/inputs/test/class_spec.yue", | ||
50 | "spec/inputs/test/table_spreading_spec.yue", | ||
51 | "spec/inputs/test/loops_spec.yue", | ||
52 | "spec/inputs/test/format_spec.yue", | ||
53 | "spec/inputs/unicode/macro_export.yue", | ||
54 | "spec/inputs/unicode/attrib.yue", | ||
55 | "spec/inputs/unicode/macro.yue", | ||
56 | "spec/inputs/unicode/using.yue", | ||
57 | "spec/inputs/unicode/whitespace.yue", | ||
58 | "spec/inputs/unicode/nil_coalescing.yue", | ||
59 | "spec/inputs/unicode/stub.yue", | ||
60 | "spec/inputs/unicode/pipe.yue", | ||
61 | "spec/inputs/unicode/string.yue", | ||
62 | "spec/inputs/unicode/local.yue", | ||
63 | "spec/inputs/unicode/tables.yue", | ||
64 | "spec/inputs/unicode/operators.yue", | ||
65 | "spec/inputs/unicode/lists.yue", | ||
66 | "spec/inputs/unicode/switch.yue", | ||
67 | "spec/inputs/unicode/multiline_chain.yue", | ||
68 | "spec/inputs/unicode/existential.yue", | ||
69 | "spec/inputs/unicode/export_default.yue", | ||
70 | "spec/inputs/unicode/assign.yue", | ||
71 | "spec/inputs/unicode/literals.yue", | ||
72 | "spec/inputs/unicode/ambiguous.yue", | ||
73 | "spec/inputs/unicode/bubbling.yue", | ||
74 | "spec/inputs/unicode/try_catch.yue", | ||
75 | "spec/inputs/unicode/funcs.yue", | ||
76 | "spec/inputs/unicode/do.yue", | ||
77 | "spec/inputs/unicode/with.yue", | ||
78 | "spec/inputs/unicode/export.yue", | ||
79 | "spec/inputs/unicode/macro_todo.yue", | ||
80 | "spec/inputs/unicode/backcall.yue", | ||
81 | "spec/inputs/unicode/cond.yue", | ||
82 | "spec/inputs/unicode/in_expression.yue", | ||
83 | "spec/inputs/unicode/comprehension.yue", | ||
84 | "spec/inputs/unicode/import.yue", | ||
85 | "spec/inputs/unicode/unless_else.yue", | ||
86 | "spec/inputs/unicode/destructure.yue", | ||
87 | "spec/inputs/unicode/return.yue", | ||
88 | "spec/inputs/unicode/loops.yue", | ||
89 | "spec/inputs/unicode/class.yue", | ||
90 | "spec/inputs/unicode/vararg.yue", | ||
91 | "spec/inputs/unicode/goto.yue", | ||
92 | "spec/inputs/unicode/metatable.yue", | ||
93 | "spec/inputs/unicode/syntax.yue", | ||
94 | "spec/inputs/unicode/global.yue", | ||
95 | "spec/inputs/unicode/plus.yue" | ||
96 | } | ||
97 | local yue = require("yue") | ||
98 | local rewriteLineCol | ||
99 | rewriteLineCol = function(item) | ||
100 | item[2] = 0 | ||
101 | item[3] = 0 | ||
102 | for i = 4, #item do | ||
103 | do | ||
104 | local _exp_0 = type(item[i]) | ||
105 | if "table" == _exp_0 then | ||
106 | if item[i][1] == "comment" then | ||
107 | table.remove(item, i) | ||
108 | rewriteLineCol(item) | ||
109 | return | ||
110 | end | ||
111 | rewriteLineCol(item[i]) | ||
112 | end | ||
113 | end | ||
114 | end | ||
115 | end | ||
116 | return describe("format", function() | ||
117 | for _index_0 = 1, #files do | ||
118 | local file = files[_index_0] | ||
119 | it(file, function() | ||
120 | local f = io.open(file) | ||
121 | local code = f:read("a*") | ||
122 | f:close() | ||
123 | local original_ast = yue.to_ast(code) | ||
124 | assert.is_not_nil(original_ast) | ||
125 | rewriteLineCol(original_ast) | ||
126 | local formated = yue.format(code) | ||
127 | local ast = yue.to_ast(formated) | ||
128 | assert.is_not_nil(ast) | ||
129 | rewriteLineCol(ast) | ||
130 | return assert.same(original_ast, ast) | ||
131 | end) | ||
132 | end | ||
133 | end) | ||
diff --git a/src/yue_wasm.cpp b/src/yue_wasm.cpp index 4a054e6..daa5757 100644 --- a/src/yue_wasm.cpp +++ b/src/yue_wasm.cpp | |||
@@ -138,7 +138,7 @@ std::string exec(const std::string& codes) { | |||
138 | }; | 138 | }; |
139 | 139 | ||
140 | execStr(R"yuescript( | 140 | execStr(R"yuescript( |
141 | _G.__output = {} | 141 | _G.__output = [] |
142 | _G.print = (...)-> | 142 | _G.print = (...)-> |
143 | _G.__output[] = table.concat [tostring select i, ... for i = 1, select "#", ...], " " | 143 | _G.__output[] = table.concat [tostring select i, ... for i = 1, select "#", ...], " " |
144 | _G.__output[] = "\n" | 144 | _G.__output[] = "\n" |
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp index 6126f71..6b2c96d 100644 --- a/src/yuescript/yue_ast.cpp +++ b/src/yuescript/yue_ast.cpp | |||
@@ -230,7 +230,7 @@ std::string LocalValues_t::to_string(void* ud) const { | |||
230 | temp.emplace_back(nameList->to_string(ud)); | 230 | temp.emplace_back(nameList->to_string(ud)); |
231 | if (valueList) { | 231 | if (valueList) { |
232 | if (valueList.is<TableBlock_t>()) { | 232 | if (valueList.is<TableBlock_t>()) { |
233 | temp.emplace_back("="s + valueList->to_string(ud)); | 233 | temp.emplace_back("=\n"s + valueList->to_string(ud)); |
234 | } else { | 234 | } else { |
235 | temp.emplace_back("="s); | 235 | temp.emplace_back("="s); |
236 | temp.emplace_back(valueList->to_string(ud)); | 236 | temp.emplace_back(valueList->to_string(ud)); |
@@ -312,7 +312,10 @@ std::string ShortTabAppending_t::to_string(void* ud) const { | |||
312 | std::string Backcall_t::to_string(void* ud) const { | 312 | std::string Backcall_t::to_string(void* ud) const { |
313 | str_list temp; | 313 | str_list temp; |
314 | if (argsDef) { | 314 | if (argsDef) { |
315 | temp.emplace_back(argsDef->to_string(ud)); | 315 | auto def = argsDef->to_string(ud); |
316 | if (!def.empty()) { | ||
317 | temp.emplace_back(def); | ||
318 | } | ||
316 | } | 319 | } |
317 | temp.emplace_back(arrow->to_string(ud)); | 320 | temp.emplace_back(arrow->to_string(ud)); |
318 | temp.emplace_back(value->to_string(ud)); | 321 | temp.emplace_back(value->to_string(ud)); |
@@ -343,7 +346,7 @@ std::string ExpList_t::to_string(void* ud) const { | |||
343 | std::string Return_t::to_string(void* ud) const { | 346 | std::string Return_t::to_string(void* ud) const { |
344 | str_list temp{"return"s}; | 347 | str_list temp{"return"s}; |
345 | if (valueList) { | 348 | if (valueList) { |
346 | temp.emplace_back(valueList.is<TableBlock_t>() ? ""s : " "s); | 349 | temp.emplace_back(valueList.is<TableBlock_t>() ? "\n"s : " "s); |
347 | temp.emplace_back(valueList->to_string(ud)); | 350 | temp.emplace_back(valueList->to_string(ud)); |
348 | } | 351 | } |
349 | return join(temp); | 352 | return join(temp); |
@@ -365,6 +368,9 @@ std::string With_t::to_string(void* ud) const { | |||
365 | } | 368 | } |
366 | info->pushScope(); | 369 | info->pushScope(); |
367 | auto code = body->to_string(ud); | 370 | auto code = body->to_string(ud); |
371 | if (code.empty()) { | ||
372 | code = info->ind() + "--"s; | ||
373 | } | ||
368 | info->popScope(); | 374 | info->popScope(); |
369 | return line + '\n' + code; | 375 | return line + '\n' + code; |
370 | } | 376 | } |
@@ -383,6 +389,9 @@ std::string SwitchCase_t::to_string(void* ud) const { | |||
383 | } else { | 389 | } else { |
384 | info->pushScope(); | 390 | info->pushScope(); |
385 | auto block = body->to_string(ud); | 391 | auto block = body->to_string(ud); |
392 | if (block.empty()) { | ||
393 | block = info->ind() + "--"s; | ||
394 | } | ||
386 | info->popScope(); | 395 | info->popScope(); |
387 | auto line = "when "s + condition->to_string(ud); | 396 | auto line = "when "s + condition->to_string(ud); |
388 | if (line.find('\n') != std::string::npos) { | 397 | if (line.find('\n') != std::string::npos) { |
@@ -405,6 +414,9 @@ std::string Switch_t::to_string(void* ud) const { | |||
405 | temp.emplace_back(info->ind() + "else"s); | 414 | temp.emplace_back(info->ind() + "else"s); |
406 | info->pushScope(); | 415 | info->pushScope(); |
407 | temp.emplace_back(lastBranch->to_string(ud)); | 416 | temp.emplace_back(lastBranch->to_string(ud)); |
417 | if (temp.back().empty()) { | ||
418 | temp.back() = info->ind() + "--"s; | ||
419 | } | ||
408 | info->popScope(); | 420 | info->popScope(); |
409 | } | 421 | } |
410 | } | 422 | } |
@@ -412,10 +424,18 @@ std::string Switch_t::to_string(void* ud) const { | |||
412 | return join(temp, "\n"sv); | 424 | return join(temp, "\n"sv); |
413 | } | 425 | } |
414 | std::string Assignment_t::to_string(void* ud) const { | 426 | std::string Assignment_t::to_string(void* ud) const { |
415 | return expList->to_string(ud) + ' ' + assign->to_string(ud); | 427 | if (expList) { |
428 | return ", "s + expList->to_string(ud) + " :"s + assign->to_string(ud); | ||
429 | } else { | ||
430 | return " :"s + assign->to_string(ud); | ||
431 | } | ||
416 | } | 432 | } |
417 | std::string IfCond_t::to_string(void* ud) const { | 433 | std::string IfCond_t::to_string(void* ud) const { |
418 | return condition->to_string(ud); | 434 | if (assignment) { |
435 | return condition->to_string(ud) + assignment->to_string(ud); | ||
436 | } else { | ||
437 | return condition->to_string(ud); | ||
438 | } | ||
419 | } | 439 | } |
420 | std::string If_t::to_string(void* ud) const { | 440 | std::string If_t::to_string(void* ud) const { |
421 | auto info = reinterpret_cast<YueFormat*>(ud); | 441 | auto info = reinterpret_cast<YueFormat*>(ud); |
@@ -447,11 +467,17 @@ std::string If_t::to_string(void* ud) const { | |||
447 | if (condition) { | 467 | if (condition) { |
448 | info->pushScope(); | 468 | info->pushScope(); |
449 | temp.emplace_back(node->to_string(ud)); | 469 | temp.emplace_back(node->to_string(ud)); |
470 | if (temp.back().empty()) { | ||
471 | temp.back() = info->ind() + "--"s; | ||
472 | } | ||
450 | info->popScope(); | 473 | info->popScope(); |
451 | } else { | 474 | } else { |
452 | temp.emplace_back(info->ind() + "else"s); | 475 | temp.emplace_back(info->ind() + "else"s); |
453 | info->pushScope(); | 476 | info->pushScope(); |
454 | temp.emplace_back(node->to_string(ud)); | 477 | temp.emplace_back(node->to_string(ud)); |
478 | if (temp.back().empty()) { | ||
479 | temp.back() = info->ind() + "--"s; | ||
480 | } | ||
455 | info->popScope(); | 481 | info->popScope(); |
456 | } | 482 | } |
457 | condition = false; | 483 | condition = false; |
@@ -473,6 +499,9 @@ std::string While_t::to_string(void* ud) const { | |||
473 | } | 499 | } |
474 | info->pushScope(); | 500 | info->pushScope(); |
475 | temp.emplace_back(body->to_string(ud)); | 501 | temp.emplace_back(body->to_string(ud)); |
502 | if (temp.back().empty()) { | ||
503 | temp.back() = info->ind() + "--"s; | ||
504 | } | ||
476 | info->popScope(); | 505 | info->popScope(); |
477 | } | 506 | } |
478 | return join(temp, "\n"sv); | 507 | return join(temp, "\n"sv); |
@@ -486,6 +515,9 @@ std::string Repeat_t::to_string(void* ud) const { | |||
486 | temp.emplace_back("repeat"s); | 515 | temp.emplace_back("repeat"s); |
487 | info->pushScope(); | 516 | info->pushScope(); |
488 | temp.emplace_back(body->to_string(ud)); | 517 | temp.emplace_back(body->to_string(ud)); |
518 | if (temp.back().empty()) { | ||
519 | temp.back() = info->ind() + "--"s; | ||
520 | } | ||
489 | info->popScope(); | 521 | info->popScope(); |
490 | } | 522 | } |
491 | temp.emplace_back(info->ind() + "until "s + condition->to_string(ud)); | 523 | temp.emplace_back(info->ind() + "until "s + condition->to_string(ud)); |
@@ -508,6 +540,9 @@ std::string For_t::to_string(void* ud) const { | |||
508 | } | 540 | } |
509 | info->pushScope(); | 541 | info->pushScope(); |
510 | auto block = body->to_string(ud); | 542 | auto block = body->to_string(ud); |
543 | if (block.empty()) { | ||
544 | block = info->ind() + "--"s; | ||
545 | } | ||
511 | info->popScope(); | 546 | info->popScope(); |
512 | return line + '\n' + block; | 547 | return line + '\n' + block; |
513 | } | 548 | } |
@@ -523,6 +558,9 @@ std::string ForEach_t::to_string(void* ud) const { | |||
523 | } | 558 | } |
524 | info->pushScope(); | 559 | info->pushScope(); |
525 | auto block = body->to_string(ud); | 560 | auto block = body->to_string(ud); |
561 | if (block.empty()) { | ||
562 | block = info->ind() + "--"s; | ||
563 | } | ||
526 | info->popScope(); | 564 | info->popScope(); |
527 | return line + '\n' + block; | 565 | return line + '\n' + block; |
528 | } | 566 | } |
@@ -534,6 +572,9 @@ std::string Do_t::to_string(void* ud) const { | |||
534 | } else { | 572 | } else { |
535 | info->pushScope(); | 573 | info->pushScope(); |
536 | auto block = body->to_string(ud); | 574 | auto block = body->to_string(ud); |
575 | if (block.empty()) { | ||
576 | block = info->ind() + "--"s; | ||
577 | } | ||
537 | info->popScope(); | 578 | info->popScope(); |
538 | return "do\n"s + block; | 579 | return "do\n"s + block; |
539 | } | 580 | } |
@@ -543,6 +584,9 @@ std::string CatchBlock_t::to_string(void* ud) const { | |||
543 | auto line = "catch "s + err->to_string(ud); | 584 | auto line = "catch "s + err->to_string(ud); |
544 | info->pushScope(); | 585 | info->pushScope(); |
545 | auto block = body->to_string(ud); | 586 | auto block = body->to_string(ud); |
587 | if (block.empty()) { | ||
588 | block = info->ind() + "--"s; | ||
589 | } | ||
546 | info->popScope(); | 590 | info->popScope(); |
547 | return line + '\n' + block; | 591 | return line + '\n' + block; |
548 | } | 592 | } |
@@ -555,6 +599,9 @@ std::string Try_t::to_string(void* ud) const { | |||
555 | temp.emplace_back("try"s); | 599 | temp.emplace_back("try"s); |
556 | info->pushScope(); | 600 | info->pushScope(); |
557 | temp.emplace_back(func->to_string(ud)); | 601 | temp.emplace_back(func->to_string(ud)); |
602 | if (temp.back().empty()) { | ||
603 | temp.back() = info->ind() + "--"s; | ||
604 | } | ||
558 | info->popScope(); | 605 | info->popScope(); |
559 | } | 606 | } |
560 | if (catchBlock) { | 607 | if (catchBlock) { |
@@ -571,7 +618,11 @@ std::string Comprehension_t::to_string(void* ud) const { | |||
571 | temp.front().insert(0, temp.front()[0] == '[' ? " "s : ""s); | 618 | temp.front().insert(0, temp.front()[0] == '[' ? " "s : ""s); |
572 | } | 619 | } |
573 | if (items.size() != 2 || !ast_is<CompInner_t>(items.back())) { | 620 | if (items.size() != 2 || !ast_is<CompInner_t>(items.back())) { |
574 | return '[' + join(temp, ", "sv) + ']'; | 621 | if (items.size() == 1) { |
622 | return '[' + join(temp, ", "sv) + ",]"s; | ||
623 | } else { | ||
624 | return '[' + join(temp, ", "sv) + ']'; | ||
625 | } | ||
575 | } else { | 626 | } else { |
576 | return '[' + join(temp, " "sv) + ']'; | 627 | return '[' + join(temp, " "sv) + ']'; |
577 | } | 628 | } |
@@ -613,7 +664,7 @@ std::string CompInner_t::to_string(void* ud) const { | |||
613 | std::string Assign_t::to_string(void* ud) const { | 664 | std::string Assign_t::to_string(void* ud) const { |
614 | str_list temp; | 665 | str_list temp; |
615 | if (values.size() == 1 && ast_is<TableBlock_t>(values.front())) { | 666 | if (values.size() == 1 && ast_is<TableBlock_t>(values.front())) { |
616 | return '=' + values.front()->to_string(ud); | 667 | return "=\n"s + values.front()->to_string(ud); |
617 | } | 668 | } |
618 | for (auto value : values.objects()) { | 669 | for (auto value : values.objects()) { |
619 | temp.emplace_back(value->to_string(ud)); | 670 | temp.emplace_back(value->to_string(ud)); |
@@ -790,7 +841,13 @@ static bool isInBlockExp(ast_node* node) { | |||
790 | TblComprehension_t, Comprehension_t>(simpleValue->value)) { | 841 | TblComprehension_t, Comprehension_t>(simpleValue->value)) { |
791 | return true; | 842 | return true; |
792 | } | 843 | } |
844 | } else if (auto chainValue = value->item.as<ChainValue_t>()) { | ||
845 | if (ast_is<InvokeArgs_t>(chainValue->items.back())) { | ||
846 | return true; | ||
847 | } | ||
793 | } | 848 | } |
849 | } else if (ast_is<TableBlock_t>(node)) { | ||
850 | return true; | ||
794 | } | 851 | } |
795 | return false; | 852 | return false; |
796 | } | 853 | } |
@@ -863,7 +920,7 @@ std::string TableBlock_t::to_string(void* ud) const { | |||
863 | temp.emplace_back(info->ind() + "* "s + value->to_string(ud)); | 920 | temp.emplace_back(info->ind() + "* "s + value->to_string(ud)); |
864 | break; | 921 | break; |
865 | case id<TableBlock_t>(): | 922 | case id<TableBlock_t>(): |
866 | temp.emplace_back(info->ind() + "*"s + value->to_string(ud)); | 923 | temp.emplace_back(info->ind() + "*\n"s + value->to_string(ud)); |
867 | break; | 924 | break; |
868 | default: | 925 | default: |
869 | temp.emplace_back(info->ind() + value->to_string(ud)); | 926 | temp.emplace_back(info->ind() + value->to_string(ud)); |
@@ -871,21 +928,25 @@ std::string TableBlock_t::to_string(void* ud) const { | |||
871 | } | 928 | } |
872 | } | 929 | } |
873 | info->popScope(); | 930 | info->popScope(); |
874 | return '\n' + join(temp, "\n"sv); | 931 | return join(temp, "\n"sv); |
875 | } | 932 | } |
876 | std::string TableBlockIndent_t::to_string(void* ud) const { | 933 | std::string TableBlockIndent_t::to_string(void* ud) const { |
877 | auto info = reinterpret_cast<YueFormat*>(ud); | 934 | auto info = reinterpret_cast<YueFormat*>(ud); |
878 | str_list temp; | 935 | str_list temp; |
879 | info->pushScope(); | 936 | info->pushScope(); |
880 | for (auto value : values.objects()) { | 937 | for (auto value : values.objects()) { |
881 | if (value == values.front()) { | 938 | if (ast_is<TableBlockIndent_t>(value)) { |
882 | temp.emplace_back("* "s + value->to_string(ud)); | 939 | temp.emplace_back("\n"s + value->to_string(ud)); |
883 | } else { | 940 | } else { |
884 | temp.emplace_back(info->ind() + value->to_string(ud)); | 941 | if (value == values.front()) { |
942 | temp.emplace_back(" "s + value->to_string(ud)); | ||
943 | } else { | ||
944 | temp.emplace_back(info->ind() + value->to_string(ud)); | ||
945 | } | ||
885 | } | 946 | } |
886 | } | 947 | } |
887 | info->popScope(); | 948 | info->popScope(); |
888 | return join(temp, "\n"sv); | 949 | return "*"s + join(temp, "\n"sv); |
889 | } | 950 | } |
890 | std::string ClassMemberList_t::to_string(void* ud) const { | 951 | std::string ClassMemberList_t::to_string(void* ud) const { |
891 | auto info = reinterpret_cast<YueFormat*>(ud); | 952 | auto info = reinterpret_cast<YueFormat*>(ud); |
@@ -893,7 +954,7 @@ std::string ClassMemberList_t::to_string(void* ud) const { | |||
893 | for (auto value : values.objects()) { | 954 | for (auto value : values.objects()) { |
894 | temp.emplace_back(info->ind() + value->to_string(ud)); | 955 | temp.emplace_back(info->ind() + value->to_string(ud)); |
895 | } | 956 | } |
896 | return join(temp, "\n"sv); | 957 | return join(temp, ", "sv); |
897 | } | 958 | } |
898 | std::string ClassBlock_t::to_string(void* ud) const { | 959 | std::string ClassBlock_t::to_string(void* ud) const { |
899 | auto info = reinterpret_cast<YueFormat*>(ud); | 960 | auto info = reinterpret_cast<YueFormat*>(ud); |
@@ -929,7 +990,7 @@ std::string GlobalValues_t::to_string(void* ud) const { | |||
929 | auto line = nameList->to_string(ud); | 990 | auto line = nameList->to_string(ud); |
930 | if (valueList) { | 991 | if (valueList) { |
931 | if (valueList.is<TableBlock_t>()) { | 992 | if (valueList.is<TableBlock_t>()) { |
932 | line += " ="s + valueList->to_string(ud); | 993 | line += " =\n"s + valueList->to_string(ud); |
933 | } else { | 994 | } else { |
934 | line += " = "s + valueList->to_string(ud); | 995 | line += " = "s + valueList->to_string(ud); |
935 | } | 996 | } |
@@ -949,8 +1010,12 @@ std::string Export_t::to_string(void* ud) const { | |||
949 | line += target->to_string(ud); | 1010 | line += target->to_string(ud); |
950 | break; | 1011 | break; |
951 | case id<Exp_t>(): { | 1012 | case id<Exp_t>(): { |
952 | auto valueStr = target->to_string(ud); | 1013 | if (def) { |
953 | line += '[' + (valueStr[0] == '[' ? " "s : ""s) + valueStr + ']'; | 1014 | line += target->to_string(ud); |
1015 | } else { | ||
1016 | auto valueStr = target->to_string(ud); | ||
1017 | line += '[' + (valueStr[0] == '[' ? " "s : ""s) + valueStr + ']'; | ||
1018 | } | ||
954 | break; | 1019 | break; |
955 | } | 1020 | } |
956 | default: | 1021 | default: |
@@ -973,7 +1038,7 @@ std::string NormalPair_t::to_string(void* ud) const { | |||
973 | } else { | 1038 | } else { |
974 | line = key->to_string(ud) + ":"s; | 1039 | line = key->to_string(ud) + ":"s; |
975 | } | 1040 | } |
976 | line += (value.is<TableBlock_t>() ? ""s : " "s) + value->to_string(ud); | 1041 | line += (value.is<TableBlock_t>() ? "\n"s : " "s) + value->to_string(ud); |
977 | return line; | 1042 | return line; |
978 | } | 1043 | } |
979 | std::string MetaVariablePair_t::to_string(void* ud) const { | 1044 | std::string MetaVariablePair_t::to_string(void* ud) const { |
@@ -989,7 +1054,7 @@ std::string MetaNormalPair_t::to_string(void* ud) const { | |||
989 | } else { | 1054 | } else { |
990 | line = '<' + key->to_string(ud) + ">:"s; | 1055 | line = '<' + key->to_string(ud) + ">:"s; |
991 | } | 1056 | } |
992 | line += (value.is<TableBlock_t>() ? ""s : " "s) + value->to_string(ud); | 1057 | line += (value.is<TableBlock_t>() ? "\n"s : " "s) + value->to_string(ud); |
993 | return line; | 1058 | return line; |
994 | } | 1059 | } |
995 | std::string VariablePairDef_t::to_string(void* ud) const { | 1060 | std::string VariablePairDef_t::to_string(void* ud) const { |
@@ -1033,23 +1098,38 @@ std::string FnArgDef_t::to_string(void* ud) const { | |||
1033 | line += op->to_string(ud); | 1098 | line += op->to_string(ud); |
1034 | } | 1099 | } |
1035 | if (defaultValue) { | 1100 | if (defaultValue) { |
1036 | if (isInBlockExp(defaultValue)) { | 1101 | line += " = "s + defaultValue->to_string(ud); |
1037 | line += " = ("s + defaultValue->to_string(ud) + ')'; | ||
1038 | } else { | ||
1039 | line += " = "s + defaultValue->to_string(ud); | ||
1040 | } | ||
1041 | } | 1102 | } |
1042 | return line; | 1103 | return line; |
1043 | } | 1104 | } |
1044 | std::string FnArgDefList_t::to_string(void* ud) const { | 1105 | std::string FnArgDefList_t::to_string(void* ud) const { |
1106 | auto info = reinterpret_cast<YueFormat*>(ud); | ||
1045 | str_list temp; | 1107 | str_list temp; |
1108 | bool hasInBlockExp = false; | ||
1046 | for (auto def : definitions.objects()) { | 1109 | for (auto def : definitions.objects()) { |
1047 | temp.emplace_back(def->to_string(ud)); | 1110 | auto argDef = static_cast<FnArgDef_t*>(def); |
1111 | if (argDef->defaultValue && isInBlockExp(argDef->defaultValue)) { | ||
1112 | hasInBlockExp = true; | ||
1113 | break; | ||
1114 | } | ||
1048 | } | 1115 | } |
1049 | if (varArg) { | 1116 | if (hasInBlockExp) { |
1050 | temp.emplace_back(varArg->to_string(ud)); | 1117 | for (auto def : definitions.objects()) { |
1118 | temp.emplace_back(info->ind() + def->to_string(ud)); | ||
1119 | } | ||
1120 | if (varArg) { | ||
1121 | temp.emplace_back(info->ind() + varArg->to_string(ud)); | ||
1122 | } | ||
1123 | return join(temp, "\n"sv); | ||
1124 | } else { | ||
1125 | for (auto def : definitions.objects()) { | ||
1126 | temp.emplace_back(def->to_string(ud)); | ||
1127 | } | ||
1128 | if (varArg) { | ||
1129 | temp.emplace_back(varArg->to_string(ud)); | ||
1130 | } | ||
1131 | return join(temp, ", "sv); | ||
1051 | } | 1132 | } |
1052 | return join(temp, ", "sv); | ||
1053 | } | 1133 | } |
1054 | std::string OuterVarShadow_t::to_string(void* ud) const { | 1134 | std::string OuterVarShadow_t::to_string(void* ud) const { |
1055 | if (varList) { | 1135 | if (varList) { |
@@ -1059,14 +1139,38 @@ std::string OuterVarShadow_t::to_string(void* ud) const { | |||
1059 | } | 1139 | } |
1060 | } | 1140 | } |
1061 | std::string FnArgsDef_t::to_string(void* ud) const { | 1141 | std::string FnArgsDef_t::to_string(void* ud) const { |
1062 | std::string line; | 1142 | auto info = reinterpret_cast<YueFormat*>(ud); |
1143 | bool hasInBlockExp = false; | ||
1063 | if (defList) { | 1144 | if (defList) { |
1064 | line += defList->to_string(ud); | 1145 | for (auto def : defList->definitions.objects()) { |
1146 | auto argDef = static_cast<FnArgDef_t*>(def); | ||
1147 | if (argDef->defaultValue && isInBlockExp(argDef->defaultValue)) { | ||
1148 | hasInBlockExp = true; | ||
1149 | break; | ||
1150 | } | ||
1151 | } | ||
1065 | } | 1152 | } |
1066 | if (shadowOption) { | 1153 | if (hasInBlockExp) { |
1067 | line += (line.empty() ? ""s : " "s) + shadowOption->to_string(ud); | 1154 | str_list temp; |
1155 | info->pushScope(); | ||
1156 | if (defList) { | ||
1157 | temp.push_back(defList->to_string(ud)); | ||
1158 | } | ||
1159 | if (shadowOption) { | ||
1160 | temp.push_back(info->ind() + shadowOption->to_string(ud)); | ||
1161 | } | ||
1162 | info->popScope(); | ||
1163 | return "(\n" + join(temp, "\n"sv) + '\n' + info->ind() + ')'; | ||
1164 | } else { | ||
1165 | std::string line; | ||
1166 | if (defList) { | ||
1167 | line += defList->to_string(ud); | ||
1168 | } | ||
1169 | if (shadowOption) { | ||
1170 | line += (line.empty() ? ""s : " "s) + shadowOption->to_string(ud); | ||
1171 | } | ||
1172 | return line.empty() ? (defList ? "()"s : ""s) : '(' + line + ')'; | ||
1068 | } | 1173 | } |
1069 | return line.empty() ? ""s : '(' + line + ')'; | ||
1070 | } | 1174 | } |
1071 | std::string FunLit_t::to_string(void* ud) const { | 1175 | std::string FunLit_t::to_string(void* ud) const { |
1072 | auto info = reinterpret_cast<YueFormat*>(ud); | 1176 | auto info = reinterpret_cast<YueFormat*>(ud); |
@@ -1080,7 +1184,11 @@ std::string FunLit_t::to_string(void* ud) const { | |||
1080 | line += ' ' + body->to_string(ud); | 1184 | line += ' ' + body->to_string(ud); |
1081 | } else { | 1185 | } else { |
1082 | info->pushScope(); | 1186 | info->pushScope(); |
1083 | line += '\n' + body->to_string(ud); | 1187 | auto bodyStr = body->to_string(ud); |
1188 | if (bodyStr.empty()) { | ||
1189 | bodyStr = info->ind() + "--"s; | ||
1190 | } | ||
1191 | line += '\n' + bodyStr; | ||
1084 | info->popScope(); | 1192 | info->popScope(); |
1085 | } | 1193 | } |
1086 | } | 1194 | } |
@@ -1096,14 +1204,16 @@ std::string MacroLit_t::to_string(void* ud) const { | |||
1096 | line = '(' + argsDef->to_string(ud) + ')'; | 1204 | line = '(' + argsDef->to_string(ud) + ')'; |
1097 | } | 1205 | } |
1098 | line += "->"s; | 1206 | line += "->"s; |
1099 | if (body) { | 1207 | if (body->content.is<Statement_t>()) { |
1100 | if (body->content.is<Statement_t>()) { | 1208 | line += ' ' + body->to_string(ud); |
1101 | line += ' ' + body->to_string(ud); | 1209 | } else { |
1102 | } else { | 1210 | info->pushScope(); |
1103 | info->pushScope(); | 1211 | auto bodyStr = body->to_string(ud); |
1104 | line += '\n' + body->to_string(ud); | 1212 | if (bodyStr.empty()) { |
1105 | info->popScope(); | 1213 | bodyStr = info->ind() + "--"s; |
1106 | } | 1214 | } |
1215 | line += '\n' + bodyStr; | ||
1216 | info->popScope(); | ||
1107 | } | 1217 | } |
1108 | return line; | 1218 | return line; |
1109 | } | 1219 | } |
@@ -1113,14 +1223,16 @@ std::string Macro_t::to_string(void* ud) const { | |||
1113 | std::string MacroInPlace_t::to_string(void* ud) const { | 1223 | std::string MacroInPlace_t::to_string(void* ud) const { |
1114 | auto info = reinterpret_cast<YueFormat*>(ud); | 1224 | auto info = reinterpret_cast<YueFormat*>(ud); |
1115 | auto line = "$->"s; | 1225 | auto line = "$->"s; |
1116 | if (body) { | 1226 | if (body->content.is<Statement_t>()) { |
1117 | if (body->content.is<Statement_t>()) { | 1227 | line += ' ' + body->to_string(ud); |
1118 | line += ' ' + body->to_string(ud); | 1228 | } else { |
1119 | } else { | 1229 | info->pushScope(); |
1120 | info->pushScope(); | 1230 | auto bodyStr = body->to_string(ud); |
1121 | line += '\n' + body->to_string(ud); | 1231 | if (bodyStr.empty()) { |
1122 | info->popScope(); | 1232 | bodyStr = info->ind() + "--"s; |
1123 | } | 1233 | } |
1234 | line += '\n' + bodyStr; | ||
1235 | info->popScope(); | ||
1124 | } | 1236 | } |
1125 | return line; | 1237 | return line; |
1126 | } | 1238 | } |
@@ -1135,15 +1247,32 @@ std::string AssignableNameList_t::to_string(void* ud) const { | |||
1135 | return join(temp, ", "sv); | 1247 | return join(temp, ", "sv); |
1136 | } | 1248 | } |
1137 | std::string InvokeArgs_t::to_string(void* ud) const { | 1249 | std::string InvokeArgs_t::to_string(void* ud) const { |
1138 | if (!args.empty() && ast_is<TableBlock_t>(args.back())) { | 1250 | auto info = reinterpret_cast<YueFormat*>(ud); |
1251 | bool hasInBlockExp = false; | ||
1252 | for (auto arg : args.objects()) { | ||
1253 | if (isInBlockExp(arg)) { | ||
1254 | hasInBlockExp = true; | ||
1255 | break; | ||
1256 | } | ||
1257 | } | ||
1258 | if (hasInBlockExp) { | ||
1139 | str_list temp; | 1259 | str_list temp; |
1260 | bool newLine = false; | ||
1140 | for (auto arg : args.objects()) { | 1261 | for (auto arg : args.objects()) { |
1141 | if (arg != args.back()) { | 1262 | if (arg == args.front()) { |
1142 | temp.emplace_back(arg->to_string(ud)); | 1263 | if (ast_is<TableBlock_t>(arg)) { |
1264 | newLine = true; | ||
1265 | } | ||
1266 | temp.push_back(arg->to_string(ud)); | ||
1267 | info->pushScope(); | ||
1268 | } else if (ast_is<TableBlock_t>(arg)) { | ||
1269 | temp.push_back(arg->to_string(ud)); | ||
1270 | } else { | ||
1271 | temp.push_back(info->ind() + arg->to_string(ud)); | ||
1143 | } | 1272 | } |
1144 | } | 1273 | } |
1145 | auto list = join(temp, ", "sv); | 1274 | info->popScope(); |
1146 | return ' ' + list + (list.empty() ? ""s : ","s) + args.back()->to_string(ud); | 1275 | return (newLine ? '\n' : ' ') + join(temp, ",\n"sv); |
1147 | } else { | 1276 | } else { |
1148 | str_list temp; | 1277 | str_list temp; |
1149 | for (auto arg : args.objects()) { | 1278 | for (auto arg : args.objects()) { |
@@ -1203,10 +1332,29 @@ std::string StatementAppendix_t::to_string(void* ud) const { | |||
1203 | } | 1332 | } |
1204 | std::string Statement_t::to_string(void* ud) const { | 1333 | std::string Statement_t::to_string(void* ud) const { |
1205 | std::string line; | 1334 | std::string line; |
1206 | if (appendix) { | 1335 | if (!comments.empty()) { |
1207 | return content->to_string(ud) + ' ' + appendix->to_string(ud); | 1336 | auto info = reinterpret_cast<YueFormat*>(ud); |
1337 | str_list temp; | ||
1338 | for (ast_node* comment : comments.objects()) { | ||
1339 | if (comment == comments.front()) { | ||
1340 | temp.push_back(comment->to_string(ud)); | ||
1341 | } else { | ||
1342 | temp.push_back(info->ind() + comment->to_string(ud)); | ||
1343 | } | ||
1344 | } | ||
1345 | if (appendix) { | ||
1346 | temp.push_back(info->ind() + content->to_string(ud) + ' ' + appendix->to_string(ud)); | ||
1347 | return join(temp, "\n"sv); | ||
1348 | } else { | ||
1349 | temp.push_back(info->ind() + content->to_string(ud)); | ||
1350 | return join(temp, "\n"sv); | ||
1351 | } | ||
1208 | } else { | 1352 | } else { |
1209 | return content->to_string(ud); | 1353 | if (appendix) { |
1354 | return content->to_string(ud) + ' ' + appendix->to_string(ud); | ||
1355 | } else { | ||
1356 | return content->to_string(ud); | ||
1357 | } | ||
1210 | } | 1358 | } |
1211 | } | 1359 | } |
1212 | std::string StatementSep_t::to_string(void*) const { | 1360 | std::string StatementSep_t::to_string(void*) const { |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 3e60556..59f6d4b 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -75,7 +75,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
75 | "close"s // Lua 5.4 | 75 | "close"s // Lua 5.4 |
76 | }; | 76 | }; |
77 | 77 | ||
78 | const std::string_view version = "0.21.1"sv; | 78 | const std::string_view version = "0.21.2"sv; |
79 | const std::string_view extension = "yue"sv; | 79 | const std::string_view extension = "yue"sv; |
80 | 80 | ||
81 | class CompileError : public std::logic_error { | 81 | class CompileError : public std::logic_error { |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 4b865f5..89791d6 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
@@ -477,7 +477,7 @@ YueParser::YueParser() { | |||
477 | space | 477 | space |
478 | ); | 478 | ); |
479 | 479 | ||
480 | list_lit_lines = space_break >> list_lit_line >> *(-(space >> ',') >> space_break >> list_lit_line) >> -(space >> ','); | 480 | list_lit_lines = +space_break >> list_lit_line >> *(-(space >> ',') >> space_break >> list_lit_line) >> -(space >> ','); |
481 | 481 | ||
482 | Comprehension = '[' >> not_('[') >> | 482 | Comprehension = '[' >> not_('[') >> |
483 | Seperator >> space >> ( | 483 | Seperator >> space >> ( |
@@ -489,7 +489,6 @@ YueParser::YueParser() { | |||
489 | white >> ']' >> not_(space >> '=') | 489 | white >> ']' >> not_(space >> '=') |
490 | ); | 490 | ); |
491 | 491 | ||
492 | (space >> disable_for_rule(Exp) >> space >> CompInner >> space >> ']'); | ||
493 | CompValue = ',' >> space >> Exp; | 492 | CompValue = ',' >> space >> Exp; |
494 | TblComprehension = and_('{') >> ('{' >> space >> disable_for_rule(Exp >> space >> -(CompValue >> space)) >> CompInner >> space >> '}' | braces_expression_error); | 493 | TblComprehension = and_('{') >> ('{' >> space >> disable_for_rule(Exp >> space >> -(CompValue >> space)) >> CompInner >> space >> '}' | braces_expression_error); |
495 | 494 | ||
@@ -829,17 +828,26 @@ YueParser::YueParser() { | |||
829 | '*' >> space >> (SpreadExp | Exp | TableBlock) | 828 | '*' >> space >> (SpreadExp | Exp | TableBlock) |
830 | ); | 829 | ); |
831 | 830 | ||
831 | fn_arg_def_list = FnArgDef >> *(space >> ',' >> space >> FnArgDef); | ||
832 | |||
833 | fn_arg_def_lit_line = ( | ||
834 | push_indent_match >> (space >> fn_arg_def_list >> pop_indent | pop_indent) | ||
835 | ) | ( | ||
836 | space | ||
837 | ); | ||
838 | |||
839 | fn_arg_def_lit_lines = fn_arg_def_lit_line >> *(-(space >> ',') >> space_break >> fn_arg_def_lit_line); | ||
840 | |||
832 | FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '=' >> space >> Exp); | 841 | FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '=' >> space >> Exp); |
833 | 842 | ||
834 | FnArgDefList = Seperator >> (( | 843 | FnArgDefList = Seperator >> ( |
835 | FnArgDef >> | 844 | fn_arg_def_lit_lines >> -(-(space >> ',') >> white >> VarArg) | |
836 | *(space >> (',' | line_break) >> white >> FnArgDef) >> | 845 | white >> VarArg |
837 | -(space >> (',' | line_break) >> white >> VarArg) | 846 | ); |
838 | ) | VarArg); | ||
839 | 847 | ||
840 | OuterVarShadow = key("using") >> space >> (NameList | key("nil")); | 848 | OuterVarShadow = key("using") >> space >> (NameList | key("nil")); |
841 | 849 | ||
842 | FnArgsDef = '(' >> white >> -FnArgDefList >> -(space >> OuterVarShadow) >> white >> ')'; | 850 | FnArgsDef = '(' >> *space_break >> -FnArgDefList >> -(white >> OuterVarShadow) >> white >> ')'; |
843 | FnArrow = expr("->") | "=>"; | 851 | FnArrow = expr("->") | "=>"; |
844 | FunLit = -FnArgsDef >> space >> FnArrow >> -(space >> Body); | 852 | FunLit = -FnArgsDef >> space >> FnArrow >> -(space >> Body); |
845 | 853 | ||
@@ -873,8 +881,8 @@ YueParser::YueParser() { | |||
873 | 881 | ||
874 | invoke_args_with_table = | 882 | invoke_args_with_table = |
875 | ',' >> ( | 883 | ',' >> ( |
876 | TableBlock | | 884 | arg_table_block | |
877 | space_break >> advance_match >> arg_block >> -arg_table_block | 885 | space_break >> advance_match >> arg_block >> -(-(space >> ',') >> arg_table_block) |
878 | ) | arg_table_block; | 886 | ) | arg_table_block; |
879 | 887 | ||
880 | leading_spaces_error = pl::user(+space_one >> '(' >> space >> Exp >> +(space >> ',' >> space >> Exp) >> space >> ')', [](const item_t& item) { | 888 | leading_spaces_error = pl::user(+space_one >> '(' >> space >> Exp >> +(space >> ',' >> space >> Exp) >> space >> ')', [](const item_t& item) { |
@@ -954,11 +962,10 @@ YueParser::YueParser() { | |||
954 | 962 | ||
955 | Body = in_block | Statement; | 963 | Body = in_block | Statement; |
956 | 964 | ||
957 | empty_line_break = ( | 965 | empty_line_break = |
958 | check_indent >> (multi_line_comment >> space | comment) | | 966 | check_indent >> (multi_line_comment >> space | comment) >> and_(stop) | |
959 | advance >> ensure(multi_line_comment >> space | comment, pop_indent) | | 967 | advance >> ensure(multi_line_comment >> space | comment, pop_indent) >> and_(stop) | |
960 | plain_space | 968 | plain_space >> and_(line_break); |
961 | ) >> and_(stop); | ||
962 | 969 | ||
963 | indentation_error = pl::user(not_(pipe_operator | eof()), [](const item_t& item) { | 970 | indentation_error = pl::user(not_(pipe_operator | eof()), [](const item_t& item) { |
964 | throw ParserError("unexpected indent"sv, item.begin); | 971 | throw ParserError("unexpected indent"sv, item.begin); |
@@ -1084,6 +1091,11 @@ void trim(std::string& str) { | |||
1084 | } // namespace Utils | 1091 | } // namespace Utils |
1085 | 1092 | ||
1086 | std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { | 1093 | std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { |
1094 | if (!codes) { | ||
1095 | std::ostringstream buf; | ||
1096 | buf << errLine + lineOffset << ": "sv << msg; | ||
1097 | return buf.str(); | ||
1098 | } | ||
1087 | const int ASCII = 255; | 1099 | const int ASCII = 255; |
1088 | int length = errLine; | 1100 | int length = errLine; |
1089 | auto begin = codes->begin(); | 1101 | auto begin = codes->begin(); |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index c3d5d7d..e183bf2 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
@@ -222,6 +222,9 @@ private: | |||
222 | NONE_AST_RULE(fn_args_lit_line); | 222 | NONE_AST_RULE(fn_args_lit_line); |
223 | NONE_AST_RULE(fn_args_lit_lines); | 223 | NONE_AST_RULE(fn_args_lit_lines); |
224 | NONE_AST_RULE(fn_args); | 224 | NONE_AST_RULE(fn_args); |
225 | NONE_AST_RULE(fn_arg_def_list); | ||
226 | NONE_AST_RULE(fn_arg_def_lit_line); | ||
227 | NONE_AST_RULE(fn_arg_def_lit_lines); | ||
225 | NONE_AST_RULE(destruct_def); | 228 | NONE_AST_RULE(destruct_def); |
226 | NONE_AST_RULE(macro_args_def); | 229 | NONE_AST_RULE(macro_args_def); |
227 | NONE_AST_RULE(chain_call); | 230 | NONE_AST_RULE(chain_call); |
diff --git a/src/yuescript/yuescript.cpp b/src/yuescript/yuescript.cpp index 856d8f3..dbaa287 100644 --- a/src/yuescript/yuescript.cpp +++ b/src/yuescript/yuescript.cpp | |||
@@ -172,6 +172,39 @@ static int yuetolua(lua_State* L) { | |||
172 | return 3; | 172 | return 3; |
173 | } | 173 | } |
174 | 174 | ||
175 | static int yueformat(lua_State* L) { | ||
176 | size_t len = 0; | ||
177 | auto input = luaL_checklstring(L, 1, &len); | ||
178 | int tabSize = 0; | ||
179 | if (!lua_isnoneornil(L, 2)) { | ||
180 | tabSize = static_cast<int>(luaL_checkinteger(L, 2)); | ||
181 | } | ||
182 | std::string_view codes(input, len); | ||
183 | auto info = yue::YueParser{}.parse<yue::File_t>(codes); | ||
184 | if (info.error) { | ||
185 | const auto& error = info.error.value(); | ||
186 | if (!info.codes) { | ||
187 | lua_pushnil(L); | ||
188 | lua_pushlstring(L, error.msg.c_str(), error.msg.size()); | ||
189 | return 2; | ||
190 | } | ||
191 | auto displayMessage = info.errorMessage(error.msg, error.line, error.col, 0); | ||
192 | lua_pushnil(L); | ||
193 | lua_pushlstring(L, displayMessage.c_str(), displayMessage.size()); | ||
194 | return 2; | ||
195 | } | ||
196 | yue::YueFormat formatter{}; | ||
197 | if (tabSize > 0) { | ||
198 | formatter.spaceOverTab = true; | ||
199 | formatter.tabSpaces = tabSize; | ||
200 | } else { | ||
201 | formatter.spaceOverTab = false; | ||
202 | } | ||
203 | auto result = formatter.toString(info.node.get()); | ||
204 | lua_pushlstring(L, result.c_str(), result.size()); | ||
205 | return 1; | ||
206 | } | ||
207 | |||
175 | static int yuecheck(lua_State* L) { | 208 | static int yuecheck(lua_State* L) { |
176 | size_t len = 0; | 209 | size_t len = 0; |
177 | auto input = luaL_checklstring(L, 1, &len); | 210 | auto input = luaL_checklstring(L, 1, &len); |
@@ -268,6 +301,7 @@ static int yuetoast(lua_State* L) { | |||
268 | stack.pop(); | 301 | stack.pop(); |
269 | }; | 302 | }; |
270 | do_call(info.node); | 303 | do_call(info.node); |
304 | yue::YueFormat formatter{}; | ||
271 | while (!stack.empty()) { | 305 | while (!stack.empty()) { |
272 | auto& current = stack.top(); | 306 | auto& current = stack.top(); |
273 | int continuation = current.continuation; | 307 | int continuation = current.continuation; |
@@ -319,7 +353,8 @@ static int yuetoast(lua_State* L) { | |||
319 | lua_rawseti(L, -2, 2); | 353 | lua_rawseti(L, -2, 2); |
320 | lua_pushinteger(L, node->m_begin.m_col); | 354 | lua_pushinteger(L, node->m_begin.m_col); |
321 | lua_rawseti(L, -2, 3); | 355 | lua_rawseti(L, -2, 3); |
322 | auto str = parser.toString(node); | 356 | formatter.indent = 0; |
357 | auto str = node->to_string(&formatter); | ||
323 | yue::Utils::trim(str); | 358 | yue::Utils::trim(str); |
324 | lua_pushlstring(L, str.c_str(), str.length()); | 359 | lua_pushlstring(L, str.c_str(), str.length()); |
325 | lua_rawseti(L, -2, 4); | 360 | lua_rawseti(L, -2, 4); |
@@ -371,8 +406,9 @@ static int yuetoast(lua_State* L) { | |||
371 | return 1; | 406 | return 1; |
372 | } else { | 407 | } else { |
373 | lua_pushnil(L); | 408 | lua_pushnil(L); |
374 | const auto& msg = info.error.value().msg; | 409 | const auto& err = info.error.value(); |
375 | lua_pushlstring(L, msg.c_str(), msg.length()); | 410 | auto displayMessage = info.errorMessage(err.msg, err.line, err.col); |
411 | lua_pushlstring(L, displayMessage.c_str(), displayMessage.length()); | ||
376 | return 2; | 412 | return 2; |
377 | } | 413 | } |
378 | } | 414 | } |
@@ -381,6 +417,7 @@ static const luaL_Reg yuelib[] = { | |||
381 | {"to_lua", yuetolua}, | 417 | {"to_lua", yuetolua}, |
382 | {"to_ast", yuetoast}, | 418 | {"to_ast", yuetoast}, |
383 | {"check", yuecheck}, | 419 | {"check", yuecheck}, |
420 | {"format", yueformat}, | ||
384 | {"version", nullptr}, | 421 | {"version", nullptr}, |
385 | {"options", nullptr}, | 422 | {"options", nullptr}, |
386 | {"load_stacktraceplus", nullptr}, | 423 | {"load_stacktraceplus", nullptr}, |