diff options
Diffstat (limited to '')
| -rw-r--r-- | src/yue.cpp | 39 | ||||
| -rwxr-xr-x | src/yuescript/yue_ast.h | 24 | ||||
| -rwxr-xr-x | src/yuescript/yue_compiler.cpp | 232 | ||||
| -rwxr-xr-x | src/yuescript/yue_parser.cpp | 42 | ||||
| -rwxr-xr-x | src/yuescript/yue_parser.h | 8 | ||||
| -rw-r--r-- | src/yuescript/yuescript.cpp | 10 |
6 files changed, 256 insertions, 99 deletions
diff --git a/src/yue.cpp b/src/yue.cpp index 3e30c70..cb27db8 100644 --- a/src/yue.cpp +++ b/src/yue.cpp | |||
| @@ -21,6 +21,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
| 21 | #include <string_view> | 21 | #include <string_view> |
| 22 | #include <memory> | 22 | #include <memory> |
| 23 | using namespace std::string_view_literals; | 23 | using namespace std::string_view_literals; |
| 24 | using namespace std::string_literals; | ||
| 24 | #include "ghc/fs_std.hpp" | 25 | #include "ghc/fs_std.hpp" |
| 25 | #include "linenoise.hpp" | 26 | #include "linenoise.hpp" |
| 26 | 27 | ||
| @@ -91,10 +92,10 @@ static const char luaminifyCodes[] = | |||
| 91 | 92 | ||
| 92 | static void pushLuaminify(lua_State* L) { | 93 | static void pushLuaminify(lua_State* L) { |
| 93 | if (luaL_loadbuffer(L, luaminifyCodes, sizeof(luaminifyCodes) / sizeof(luaminifyCodes[0]) - 1, "=(luaminify)") != 0) { | 94 | if (luaL_loadbuffer(L, luaminifyCodes, sizeof(luaminifyCodes) / sizeof(luaminifyCodes[0]) - 1, "=(luaminify)") != 0) { |
| 94 | std::string err = std::string("failed to load luaminify module.\n") + lua_tostring(L, -1); | 95 | std::string err = "failed to load luaminify module.\n"s + lua_tostring(L, -1); |
| 95 | luaL_error(L, err.c_str()); | 96 | luaL_error(L, err.c_str()); |
| 96 | } else if (lua_pcall(L, 0, 1, 0) != 0) { | 97 | } else if (lua_pcall(L, 0, 1, 0) != 0) { |
| 97 | std::string err = std::string("failed to init luaminify module.\n") + lua_tostring(L, -1); | 98 | std::string err = "failed to init luaminify module.\n"s + lua_tostring(L, -1); |
| 98 | luaL_error(L, err.c_str()); | 99 | luaL_error(L, err.c_str()); |
| 99 | } | 100 | } |
| 100 | } | 101 | } |
| @@ -209,7 +210,7 @@ int main(int narg, const char** args) { | |||
| 209 | DEFER(lua_settop(L, top)); | 210 | DEFER(lua_settop(L, top)); |
| 210 | pushYue(L, "loadstring"sv); | 211 | pushYue(L, "loadstring"sv); |
| 211 | lua_pushlstring(L, codes.c_str(), codes.size()); | 212 | lua_pushlstring(L, codes.c_str(), codes.size()); |
| 212 | lua_pushstring(L, (std::string("=(repl ") + std::to_string(count) + ')').c_str()); | 213 | lua_pushstring(L, ("=(repl "s + std::to_string(count) + ')').c_str()); |
| 213 | pushOptions(L, -1); | 214 | pushOptions(L, -1); |
| 214 | const std::string_view Err = "\033[35m"sv, Val = "\033[33m"sv, Stop = "\033[0m\n"sv; | 215 | const std::string_view Err = "\033[35m"sv, Val = "\033[33m"sv, Stop = "\033[0m\n"sv; |
| 215 | if (lua_pcall(L, 3, 2, 0) != 0) { | 216 | if (lua_pcall(L, 3, 2, 0) != 0) { |
| @@ -218,7 +219,7 @@ int main(int narg, const char** args) { | |||
| 218 | } | 219 | } |
| 219 | if (lua_isnil(L, -2) != 0) { | 220 | if (lua_isnil(L, -2) != 0) { |
| 220 | std::string err = lua_tostring(L, -1); | 221 | std::string err = lua_tostring(L, -1); |
| 221 | auto modName = std::string("(repl "sv) + std::to_string(count) + "):"; | 222 | auto modName = "(repl "s + std::to_string(count) + "):"s; |
| 222 | if (err.substr(0, modName.size()) == modName) { | 223 | if (err.substr(0, modName.size()) == modName) { |
| 223 | err = err.substr(modName.size()); | 224 | err = err.substr(modName.size()); |
| 224 | } | 225 | } |
| @@ -409,8 +410,8 @@ int main(int narg, const char** args) { | |||
| 409 | std::cout << help; | 410 | std::cout << help; |
| 410 | return 1; | 411 | return 1; |
| 411 | } | 412 | } |
| 412 | } else if (arg.size() > 1 && arg.substr(0, 1) == "-"sv && arg.substr(1, 1) != "-"sv) { | 413 | } else if (arg.size() > 2 && arg.substr(0, 2) == "--"sv && arg.substr(2, 1) != "-"sv) { |
| 413 | auto argStr = arg.substr(1); | 414 | auto argStr = arg.substr(2); |
| 414 | yue::Utils::trim(argStr); | 415 | yue::Utils::trim(argStr); |
| 415 | size_t idx = argStr.find('='); | 416 | size_t idx = argStr.find('='); |
| 416 | if (idx != std::string::npos) { | 417 | if (idx != std::string::npos) { |
| @@ -420,7 +421,7 @@ int main(int narg, const char** args) { | |||
| 420 | yue::Utils::trim(value); | 421 | yue::Utils::trim(value); |
| 421 | config.options[key] = value; | 422 | config.options[key] = value; |
| 422 | } else { | 423 | } else { |
| 423 | config.options[argStr] = ""; | 424 | config.options[argStr] = std::string(); |
| 424 | } | 425 | } |
| 425 | } else { | 426 | } else { |
| 426 | if (fs::is_directory(arg)) { | 427 | if (fs::is_directory(arg)) { |
| @@ -459,7 +460,13 @@ int main(int narg, const char** args) { | |||
| 459 | auto conf = config; | 460 | auto conf = config; |
| 460 | conf.module = file.first; | 461 | conf.module = file.first; |
| 461 | if (!workPath.empty()) { | 462 | if (!workPath.empty()) { |
| 462 | conf.options["path"] = (fs::path(workPath) / "?.lua").string(); | 463 | auto it = conf.options.find("path"); |
| 464 | if (it != conf.options.end()) { | ||
| 465 | it->second += ';'; | ||
| 466 | it->second += (fs::path(workPath) / "?.lua"sv).string(); | ||
| 467 | } else { | ||
| 468 | conf.options["path"] = (fs::path(workPath) / "?.lua"sv).string(); | ||
| 469 | } | ||
| 463 | } | 470 | } |
| 464 | if (dumpCompileTime) { | 471 | if (dumpCompileTime) { |
| 465 | auto start = std::chrono::high_resolution_clock::now(); | 472 | auto start = std::chrono::high_resolution_clock::now(); |
| @@ -499,7 +506,7 @@ int main(int narg, const char** args) { | |||
| 499 | } else { | 506 | } else { |
| 500 | std::string targetExtension("lua"sv); | 507 | std::string targetExtension("lua"sv); |
| 501 | if (result.options) { | 508 | if (result.options) { |
| 502 | auto it = result.options->find("target_extension"); | 509 | auto it = result.options->find("target_extension"s); |
| 503 | if (it != result.options->end()) { | 510 | if (it != result.options->end()) { |
| 504 | targetExtension = it->second; | 511 | targetExtension = it->second; |
| 505 | } | 512 | } |
| @@ -519,19 +526,19 @@ int main(int narg, const char** args) { | |||
| 519 | fs::create_directories(targetFile.parent_path()); | 526 | fs::create_directories(targetFile.parent_path()); |
| 520 | } | 527 | } |
| 521 | if (result.codes.empty()) { | 528 | if (result.codes.empty()) { |
| 522 | return std::tuple{0, targetFile.string(), std::string("Built "sv) + file.first + '\n'}; | 529 | return std::tuple{0, targetFile.string(), "Built "s + file.first + '\n'}; |
| 523 | } | 530 | } |
| 524 | std::ofstream output(targetFile, std::ios::trunc | std::ios::out); | 531 | std::ofstream output(targetFile, std::ios::trunc | std::ios::out); |
| 525 | if (output) { | 532 | if (output) { |
| 526 | const auto& codes = result.codes; | 533 | const auto& codes = result.codes; |
| 527 | if (config.reserveLineNumber) { | 534 | if (config.reserveLineNumber) { |
| 528 | auto head = std::string("-- [yue]: "sv) + file.first + '\n'; | 535 | auto head = "-- [yue]: "s + file.first + '\n'; |
| 529 | output.write(head.c_str(), head.size()); | 536 | output.write(head.c_str(), head.size()); |
| 530 | } | 537 | } |
| 531 | output.write(codes.c_str(), codes.size()); | 538 | output.write(codes.c_str(), codes.size()); |
| 532 | return std::tuple{0, targetFile.string(), std::string("Built "sv) + file.first + '\n'}; | 539 | return std::tuple{0, targetFile.string(), "Built "s + file.first + '\n'}; |
| 533 | } else { | 540 | } else { |
| 534 | return std::tuple{1, std::string(), std::string("Failed to write file: "sv) + targetFile.string() + '\n'}; | 541 | return std::tuple{1, std::string(), "Failed to write file: "s + targetFile.string() + '\n'}; |
| 535 | } | 542 | } |
| 536 | } | 543 | } |
| 537 | } else { | 544 | } else { |
| @@ -541,7 +548,7 @@ int main(int narg, const char** args) { | |||
| 541 | return std::tuple{1, std::string(), buf.str()}; | 548 | return std::tuple{1, std::string(), buf.str()}; |
| 542 | } | 549 | } |
| 543 | } else { | 550 | } else { |
| 544 | return std::tuple{1, std::string(), std::string("Failed to read file: "sv) + file.first + ".\n"}; | 551 | return std::tuple{1, std::string(), "Failed to read file: "s + file.first + ".\n"}; |
| 545 | } | 552 | } |
| 546 | }); | 553 | }); |
| 547 | results.push_back(std::move(task)); | 554 | results.push_back(std::move(task)); |
| @@ -588,7 +595,7 @@ int main(int narg, const char** args) { | |||
| 588 | if (lua_pcall(L, 1, 1, 0) != 0) { | 595 | if (lua_pcall(L, 1, 1, 0) != 0) { |
| 589 | ret = 2; | 596 | ret = 2; |
| 590 | std::string err = lua_tostring(L, -1); | 597 | std::string err = lua_tostring(L, -1); |
| 591 | errs.push_back(std::string("Failed to minify: "sv) + file + '\n' + err + '\n'); | 598 | errs.push_back("Failed to minify: "s + file + '\n' + err + '\n'); |
| 592 | } else { | 599 | } else { |
| 593 | size_t size = 0; | 600 | size_t size = 0; |
| 594 | const char* minifiedCodes = lua_tolstring(L, -1, &size); | 601 | const char* minifiedCodes = lua_tolstring(L, -1, &size); |
| @@ -603,7 +610,7 @@ int main(int narg, const char** args) { | |||
| 603 | } | 610 | } |
| 604 | } else { | 611 | } else { |
| 605 | ret = 2; | 612 | ret = 2; |
| 606 | errs.push_back(std::string("Failed to minify: "sv) + file + '\n'); | 613 | errs.push_back("Failed to minify: "s + file + '\n'); |
| 607 | } | 614 | } |
| 608 | } else { | 615 | } else { |
| 609 | std::cout << msg; | 616 | std::cout << msg; |
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 05ac5ef..620dfcc 100755 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
| @@ -118,16 +118,22 @@ AST_NODE(Local) | |||
| 118 | AST_MEMBER(Local, &item) | 118 | AST_MEMBER(Local, &item) |
| 119 | AST_END(Local, "local"sv) | 119 | AST_END(Local, "local"sv) |
| 120 | 120 | ||
| 121 | class Assign_t; | 121 | AST_LEAF(const_attrib) |
| 122 | AST_END(const_attrib, "const"sv) | ||
| 123 | |||
| 124 | AST_LEAF(close_attrib) | ||
| 125 | AST_END(close_attrib, "close"sv) | ||
| 122 | 126 | ||
| 123 | AST_LEAF(Attrib) | 127 | class simple_table_t; |
| 124 | AST_END(Attrib, "attrib"sv) | 128 | class TableLit_t; |
| 129 | class Assign_t; | ||
| 125 | 130 | ||
| 126 | AST_NODE(LocalAttrib) | 131 | AST_NODE(LocalAttrib) |
| 127 | ast_ptr<true, Attrib_t> attrib; | 132 | ast_sel<true, const_attrib_t, close_attrib_t> attrib; |
| 128 | ast_ptr<true, NameList_t> nameList; | 133 | ast_ptr<true, Seperator_t> sep; |
| 134 | ast_sel_list<true, Variable_t, simple_table_t, TableLit_t> leftList; | ||
| 129 | ast_ptr<true, Assign_t> assign; | 135 | ast_ptr<true, Assign_t> assign; |
| 130 | AST_MEMBER(LocalAttrib, &attrib, &nameList, &assign) | 136 | AST_MEMBER(LocalAttrib, &attrib, &sep, &leftList, &assign) |
| 131 | AST_END(LocalAttrib, "local_attrib"sv) | 137 | AST_END(LocalAttrib, "local_attrib"sv) |
| 132 | 138 | ||
| 133 | AST_NODE(colon_import_name) | 139 | AST_NODE(colon_import_name) |
| @@ -135,9 +141,6 @@ AST_NODE(colon_import_name) | |||
| 135 | AST_MEMBER(colon_import_name, &name) | 141 | AST_MEMBER(colon_import_name, &name) |
| 136 | AST_END(colon_import_name, "colon_import_name"sv) | 142 | AST_END(colon_import_name, "colon_import_name"sv) |
| 137 | 143 | ||
| 138 | class Exp_t; | ||
| 139 | class TableLit_t; | ||
| 140 | |||
| 141 | AST_LEAF(import_literal_inner) | 144 | AST_LEAF(import_literal_inner) |
| 142 | AST_END(import_literal_inner, "import_literal_inner"sv) | 145 | AST_END(import_literal_inner, "import_literal_inner"sv) |
| 143 | 146 | ||
| @@ -147,6 +150,8 @@ AST_NODE(ImportLiteral) | |||
| 147 | AST_MEMBER(ImportLiteral, &sep, &inners) | 150 | AST_MEMBER(ImportLiteral, &sep, &inners) |
| 148 | AST_END(ImportLiteral, "import_literal"sv) | 151 | AST_END(ImportLiteral, "import_literal"sv) |
| 149 | 152 | ||
| 153 | class Exp_t; | ||
| 154 | |||
| 150 | AST_NODE(ImportFrom) | 155 | AST_NODE(ImportFrom) |
| 151 | ast_ptr<true, Seperator_t> sep; | 156 | ast_ptr<true, Seperator_t> sep; |
| 152 | ast_sel_list<true, colon_import_name_t, Variable_t> names; | 157 | ast_sel_list<true, colon_import_name_t, Variable_t> names; |
| @@ -499,7 +504,6 @@ class String_t; | |||
| 499 | class const_value_t; | 504 | class const_value_t; |
| 500 | class ClassDecl_t; | 505 | class ClassDecl_t; |
| 501 | class unary_value_t; | 506 | class unary_value_t; |
| 502 | class TableLit_t; | ||
| 503 | class FunLit_t; | 507 | class FunLit_t; |
| 504 | 508 | ||
| 505 | AST_NODE(SimpleValue) | 509 | AST_NODE(SimpleValue) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 7bbf5e9..0d027a0 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -13,6 +13,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
| 13 | #include <vector> | 13 | #include <vector> |
| 14 | #include <memory> | 14 | #include <memory> |
| 15 | #include <set> | 15 | #include <set> |
| 16 | #include <optional> | ||
| 16 | 17 | ||
| 17 | #include "yuescript/yue_parser.h" | 18 | #include "yuescript/yue_parser.h" |
| 18 | #include "yuescript/yue_compiler.h" | 19 | #include "yuescript/yue_compiler.h" |
| @@ -37,9 +38,6 @@ extern "C" { | |||
| 37 | #endif // YUE_NO_MACRO | 38 | #endif // YUE_NO_MACRO |
| 38 | 39 | ||
| 39 | namespace yue { | 40 | namespace yue { |
| 40 | using namespace std::string_view_literals; | ||
| 41 | using namespace std::string_literals; | ||
| 42 | using namespace parserlib; | ||
| 43 | 41 | ||
| 44 | #define BLOCK_START do { | 42 | #define BLOCK_START do { |
| 45 | #define BLOCK_END } while (false); | 43 | #define BLOCK_END } while (false); |
| @@ -56,7 +54,7 @@ using namespace parserlib; | |||
| 56 | 54 | ||
| 57 | typedef std::list<std::string> str_list; | 55 | typedef std::list<std::string> str_list; |
| 58 | 56 | ||
| 59 | const std::string_view version = "0.13.6"sv; | 57 | const std::string_view version = "0.14.0"sv; |
| 60 | const std::string_view extension = "yue"sv; | 58 | const std::string_view extension = "yue"sv; |
| 61 | 59 | ||
| 62 | class YueCompilerImpl { | 60 | class YueCompilerImpl { |
| @@ -1266,8 +1264,8 @@ private: | |||
| 1266 | 1264 | ||
| 1267 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { | 1265 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { |
| 1268 | auto info = extractDestructureInfo(assignment, true, false); | 1266 | auto info = extractDestructureInfo(assignment, true, false); |
| 1269 | if (!info.first.empty()) { | 1267 | if (!info.destructures.empty()) { |
| 1270 | for (const auto& destruct : info.first) { | 1268 | for (const auto& destruct : info.destructures) { |
| 1271 | str_list defs; | 1269 | str_list defs; |
| 1272 | for (const auto& item : destruct.items) { | 1270 | for (const auto& item : destruct.items) { |
| 1273 | if (!item.targetVar.empty()) { | 1271 | if (!item.targetVar.empty()) { |
| @@ -1319,11 +1317,30 @@ private: | |||
| 1319 | return assignment; | 1317 | return assignment; |
| 1320 | } | 1318 | } |
| 1321 | 1319 | ||
| 1320 | void markDestructureConst(ExpListAssign_t* assignment) { | ||
| 1321 | auto info = extractDestructureInfo(assignment, true, false); | ||
| 1322 | for (auto& destruct : info.destructures) { | ||
| 1323 | for (auto& item : destruct.items) { | ||
| 1324 | if (item.targetVar.empty()) { | ||
| 1325 | throw std::logic_error(_info.errorMessage("can only declare variable as const"sv, item.target)); | ||
| 1326 | } | ||
| 1327 | markVarConst(item.targetVar); | ||
| 1328 | } | ||
| 1329 | } | ||
| 1330 | } | ||
| 1331 | |||
| 1322 | void transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { | 1332 | void transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { |
| 1323 | checkAssignable(assignment->expList); | 1333 | checkAssignable(assignment->expList); |
| 1324 | BLOCK_START | 1334 | BLOCK_START |
| 1325 | auto assign = ast_cast<Assign_t>(assignment->action); | 1335 | auto assign = ast_cast<Assign_t>(assignment->action); |
| 1326 | BREAK_IF(!assign); | 1336 | BREAK_IF(!assign); |
| 1337 | if (assignment->expList->exprs.size() < assign->values.size()) { | ||
| 1338 | auto num = assignment->expList->exprs.size(); | ||
| 1339 | _buf << "no more than "sv << num << " right value"sv; | ||
| 1340 | if (num > 1) _buf << 's'; | ||
| 1341 | _buf << " required"sv; | ||
| 1342 | throw std::logic_error(_info.errorMessage(clearBuf(), assign->values.front())); | ||
| 1343 | } | ||
| 1327 | auto x = assignment; | 1344 | auto x = assignment; |
| 1328 | const auto& exprs = assignment->expList->exprs.objects(); | 1345 | const auto& exprs = assignment->expList->exprs.objects(); |
| 1329 | const auto& values = assign->values.objects(); | 1346 | const auto& values = assign->values.objects(); |
| @@ -1554,15 +1571,15 @@ private: | |||
| 1554 | } | 1571 | } |
| 1555 | BLOCK_END | 1572 | BLOCK_END |
| 1556 | auto info = extractDestructureInfo(assignment, false, optionalDestruct); | 1573 | auto info = extractDestructureInfo(assignment, false, optionalDestruct); |
| 1557 | if (info.first.empty()) { | 1574 | if (info.destructures.empty()) { |
| 1558 | transformAssignmentCommon(assignment, out); | 1575 | transformAssignmentCommon(assignment, out); |
| 1559 | } else { | 1576 | } else { |
| 1560 | str_list temp; | 1577 | str_list temp; |
| 1561 | if (info.second) { | 1578 | if (info.assignment) { |
| 1562 | transformAssignmentCommon(info.second, temp); | 1579 | transformAssignmentCommon(info.assignment, temp); |
| 1563 | } | 1580 | } |
| 1564 | auto x = assignment; | 1581 | auto x = assignment; |
| 1565 | for (auto& destruct : info.first) { | 1582 | for (auto& destruct : info.destructures) { |
| 1566 | std::list<std::pair<ast_ptr<true, Exp_t>, ast_ptr<true, Exp_t>>> leftPairs; | 1583 | std::list<std::pair<ast_ptr<true, Exp_t>, ast_ptr<true, Exp_t>>> leftPairs; |
| 1567 | bool extraScope = false; | 1584 | bool extraScope = false; |
| 1568 | if (destruct.items.size() == 1) { | 1585 | if (destruct.items.size() == 1) { |
| @@ -2030,24 +2047,22 @@ private: | |||
| 2030 | return pairs; | 2047 | return pairs; |
| 2031 | } | 2048 | } |
| 2032 | 2049 | ||
| 2033 | std::pair<std::list<Destructure>, ast_ptr<false, ExpListAssign_t>> | 2050 | struct DestructureInfo { |
| 2034 | extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly, bool optional) { | 2051 | std::list<Destructure> destructures; |
| 2052 | ast_ptr<false, ExpListAssign_t> assignment; | ||
| 2053 | }; | ||
| 2054 | |||
| 2055 | DestructureInfo extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly, bool optional) { | ||
| 2035 | auto x = assignment; | 2056 | auto x = assignment; |
| 2036 | std::list<Destructure> destructs; | 2057 | std::list<Destructure> destructs; |
| 2037 | if (!assignment->action.is<Assign_t>()) return {destructs, nullptr}; | 2058 | if (!assignment->action.is<Assign_t>()) return {destructs, nullptr}; |
| 2038 | auto exprs = assignment->expList->exprs.objects(); | 2059 | auto exprs = assignment->expList->exprs.objects(); |
| 2039 | auto values = assignment->action.to<Assign_t>()->values.objects(); | 2060 | auto values = assignment->action.to<Assign_t>()->values.objects(); |
| 2040 | size_t size = std::max(exprs.size(), values.size()); | 2061 | size_t size = std::max(exprs.size(), values.size()); |
| 2041 | ast_list<false, ast_node> cache; | 2062 | ast_ptr<false, Exp_t> nil; |
| 2042 | if (exprs.size() < size) { | ||
| 2043 | auto var = toAst<Exp_t>("_"sv, x); | ||
| 2044 | cache.push_back(var); | ||
| 2045 | while (exprs.size() < size) exprs.emplace_back(var); | ||
| 2046 | } | ||
| 2047 | ast_ptr<false, Exp_t> nullNode; | ||
| 2048 | if (values.size() < size) { | 2063 | if (values.size() < size) { |
| 2049 | nullNode = toAst<Exp_t>("nil"sv, x); | 2064 | nil = toAst<Exp_t>("nil"sv, x); |
| 2050 | while (values.size() < size) values.emplace_back(nullNode); | 2065 | while (values.size() < size) values.emplace_back(nil); |
| 2051 | } | 2066 | } |
| 2052 | using iter = node_container::iterator; | 2067 | using iter = node_container::iterator; |
| 2053 | std::vector<std::pair<iter, iter>> destructPairs; | 2068 | std::vector<std::pair<iter, iter>> destructPairs; |
| @@ -2059,11 +2074,11 @@ private: | |||
| 2059 | auto value = singleValueFrom(expr); | 2074 | auto value = singleValueFrom(expr); |
| 2060 | ast_node* destructNode = value->getByPath<SimpleValue_t, TableLit_t>(); | 2075 | ast_node* destructNode = value->getByPath<SimpleValue_t, TableLit_t>(); |
| 2061 | if (destructNode || (destructNode = value->item.as<simple_table_t>())) { | 2076 | if (destructNode || (destructNode = value->item.as<simple_table_t>())) { |
| 2062 | if (*j != nullNode) { | 2077 | if (*j != nil) { |
| 2063 | if (auto ssVal = simpleSingleValueFrom(*j)) { | 2078 | if (auto ssVal = simpleSingleValueFrom(*j)) { |
| 2064 | switch (ssVal->value->getId()) { | 2079 | switch (ssVal->value->getId()) { |
| 2065 | case id<const_value_t>(): | 2080 | case id<const_value_t>(): |
| 2066 | throw std::logic_error(_info.errorMessage("can not destructure a const value"sv, ssVal->value)); | 2081 | throw std::logic_error(_info.errorMessage("can not destructure a constant"sv, ssVal->value)); |
| 2067 | break; | 2082 | break; |
| 2068 | case id<Num_t>(): | 2083 | case id<Num_t>(): |
| 2069 | throw std::logic_error(_info.errorMessage("can not destructure a number"sv, ssVal->value)); | 2084 | throw std::logic_error(_info.errorMessage("can not destructure a number"sv, ssVal->value)); |
| @@ -2074,7 +2089,7 @@ private: | |||
| 2074 | } | 2089 | } |
| 2075 | } | 2090 | } |
| 2076 | } else { | 2091 | } else { |
| 2077 | throw std::logic_error(_info.errorMessage("can not destructure a nil value"sv, destructNode)); | 2092 | throw std::logic_error(_info.errorMessage("an explicit destructure target required"sv, destructNode)); |
| 2078 | } | 2093 | } |
| 2079 | destructPairs.push_back({i, j}); | 2094 | destructPairs.push_back({i, j}); |
| 2080 | auto subDestruct = destructNode->new_ptr<TableLit_t>(); | 2095 | auto subDestruct = destructNode->new_ptr<TableLit_t>(); |
| @@ -2173,7 +2188,7 @@ private: | |||
| 2173 | } | 2188 | } |
| 2174 | destruct.items = std::move(pairs); | 2189 | destruct.items = std::move(pairs); |
| 2175 | if (!varDefOnly) { | 2190 | if (!varDefOnly) { |
| 2176 | if (*j == nullNode) { | 2191 | if (*j == nil) { |
| 2177 | for (auto& item : destruct.items) { | 2192 | for (auto& item : destruct.items) { |
| 2178 | item.structure.clear(); | 2193 | item.structure.clear(); |
| 2179 | } | 2194 | } |
| @@ -3104,8 +3119,8 @@ private: | |||
| 3104 | } | 3119 | } |
| 3105 | } | 3120 | } |
| 3106 | auto info = extractDestructureInfo(assignment, true, false); | 3121 | auto info = extractDestructureInfo(assignment, true, false); |
| 3107 | if (!info.first.empty()) { | 3122 | if (!info.destructures.empty()) { |
| 3108 | for (const auto& destruct : info.first) | 3123 | for (const auto& destruct : info.destructures) |
| 3109 | for (const auto& item : destruct.items) | 3124 | for (const auto& item : destruct.items) |
| 3110 | if (!item.targetVar.empty()) { | 3125 | if (!item.targetVar.empty()) { |
| 3111 | if (std::isupper(item.targetVar[0]) && capital) { capital->decls.push_back(item.targetVar); | 3126 | if (std::isupper(item.targetVar[0]) && capital) { capital->decls.push_back(item.targetVar); |
| @@ -3114,8 +3129,8 @@ private: | |||
| 3114 | } | 3129 | } |
| 3115 | } | 3130 | } |
| 3116 | } | 3131 | } |
| 3117 | if (info.second) { | 3132 | if (info.assignment) { |
| 3118 | auto defs = transformAssignDefs(info.second->expList, DefOp::Get); | 3133 | auto defs = transformAssignDefs(info.assignment->expList, DefOp::Get); |
| 3119 | for (const auto& def : defs) { | 3134 | for (const auto& def : defs) { |
| 3120 | if (std::isupper(def[0]) && capital) { capital->decls.push_back(def); | 3135 | if (std::isupper(def[0]) && capital) { capital->decls.push_back(def); |
| 3121 | } else if (any) { | 3136 | } else if (any) { |
| @@ -3236,6 +3251,49 @@ private: | |||
| 3236 | } | 3251 | } |
| 3237 | } | 3252 | } |
| 3238 | 3253 | ||
| 3254 | std::optional<std::string> getOption(std::string_view key) { | ||
| 3255 | #ifndef YUE_NO_MACRO | ||
| 3256 | if (L) { | ||
| 3257 | int top = lua_gettop(L); | ||
| 3258 | DEFER(lua_settop(L, top)); | ||
| 3259 | pushYue("options"sv); // options | ||
| 3260 | lua_pushlstring(L, &key.front(), key.size()); | ||
| 3261 | lua_gettable(L, -2); | ||
| 3262 | if (lua_isstring(L, -1) != 0) { | ||
| 3263 | size_t size = 0; | ||
| 3264 | const char* str = lua_tolstring(L, -1, &size); | ||
| 3265 | return std::string(str, size); | ||
| 3266 | } | ||
| 3267 | } | ||
| 3268 | #endif // YUE_NO_MACRO | ||
| 3269 | auto it = _config.options.find(std::string(key)); | ||
| 3270 | if (it != _config.options.end()) { | ||
| 3271 | return it->second; | ||
| 3272 | } | ||
| 3273 | return std::nullopt; | ||
| 3274 | } | ||
| 3275 | |||
| 3276 | int getLuaTarget(ast_node* x) { | ||
| 3277 | if (auto target = getOption("target")) { | ||
| 3278 | if (target.value() == "5.1"sv) { | ||
| 3279 | return 501; | ||
| 3280 | } else if (target.value() == "5.2"sv) { | ||
| 3281 | return 502; | ||
| 3282 | } else if (target.value() == "5.3"sv) { | ||
| 3283 | return 503; | ||
| 3284 | } else if (target.value() == "5.4"sv) { | ||
| 3285 | return 504; | ||
| 3286 | } else { | ||
| 3287 | throw std::logic_error(_info.errorMessage("get invalid Lua target \""s + target.value() + "\", should be 5.1, 5.2, 5.3 or 5.4"s, x)); | ||
| 3288 | } | ||
| 3289 | } | ||
| 3290 | #ifndef YUE_NO_MACRO | ||
| 3291 | return LUA_VERSION_NUM; | ||
| 3292 | #else | ||
| 3293 | return 504; | ||
| 3294 | #endif // YUE_NO_MACRO | ||
| 3295 | } | ||
| 3296 | |||
| 3239 | #ifndef YUE_NO_MACRO | 3297 | #ifndef YUE_NO_MACRO |
| 3240 | void passOptions() { | 3298 | void passOptions() { |
| 3241 | if (!_config.options.empty()) { | 3299 | if (!_config.options.empty()) { |
| @@ -5898,8 +5956,8 @@ private: | |||
| 5898 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Mark); | 5956 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Mark); |
| 5899 | varDefs.insert(varDefs.end(), names.begin(), names.end()); | 5957 | varDefs.insert(varDefs.end(), names.begin(), names.end()); |
| 5900 | auto info = extractDestructureInfo(assignment, true, false); | 5958 | auto info = extractDestructureInfo(assignment, true, false); |
| 5901 | if (!info.first.empty()) { | 5959 | if (!info.destructures.empty()) { |
| 5902 | for (const auto& destruct : info.first) | 5960 | for (const auto& destruct : info.destructures) |
| 5903 | for (const auto& item : destruct.items) | 5961 | for (const auto& item : destruct.items) |
| 5904 | if (!item.targetVar.empty() && addToScope(item.targetVar)) | 5962 | if (!item.targetVar.empty() && addToScope(item.targetVar)) |
| 5905 | varDefs.push_back(item.targetVar); | 5963 | varDefs.push_back(item.targetVar); |
| @@ -6329,8 +6387,8 @@ private: | |||
| 6329 | return traversal::Stop; | 6387 | return traversal::Stop; |
| 6330 | } | 6388 | } |
| 6331 | auto info = extractDestructureInfo(assignment, true, false); | 6389 | auto info = extractDestructureInfo(assignment, true, false); |
| 6332 | if (!info.first.empty()) { | 6390 | if (!info.destructures.empty()) { |
| 6333 | for (const auto& destruct : info.first) | 6391 | for (const auto& destruct : info.destructures) |
| 6334 | for (const auto& item : destruct.items) | 6392 | for (const auto& item : destruct.items) |
| 6335 | if (!item.targetVar.empty() && !isDefined(item.targetVar)) | 6393 | if (!item.targetVar.empty() && !isDefined(item.targetVar)) |
| 6336 | return traversal::Stop; | 6394 | return traversal::Stop; |
| @@ -6481,8 +6539,8 @@ private: | |||
| 6481 | transformAssignment(assignment, out); | 6539 | transformAssignment(assignment, out); |
| 6482 | str_list names = transformAssignDefs(expList, DefOp::Get); | 6540 | str_list names = transformAssignDefs(expList, DefOp::Get); |
| 6483 | auto info = extractDestructureInfo(assignment, true, false); | 6541 | auto info = extractDestructureInfo(assignment, true, false); |
| 6484 | if (!info.first.empty()) { | 6542 | if (!info.destructures.empty()) { |
| 6485 | for (const auto& destruct : info.first) | 6543 | for (const auto& destruct : info.destructures) |
| 6486 | for (const auto& item : destruct.items) | 6544 | for (const auto& item : destruct.items) |
| 6487 | if (!item.targetVar.empty()) | 6545 | if (!item.targetVar.empty()) |
| 6488 | names.push_back(item.targetVar); | 6546 | names.push_back(item.targetVar); |
| @@ -6848,6 +6906,7 @@ private: | |||
| 6848 | temp.push_back(indent() + "end"s + nlr(import)); | 6906 | temp.push_back(indent() + "end"s + nlr(import)); |
| 6849 | } | 6907 | } |
| 6850 | out.push_back(join(temp)); | 6908 | out.push_back(join(temp)); |
| 6909 | markDestructureConst(assignment); | ||
| 6851 | } | 6910 | } |
| 6852 | 6911 | ||
| 6853 | std::string moduleNameFrom(ImportLiteral_t* literal) { | 6912 | std::string moduleNameFrom(ImportLiteral_t* literal) { |
| @@ -7013,6 +7072,12 @@ private: | |||
| 7013 | assignment->expList.set(assignList); | 7072 | assignment->expList.set(assignList); |
| 7014 | assignment->action.set(assign); | 7073 | assignment->action.set(assign); |
| 7015 | transformAssignment(assignment, out); | 7074 | transformAssignment(assignment, out); |
| 7075 | if (auto var = ast_cast<Variable_t>(target)) { | ||
| 7076 | auto moduleName = _parser.toString(var); | ||
| 7077 | markVarConst(moduleName); | ||
| 7078 | } else { | ||
| 7079 | markDestructureConst(assignment); | ||
| 7080 | } | ||
| 7016 | } | 7081 | } |
| 7017 | 7082 | ||
| 7018 | void transformImport(Import_t* import, str_list& out) { | 7083 | void transformImport(Import_t* import, str_list& out) { |
| @@ -7191,7 +7256,7 @@ private: | |||
| 7191 | auto info = extractDestructureInfo(assignment, true, false); | 7256 | auto info = extractDestructureInfo(assignment, true, false); |
| 7192 | transformAssignment(assignment, temp, true); | 7257 | transformAssignment(assignment, temp, true); |
| 7193 | str_list conds; | 7258 | str_list conds; |
| 7194 | for (const auto& destruct : info.first) { | 7259 | for (const auto& destruct : info.destructures) { |
| 7195 | for (const auto& item : destruct.items) { | 7260 | for (const auto& item : destruct.items) { |
| 7196 | if (!item.defVal) { | 7261 | if (!item.defVal) { |
| 7197 | transformExp(item.target, conds, ExpUsage::Closure); | 7262 | transformExp(item.target, conds, ExpUsage::Closure); |
| @@ -7334,23 +7399,84 @@ private: | |||
| 7334 | 7399 | ||
| 7335 | void transformLocalAttrib(LocalAttrib_t* localAttrib, str_list& out) { | 7400 | void transformLocalAttrib(LocalAttrib_t* localAttrib, str_list& out) { |
| 7336 | auto x = localAttrib; | 7401 | auto x = localAttrib; |
| 7337 | auto attrib = _parser.toString(localAttrib->attrib); | 7402 | if (x->leftList.size() < x->assign->values.size()) { |
| 7338 | str_list vars; | 7403 | throw std::logic_error(_info.errorMessage("number of right values should not be greater than left values"sv, x->assign->values.front())); |
| 7339 | for (auto name : localAttrib->nameList->names.objects()) { | 7404 | } |
| 7340 | auto var = _parser.toString(name); | 7405 | auto listA = x->new_ptr<NameList_t>(); |
| 7341 | forceAddToScope(var); | 7406 | auto assignA = x->new_ptr<Assign_t>(); |
| 7342 | vars.push_back(var); | 7407 | auto listB = x->new_ptr<ExpList_t>(); |
| 7408 | auto assignB = x->new_ptr<Assign_t>(); | ||
| 7409 | auto i = x->leftList.objects().begin(); | ||
| 7410 | auto ie = x->leftList.objects().end(); | ||
| 7411 | auto j = x->assign->values.objects().begin(); | ||
| 7412 | auto je = x->assign->values.objects().end(); | ||
| 7413 | while (i != ie) { | ||
| 7414 | if (ast_is<Variable_t>(*i)) { | ||
| 7415 | listA->names.push_back(*i); | ||
| 7416 | if (j != je) assignA->values.push_back(*j); | ||
| 7417 | } else { | ||
| 7418 | auto item = *i; | ||
| 7419 | auto value = item->new_ptr<Value_t>(); | ||
| 7420 | switch (item->getId()) { | ||
| 7421 | case id<simple_table_t>(): | ||
| 7422 | value->item.set(item); | ||
| 7423 | break; | ||
| 7424 | case id<TableLit_t>(): { | ||
| 7425 | auto simpleValue = item->new_ptr<SimpleValue_t>(); | ||
| 7426 | simpleValue->value.set(item); | ||
| 7427 | value->item.set(simpleValue); | ||
| 7428 | break; | ||
| 7429 | } | ||
| 7430 | default: YUEE("AST node mismatch", item); break; | ||
| 7431 | } | ||
| 7432 | auto exp = newExp(value, item); | ||
| 7433 | listB->exprs.push_back(exp); | ||
| 7434 | if (j != je) assignB->values.push_back(*j); | ||
| 7435 | } | ||
| 7436 | ++i; | ||
| 7437 | if (j != je) ++j; | ||
| 7343 | } | 7438 | } |
| 7344 | attrib = " <"s + attrib + '>'; | 7439 | if (!listA->names.empty()) { |
| 7345 | for (auto& var : vars) { | 7440 | str_list vars; |
| 7346 | markVarConst(var); | 7441 | for (auto name : listA->names.objects()) { |
| 7347 | var.append(attrib); | 7442 | auto var = _parser.toString(name); |
| 7443 | forceAddToScope(var); | ||
| 7444 | vars.push_back(var); | ||
| 7445 | } | ||
| 7446 | if (getLuaTarget(x) >= 504) { | ||
| 7447 | std::string attrib; | ||
| 7448 | if (localAttrib->attrib.is<const_attrib_t>()) { | ||
| 7449 | attrib = " <const>"s; | ||
| 7450 | } else if (localAttrib->attrib.is<close_attrib_t>()) { | ||
| 7451 | attrib = " <close>"s; | ||
| 7452 | } else { | ||
| 7453 | YUEE("AST node mismatch", localAttrib->attrib); | ||
| 7454 | } | ||
| 7455 | for (auto& var : vars) { | ||
| 7456 | markVarConst(var); | ||
| 7457 | var.append(attrib); | ||
| 7458 | } | ||
| 7459 | } else { | ||
| 7460 | if (localAttrib->attrib.is<close_attrib_t>()) { | ||
| 7461 | throw std::logic_error(_info.errorMessage("close attribute is not available when not targeting Lua 5.4 or higher version"sv, x)); | ||
| 7462 | } | ||
| 7463 | for (auto& var : vars) { | ||
| 7464 | markVarConst(var); | ||
| 7465 | } | ||
| 7466 | } | ||
| 7467 | str_list temp; | ||
| 7468 | for (auto item : assignA->values.objects()) { | ||
| 7469 | transformAssignItem(item, temp); | ||
| 7470 | } | ||
| 7471 | out.push_back(indent() + "local "s + join(vars, ", "sv) + " = "s + join(temp, ", "sv) + nll(x)); | ||
| 7348 | } | 7472 | } |
| 7349 | str_list temp; | 7473 | if (!listB->exprs.empty()) { |
| 7350 | for (auto item : localAttrib->assign->values.objects()) { | 7474 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 7351 | transformAssignItem(item, temp); | 7475 | assignment->expList.set(listB); |
| 7476 | assignment->action.set(assignB); | ||
| 7477 | transformAssignment(assignment, out); | ||
| 7478 | markDestructureConst(assignment); | ||
| 7352 | } | 7479 | } |
| 7353 | out.push_back(indent() + "local "s + join(vars, ", "sv) + " = "s + join(temp, ", "sv) + nll(x)); | ||
| 7354 | } | 7480 | } |
| 7355 | 7481 | ||
| 7356 | void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { | 7482 | void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { |
| @@ -7372,10 +7498,16 @@ private: | |||
| 7372 | } | 7498 | } |
| 7373 | 7499 | ||
| 7374 | void transformLabel(Label_t* label, str_list& out) { | 7500 | void transformLabel(Label_t* label, str_list& out) { |
| 7501 | if (getLuaTarget(label) < 502) { | ||
| 7502 | throw std::logic_error(_info.errorMessage("label statement is not available when not targeting Lua 5.2 or higher version"sv, label)); | ||
| 7503 | } | ||
| 7375 | out.push_back(indent() + "::"s + _parser.toString(label->label) + "::"s + nll(label)); | 7504 | out.push_back(indent() + "::"s + _parser.toString(label->label) + "::"s + nll(label)); |
| 7376 | } | 7505 | } |
| 7377 | 7506 | ||
| 7378 | void transformGoto(Goto_t* gotoNode, str_list& out) { | 7507 | void transformGoto(Goto_t* gotoNode, str_list& out) { |
| 7508 | if (getLuaTarget(gotoNode) < 502) { | ||
| 7509 | throw std::logic_error(_info.errorMessage("goto statement is not available when not targeting Lua 5.2 or higher version"sv, gotoNode)); | ||
| 7510 | } | ||
| 7379 | out.push_back(indent() + "goto "s + _parser.toString(gotoNode->label) + nll(gotoNode)); | 7511 | out.push_back(indent() + "goto "s + _parser.toString(gotoNode->label) + nll(gotoNode)); |
| 7380 | } | 7512 | } |
| 7381 | 7513 | ||
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 66043d3..94ce550 100755 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -11,25 +11,24 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
| 11 | namespace pl = parserlib; | 11 | namespace pl = parserlib; |
| 12 | 12 | ||
| 13 | namespace yue { | 13 | namespace yue { |
| 14 | using namespace std::string_view_literals; | ||
| 15 | 14 | ||
| 16 | std::unordered_set<std::string> LuaKeywords = { | 15 | std::unordered_set<std::string> LuaKeywords = { |
| 17 | "and", "break", "do", "else", "elseif", | 16 | "and"s, "break"s, "do"s, "else"s, "elseif"s, |
| 18 | "end", "false", "for", "function", "goto", | 17 | "end"s, "false"s, "for"s, "function"s, "goto"s, |
| 19 | "if", "in", "local", "nil", "not", | 18 | "if"s, "in"s, "local"s, "nil"s, "not"s, |
| 20 | "or", "repeat", "return", "then", "true", | 19 | "or"s, "repeat"s, "return"s, "then"s, "true"s, |
| 21 | "until", "while" | 20 | "until"s, "while"s |
| 22 | }; | 21 | }; |
| 23 | 22 | ||
| 24 | std::unordered_set<std::string> Keywords = { | 23 | std::unordered_set<std::string> Keywords = { |
| 25 | "and", "break", "do", "else", "elseif", | 24 | "and"s, "break"s, "do"s, "else"s, "elseif"s, |
| 26 | "end", "false", "for", "function", "goto", | 25 | "end"s, "false"s, "for"s, "function"s, "goto"s, |
| 27 | "if", "in", "local", "nil", "not", | 26 | "if"s, "in"s, "local"s, "nil"s, "not"s, |
| 28 | "or", "repeat", "return", "then", "true", | 27 | "or"s, "repeat"s, "return"s, "then"s, "true"s, |
| 29 | "until", "while", // Lua keywords | 28 | "until"s, "while"s, // Lua keywords |
| 30 | "as", "class", "continue", "export", "extends", | 29 | "as"s, "class"s, "continue"s, "export"s, "extends"s, |
| 31 | "from", "global", "import", "macro", "switch", | 30 | "from"s, "global"s, "import"s, "macro"s, "switch"s, |
| 32 | "try", "unless", "using", "when", "with" // Yue keywords | 31 | "try"s, "unless"s, "using"s, "when"s, "with"s // Yue keywords |
| 33 | }; | 32 | }; |
| 34 | 33 | ||
| 35 | YueParser::YueParser() { | 34 | YueParser::YueParser() { |
| @@ -86,7 +85,7 @@ YueParser::YueParser() { | |||
| 86 | if (isValid) { | 85 | if (isValid) { |
| 87 | if (st->buffer == st->moduleName) { | 86 | if (st->buffer == st->moduleName) { |
| 88 | st->moduleFix++; | 87 | st->moduleFix++; |
| 89 | st->moduleName = std::string("_module_"sv) + std::to_string(st->moduleFix); | 88 | st->moduleName = "_module_"s + std::to_string(st->moduleFix); |
| 90 | } | 89 | } |
| 91 | } | 90 | } |
| 92 | st->buffer.clear(); | 91 | st->buffer.clear(); |
| @@ -179,10 +178,15 @@ YueParser::YueParser() { | |||
| 179 | 178 | ||
| 180 | local_flag = expr('*') | expr('^'); | 179 | local_flag = expr('*') | expr('^'); |
| 181 | local_values = NameList >> -(sym('=') >> (TableBlock | ExpListLow)); | 180 | local_values = NameList >> -(sym('=') >> (TableBlock | ExpListLow)); |
| 182 | Attrib = (expr("const") | expr("close")) >> not_(AlphaNum); | ||
| 183 | Local = key("local") >> (Space >> local_flag | local_values); | 181 | Local = key("local") >> (Space >> local_flag | local_values); |
| 184 | 182 | ||
| 185 | LocalAttrib = Attrib >> NameList >> Assign; | 183 | const_attrib = key("const"); |
| 184 | close_attrib = key("close"); | ||
| 185 | local_const_item = (Space >> Variable | simple_table | TableLit); | ||
| 186 | LocalAttrib = ( | ||
| 187 | const_attrib >> Seperator >> local_const_item >> *(sym(',') >> local_const_item) | | ||
| 188 | close_attrib >> Seperator >> Space >> Variable >> *(sym(',') >> Space >> Variable) | ||
| 189 | ) >> Assign; | ||
| 186 | 190 | ||
| 187 | colon_import_name = sym('\\') >> Space >> Variable; | 191 | colon_import_name = sym('\\') >> Space >> Variable; |
| 188 | ImportName = colon_import_name | Space >> Variable; | 192 | ImportName = colon_import_name | Space >> Variable; |
| @@ -754,6 +758,10 @@ std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc | |||
| 754 | ++it; | 758 | ++it; |
| 755 | } | 759 | } |
| 756 | auto line = Converter{}.to_bytes(std::wstring(begin, end)); | 760 | auto line = Converter{}.to_bytes(std::wstring(begin, end)); |
| 761 | while (col < static_cast<int>(line.size()) | ||
| 762 | && (line[col] == ' ' || line[col] == '\t')) { | ||
| 763 | col++; | ||
| 764 | } | ||
| 757 | Utils::replace(line, "\t"sv, " "sv); | 765 | Utils::replace(line, "\t"sv, " "sv); |
| 758 | std::ostringstream buf; | 766 | std::ostringstream buf; |
| 759 | buf << loc->m_begin.m_line << ": "sv << msg << | 767 | buf << loc->m_begin.m_line << ": "sv << msg << |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index b71a67c..b363ad7 100755 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
| @@ -21,6 +21,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
| 21 | #include "yuescript/yue_ast.h" | 21 | #include "yuescript/yue_ast.h" |
| 22 | 22 | ||
| 23 | namespace yue { | 23 | namespace yue { |
| 24 | using namespace std::string_view_literals; | ||
| 25 | using namespace std::string_literals; | ||
| 24 | using namespace parserlib; | 26 | using namespace parserlib; |
| 25 | 27 | ||
| 26 | struct ParseInfo { | 28 | struct ParseInfo { |
| @@ -77,7 +79,7 @@ protected: | |||
| 77 | int exportCount = 0; | 79 | int exportCount = 0; |
| 78 | int moduleFix = 0; | 80 | int moduleFix = 0; |
| 79 | size_t stringOpen = 0; | 81 | size_t stringOpen = 0; |
| 80 | std::string moduleName = "_module_0"; | 82 | std::string moduleName = "_module_0"s; |
| 81 | std::string buffer; | 83 | std::string buffer; |
| 82 | std::stack<int> indents; | 84 | std::stack<int> indents; |
| 83 | std::stack<bool> noDoStack; | 85 | std::stack<bool> noDoStack; |
| @@ -189,6 +191,7 @@ private: | |||
| 189 | rule expo_value; | 191 | rule expo_value; |
| 190 | rule expo_exp; | 192 | rule expo_exp; |
| 191 | rule exp_not_tab; | 193 | rule exp_not_tab; |
| 194 | rule local_const_item; | ||
| 192 | rule empty_line_stop; | 195 | rule empty_line_stop; |
| 193 | rule Line; | 196 | rule Line; |
| 194 | rule Shebang; | 197 | rule Shebang; |
| @@ -209,8 +212,9 @@ private: | |||
| 209 | AST_RULE(NameList) | 212 | AST_RULE(NameList) |
| 210 | AST_RULE(local_flag) | 213 | AST_RULE(local_flag) |
| 211 | AST_RULE(local_values) | 214 | AST_RULE(local_values) |
| 212 | AST_RULE(Attrib) | ||
| 213 | AST_RULE(Local) | 215 | AST_RULE(Local) |
| 216 | AST_RULE(const_attrib) | ||
| 217 | AST_RULE(close_attrib) | ||
| 214 | AST_RULE(LocalAttrib); | 218 | AST_RULE(LocalAttrib); |
| 215 | AST_RULE(colon_import_name) | 219 | AST_RULE(colon_import_name) |
| 216 | AST_RULE(import_literal_inner) | 220 | AST_RULE(import_literal_inner) |
diff --git a/src/yuescript/yuescript.cpp b/src/yuescript/yuescript.cpp index 2e96f16..98e214f 100644 --- a/src/yuescript/yuescript.cpp +++ b/src/yuescript/yuescript.cpp | |||
| @@ -9,6 +9,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
| 9 | #include "yuescript/yue_compiler.h" | 9 | #include "yuescript/yue_compiler.h" |
| 10 | #include "yuescript/yue_parser.h" | 10 | #include "yuescript/yue_parser.h" |
| 11 | 11 | ||
| 12 | using namespace std::string_literals; | ||
| 13 | |||
| 12 | #if defined(YUE_BUILD_AS_DLL) | 14 | #if defined(YUE_BUILD_AS_DLL) |
| 13 | #define YUE_API __declspec(dllexport) | 15 | #define YUE_API __declspec(dllexport) |
| 14 | #else | 16 | #else |
| @@ -25,12 +27,12 @@ static const char yuescriptCodes[] = | |||
| 25 | 27 | ||
| 26 | static void init_yuescript(lua_State* L) { | 28 | static void init_yuescript(lua_State* L) { |
| 27 | if (luaL_loadbuffer(L, yuescriptCodes, sizeof(yuescriptCodes) / sizeof(yuescriptCodes[0]) - 1, "=(yuescript)") != 0) { | 29 | if (luaL_loadbuffer(L, yuescriptCodes, sizeof(yuescriptCodes) / sizeof(yuescriptCodes[0]) - 1, "=(yuescript)") != 0) { |
| 28 | std::string err = std::string("failed to load yuescript module.\n") + lua_tostring(L, -1); | 30 | std::string err = "failed to load yuescript module.\n"s + lua_tostring(L, -1); |
| 29 | luaL_error(L, err.c_str()); | 31 | luaL_error(L, err.c_str()); |
| 30 | } else { | 32 | } else { |
| 31 | lua_insert(L, -2); | 33 | lua_insert(L, -2); |
| 32 | if (lua_pcall(L, 1, 0, 0) != 0) { | 34 | if (lua_pcall(L, 1, 0, 0) != 0) { |
| 33 | std::string err = std::string("failed to init yuescript module.\n") + lua_tostring(L, -1); | 35 | std::string err = "failed to init yuescript module.\n"s + lua_tostring(L, -1); |
| 34 | luaL_error(L, err.c_str()); | 36 | luaL_error(L, err.c_str()); |
| 35 | } | 37 | } |
| 36 | } | 38 | } |
| @@ -41,10 +43,10 @@ static const char stpCodes[] = | |||
| 41 | 43 | ||
| 42 | static int init_stacktraceplus(lua_State* L) { | 44 | static int init_stacktraceplus(lua_State* L) { |
| 43 | if (luaL_loadbuffer(L, stpCodes, sizeof(stpCodes) / sizeof(stpCodes[0]) - 1, "=(stacktraceplus)") != 0) { | 45 | if (luaL_loadbuffer(L, stpCodes, sizeof(stpCodes) / sizeof(stpCodes[0]) - 1, "=(stacktraceplus)") != 0) { |
| 44 | std::string err = std::string("failed to load stacktraceplus module.\n") + lua_tostring(L, -1); | 46 | std::string err = "failed to load stacktraceplus module.\n"s + lua_tostring(L, -1); |
| 45 | luaL_error(L, err.c_str()); | 47 | luaL_error(L, err.c_str()); |
| 46 | } else if (lua_pcall(L, 0, 1, 0) != 0) { | 48 | } else if (lua_pcall(L, 0, 1, 0) != 0) { |
| 47 | std::string err = std::string("failed to init stacktraceplus module.\n") + lua_tostring(L, -1); | 49 | std::string err = "failed to init stacktraceplus module.\n"s + lua_tostring(L, -1); |
| 48 | luaL_error(L, err.c_str()); | 50 | luaL_error(L, err.c_str()); |
| 49 | } | 51 | } |
| 50 | return 1; | 52 | return 1; |
