diff options
| author | Li Jin <dragon-fly@qq.com> | 2025-01-31 01:02:59 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2025-01-31 01:02:59 +0800 |
| commit | f5c1735262f07f8064575bebec8b593559abe619 (patch) | |
| tree | c0e3d660e647843c37df451e4028ec5590edb8e2 /src | |
| parent | cf91f61990babdd8a80774809e9e860a155e4201 (diff) | |
| download | yuescript-f5c1735262f07f8064575bebec8b593559abe619.tar.gz yuescript-f5c1735262f07f8064575bebec8b593559abe619.tar.bz2 yuescript-f5c1735262f07f8064575bebec8b593559abe619.zip | |
Fixing issue #178.
Diffstat (limited to 'src')
| -rw-r--r-- | src/yuescript/yue_ast.cpp | 3 | ||||
| -rw-r--r-- | src/yuescript/yue_ast.h | 6 | ||||
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 86 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.cpp | 2 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.h | 1 |
5 files changed, 70 insertions, 28 deletions
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp index 3dac699..fe6e726 100644 --- a/src/yuescript/yue_ast.cpp +++ b/src/yuescript/yue_ast.cpp | |||
| @@ -167,6 +167,9 @@ std::string ExistentialOp_t::to_string(void*) const { | |||
| 167 | std::string TableAppendingOp_t::to_string(void*) const { | 167 | std::string TableAppendingOp_t::to_string(void*) const { |
| 168 | return "[]"s; | 168 | return "[]"s; |
| 169 | } | 169 | } |
| 170 | std::string PlainItem_t::to_string(void *) const { | ||
| 171 | return {}; | ||
| 172 | } | ||
| 170 | std::string GlobalOp_t::to_string(void* ud) const { | 173 | std::string GlobalOp_t::to_string(void* ud) const { |
| 171 | auto info = reinterpret_cast<YueFormat*>(ud); | 174 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 172 | return info->convert(this); | 175 | return info->convert(this); |
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 139f4b3..e670126 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
| @@ -635,9 +635,13 @@ AST_END(ExistentialOp) | |||
| 635 | AST_LEAF(TableAppendingOp) | 635 | AST_LEAF(TableAppendingOp) |
| 636 | AST_END(TableAppendingOp) | 636 | AST_END(TableAppendingOp) |
| 637 | 637 | ||
| 638 | AST_LEAF(PlainItem) | ||
| 639 | AST_END(PlainItem) | ||
| 640 | |||
| 638 | AST_NODE(ChainValue) | 641 | AST_NODE(ChainValue) |
| 639 | ast_ptr<true, Seperator_t> sep; | 642 | ast_ptr<true, Seperator_t> sep; |
| 640 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, ExistentialOp_t, TableAppendingOp_t> items; | 643 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, ExistentialOp_t, TableAppendingOp_t, |
| 644 | /*non-syntax-rule*/ PlainItem_t> items; | ||
| 641 | AST_MEMBER(ChainValue, &sep, &items) | 645 | AST_MEMBER(ChainValue, &sep, &items) |
| 642 | AST_END(ChainValue) | 646 | AST_END(ChainValue) |
| 643 | 647 | ||
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 369f7e8..446414d 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -24,6 +24,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
| 24 | 24 | ||
| 25 | extern "C" { | 25 | extern "C" { |
| 26 | #include "lauxlib.h" | 26 | #include "lauxlib.h" |
| 27 | #include "lparser.h" | ||
| 27 | #include "lua.h" | 28 | #include "lua.h" |
| 28 | #include "lualib.h" | 29 | #include "lualib.h" |
| 29 | } // extern "C" | 30 | } // extern "C" |
| @@ -6272,6 +6273,9 @@ private: | |||
| 6272 | case id<TableAppendingOp_t>(): | 6273 | case id<TableAppendingOp_t>(): |
| 6273 | transform_table_appending_op(static_cast<TableAppendingOp_t*>(item), temp); | 6274 | transform_table_appending_op(static_cast<TableAppendingOp_t*>(item), temp); |
| 6274 | break; | 6275 | break; |
| 6276 | case id<PlainItem_t>(): | ||
| 6277 | temp.push_back(_parser.toString(item)); | ||
| 6278 | break; | ||
| 6275 | default: YUEE("AST node mismatch", item); break; | 6279 | default: YUEE("AST node mismatch", item); break; |
| 6276 | } | 6280 | } |
| 6277 | } | 6281 | } |
| @@ -6519,24 +6523,26 @@ private: | |||
| 6519 | throw CompileError("macro table must contain field \"type\" of value \"lua\" or \"text\""sv, x); | 6523 | throw CompileError("macro table must contain field \"type\" of value \"lua\" or \"text\""sv, x); |
| 6520 | } | 6524 | } |
| 6521 | lua_pop(L, 1); // cur tab | 6525 | lua_pop(L, 1); // cur tab |
| 6522 | lua_getfield(L, -1, "locals"); // cur tab locals | 6526 | if (type == "text"sv) { |
| 6523 | if (lua_istable(L, -1) != 0) { | 6527 | lua_getfield(L, -1, "locals"); // cur tab locals |
| 6524 | for (int i = 0; i < static_cast<int>(lua_objlen(L, -1)); i++) { | 6528 | if (lua_istable(L, -1) != 0) { |
| 6525 | lua_rawgeti(L, -1, i + 1); // cur tab locals item | 6529 | for (int i = 0; i < static_cast<int>(lua_objlen(L, -1)); i++) { |
| 6526 | size_t len = 0; | 6530 | lua_rawgeti(L, -1, i + 1); // cur tab locals item |
| 6527 | if (lua_isstring(L, -1) == 0) { | 6531 | size_t len = 0; |
| 6528 | throw CompileError("macro table field \"locals\" must be a table of strings"sv, x); | 6532 | if (lua_isstring(L, -1) == 0) { |
| 6529 | } | 6533 | throw CompileError("macro table field \"locals\" must be a table of strings"sv, x); |
| 6530 | auto name = lua_tolstring(L, -1, &len); | 6534 | } |
| 6531 | if (auto varNode = toAst<Variable_t>({name, len}, x)) { | 6535 | auto name = lua_tolstring(L, -1, &len); |
| 6532 | localVars.push_back(variableToString(varNode)); | 6536 | if (auto varNode = toAst<Variable_t>({name, len}, x)) { |
| 6533 | } else { | 6537 | localVars.push_back(variableToString(varNode)); |
| 6534 | throw CompileError("macro table field \"locals\" must contain names for local variables, got \""s + std::string(name, len) + '"', x); | 6538 | } else { |
| 6539 | throw CompileError("macro table field \"locals\" must contain names for local variables, got \""s + std::string(name, len) + '"', x); | ||
| 6540 | } | ||
| 6541 | lua_pop(L, 1); // cur tab locals | ||
| 6535 | } | 6542 | } |
| 6536 | lua_pop(L, 1); // cur tab locals | ||
| 6537 | } | 6543 | } |
| 6544 | lua_pop(L, 1); // cur tab | ||
| 6538 | } | 6545 | } |
| 6539 | lua_pop(L, 1); // cur tab | ||
| 6540 | } else { // cur code | 6546 | } else { // cur code |
| 6541 | codes = lua_tostring(L, -1); | 6547 | codes = lua_tostring(L, -1); |
| 6542 | } | 6548 | } |
| @@ -6554,23 +6560,49 @@ private: | |||
| 6554 | bool isBlock = (usage == ExpUsage::Common) && (chainList.size() < 2 || (chainList.size() == 2 && ast_is<Invoke_t, InvokeArgs_t>(chainList.back()))); | 6560 | bool isBlock = (usage == ExpUsage::Common) && (chainList.size() < 2 || (chainList.size() == 2 && ast_is<Invoke_t, InvokeArgs_t>(chainList.back()))); |
| 6555 | ParseInfo info; | 6561 | ParseInfo info; |
| 6556 | if (type == "lua"sv) { | 6562 | if (type == "lua"sv) { |
| 6557 | if (!isBlock) { | ||
| 6558 | throw CompileError("lua macro can only be placed where block macro is allowed"sv, x); | ||
| 6559 | } | ||
| 6560 | auto macroChunk = "=(macro "s + _parser.toString(x->name) + ')'; | 6563 | auto macroChunk = "=(macro "s + _parser.toString(x->name) + ')'; |
| 6561 | int top = lua_gettop(L); | 6564 | int top = lua_gettop(L); |
| 6562 | DEFER(lua_settop(L, top)); | 6565 | DEFER(lua_settop(L, top)); |
| 6563 | if (luaL_loadbuffer(L, codes.c_str(), codes.size(), macroChunk.c_str()) != 0) { | 6566 | if (isBlock) { |
| 6564 | std::string err = lua_tostring(L, -1); | 6567 | if (luaL_loadbuffer(L, codes.c_str(), codes.size(), macroChunk.c_str()) != 0) { |
| 6565 | throw CompileError(err, x); | 6568 | std::string err = lua_tostring(L, -1); |
| 6566 | } | 6569 | throw CompileError("lua macro is not expanding to valid block\n"s + err, x); |
| 6567 | if (!codes.empty()) { | 6570 | } else { |
| 6568 | if (_config.reserveLineNumber) { | 6571 | Proto* f = ((LClosure*)lua_topointer(L, -1))->p; |
| 6569 | codes.insert(0, nll(chainValue).substr(1)); | 6572 | for (int i = 0; i < f->sizelocvars; i++) { |
| 6573 | localVars.push_back(getstr(f->locvars[i].varname)); | ||
| 6574 | } | ||
| 6575 | } | ||
| 6576 | if (!codes.empty()) { | ||
| 6577 | if (_config.reserveLineNumber) { | ||
| 6578 | codes.insert(0, nll(chainValue).substr(1)); | ||
| 6579 | } | ||
| 6580 | codes.append(nlr(chainValue)); | ||
| 6570 | } | 6581 | } |
| 6571 | codes.append(nlr(chainValue)); | 6582 | return {nullptr, nullptr, std::move(codes), std::move(localVars)}; |
| 6583 | } else { | ||
| 6584 | auto expCode = "return ("s + codes + ')'; | ||
| 6585 | if (luaL_loadbuffer(L, expCode.c_str(), expCode.size(), macroChunk.c_str()) != 0) { | ||
| 6586 | std::string err = lua_tostring(L, -1); | ||
| 6587 | throw CompileError("lua macro is not expanding to valid expression\n"s + err, x); | ||
| 6588 | } | ||
| 6589 | Utils::trim(codes); | ||
| 6590 | codes = '(' + codes + ')'; | ||
| 6591 | auto plainItem = toAst<PlainItem_t>(codes, x); | ||
| 6592 | auto newChain = x->new_ptr<ChainValue_t>(); | ||
| 6593 | newChain->items.push_back(plainItem); | ||
| 6594 | ast_ptr<false, ast_node> exp; | ||
| 6595 | exp.set(newExp(newChain, x)); | ||
| 6596 | if (chainList.size() > 2 || (chainList.size() == 2 && !ast_is<Invoke_t, InvokeArgs_t>(chainList.back()))) { | ||
| 6597 | auto it = chainList.begin(); | ||
| 6598 | it++; | ||
| 6599 | if (chainList.size() > 1 && ast_is<Invoke_t, InvokeArgs_t>(*it)) it++; | ||
| 6600 | for (; it != chainList.end(); ++it) { | ||
| 6601 | newChain->items.push_back(*it); | ||
| 6602 | } | ||
| 6603 | } | ||
| 6604 | return {exp, nullptr, Empty, std::move(localVars)}; | ||
| 6572 | } | 6605 | } |
| 6573 | return {nullptr, nullptr, std::move(codes), std::move(localVars)}; | ||
| 6574 | } else if (type == "text"sv) { | 6606 | } else if (type == "text"sv) { |
| 6575 | if (!isBlock) { | 6607 | if (!isBlock) { |
| 6576 | throw CompileError("text macro can only be placed where block macro is allowed"sv, x); | 6608 | throw CompileError("text macro can only be placed where block macro is allowed"sv, x); |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index ef242ea..5993ed5 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -653,6 +653,8 @@ YueParser::YueParser() { | |||
| 653 | 653 | ||
| 654 | ExistentialOp = '?' >> not_('?'); | 654 | ExistentialOp = '?' >> not_('?'); |
| 655 | TableAppendingOp = and_('[') >> ("[]" | brackets_expression_error); | 655 | TableAppendingOp = and_('[') >> ("[]" | brackets_expression_error); |
| 656 | PlainItem = +any_char; | ||
| 657 | |||
| 656 | chain_call = ( | 658 | chain_call = ( |
| 657 | Callable >> -ExistentialOp >> -chain_items | 659 | Callable >> -ExistentialOp >> -chain_items |
| 658 | ) | ( | 660 | ) | ( |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index f18cc1b..02292e1 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
| @@ -381,6 +381,7 @@ private: | |||
| 381 | AST_RULE(Invoke); | 381 | AST_RULE(Invoke); |
| 382 | AST_RULE(ExistentialOp); | 382 | AST_RULE(ExistentialOp); |
| 383 | AST_RULE(TableAppendingOp); | 383 | AST_RULE(TableAppendingOp); |
| 384 | AST_RULE(PlainItem); | ||
| 384 | AST_RULE(SpreadExp); | 385 | AST_RULE(SpreadExp); |
| 385 | AST_RULE(SpreadListExp); | 386 | AST_RULE(SpreadListExp); |
| 386 | AST_RULE(TableLit); | 387 | AST_RULE(TableLit); |
