From 8acb48264d3ae87e5cdae2fea4207be22cf08a97 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Mon, 8 Mar 2021 21:02:05 +0800 Subject: add new syntax for issue #41. fix a issue for destructure syntax with TableBlock. try fix luarocks installing problem again for issue #42. --- src/yuescript/ast.hpp | 2 +- src/yuescript/yue_ast.h | 2 +- src/yuescript/yue_compiler.cpp | 188 ++++++++++++++++++++++++++--------------- src/yuescript/yue_parser.cpp | 4 +- 4 files changed, 124 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/yuescript/ast.hpp b/src/yuescript/ast.hpp index eb5cd69..162a82e 100644 --- a/src/yuescript/ast.hpp +++ b/src/yuescript/ast.hpp @@ -420,7 +420,7 @@ public: return false; } - const node_container& objects() const { + const node_container& objects() const { return m_objects; } diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index b673eb3..96968c9 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h @@ -431,7 +431,7 @@ AST_NODE(meta_variable_pair) AST_END(meta_variable_pair) AST_NODE(meta_normal_pair) - ast_sel key; + ast_sel key; ast_sel value; AST_MEMBER(meta_normal_pair, &key, &value) AST_END(meta_normal_pair) diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index a958462..e8d028d 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -59,7 +59,7 @@ inline std::string s(std::string_view sv) { return std::string(sv); } -const std::string_view version = "0.7.1"sv; +const std::string_view version = "0.7.2"sv; const std::string_view extension = "yue"sv; class YueCompilerImpl { @@ -1366,19 +1366,32 @@ private: std::list destructFromExp(ast_node* node) { const node_container* tableItems = nullptr; - if (ast_is(node)) { - auto item = singleValueFrom(node)->item.get(); - if (!item) throw std::logic_error(_info.errorMessage("invalid destructure value"sv, node)); - auto tbA = item->getByPath(); - if (tbA) { - tableItems = &tbA->values.objects(); - } else { - auto tbB = ast_cast(item); - if (tbB) tableItems = &tbB->pairs.objects(); + switch (node->getId()) { + case id(): { + auto item = singleValueFrom(node)->item.get(); + if (!item) throw std::logic_error(_info.errorMessage("invalid destructure value"sv, node)); + auto tbA = item->getByPath(); + if (tbA) { + tableItems = &tbA->values.objects(); + } else { + auto tbB = ast_cast(item); + if (tbB) tableItems = &tbB->pairs.objects(); + } + break; + } + case id(): { + auto table = ast_cast(node); + tableItems = &table->values.objects(); + break; } - } else if (auto table = ast_cast(node)) { - tableItems = &table->values.objects(); + case id(): { + auto table = ast_cast(node); + tableItems = &table->values.objects(); + break; + } + default: YUEE("AST node mismatch", node); break; } + if (!tableItems) throw std::logic_error(_info.errorMessage("invalid destructure value"sv, node)); std::list pairs; int index = 0; for (auto pair : *tableItems) { @@ -1412,7 +1425,7 @@ private: pairs.push_back({ isVariable, varName, - s("["sv) + std::to_string(index) + s("]"sv) + '[' + std::to_string(index) + ']' }); } break; @@ -1429,23 +1442,29 @@ private: } case id(): { auto np = static_cast(pair); - auto key = np->key->getByPath(); - if (!key) throw std::logic_error(_info.errorMessage("invalid key for destructure"sv, np)); + std::string keyName; + if (np->key) { + auto key = np->key->getByPath(); + if (!key) throw std::logic_error(_info.errorMessage("invalid key for destructure"sv, np)); + keyName = _parser.toString(key); + if (Keywords.find(keyName) != Keywords.end()) { + keyName = s("[\""sv) + keyName + s("\"]"sv); + } else { + keyName = s("."sv) + keyName; + } + } if (auto exp = np->value.as()) { if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp)); auto item = singleValueFrom(exp)->item.get(); if (ast_is(item) || item->getByPath()) { auto subPairs = destructFromExp(exp); - auto name = _parser.toString(key); for (auto& p : subPairs) { - if (Keywords.find(name) != Keywords.end()) { - pairs.push_back({p.isVariable, p.name, - s("[\""sv) + name + s("\"]"sv) + p.structure}); - } else { - pairs.push_back({p.isVariable, p.name, - s("."sv) + name + p.structure}); - } + pairs.push_back({ + p.isVariable, + p.name, + keyName + p.structure + }); } } else { bool lintGlobal = _config.lintGlobalVariable; @@ -1458,32 +1477,39 @@ private: varName = std::move(temp.back()); } _config.lintGlobalVariable = lintGlobal; - auto name = _parser.toString(key); - if (Keywords.find(name) != Keywords.end()) { - pairs.push_back({ - isVariable, - varName, - s("[\""sv) + name + s("\"]"sv) - }); - } else { - pairs.push_back({ - isVariable, - varName, - s("."sv) + name - }); - } + pairs.push_back({ + isVariable, + varName, + keyName + }); } break; } if (np->value.is()) { - auto subPairs = destructFromExp(pair); + auto subPairs = destructFromExp(np->value); for (auto& p : subPairs) { - pairs.push_back({p.isVariable, p.name, - s("."sv) + _parser.toString(key) + p.structure}); + pairs.push_back({ + p.isVariable, + p.name, + keyName + p.structure + }); } } break; } + case id(): { + auto tb = static_cast(pair); + ++index; + auto subPairs = destructFromExp(tb); + for (auto& p : subPairs) { + pairs.push_back({ + p.isVariable, + p.name, + '[' + std::to_string(index) + ']' + p.structure + }); + } + break; + } default: YUEE("AST node mismatch", pair); break; } } @@ -1498,9 +1524,10 @@ private: auto exprs = assignment->expList->exprs.objects(); auto values = assignment->action.to()->values.objects(); size_t size = std::max(exprs.size(), values.size()); - ast_ptr var; + ast_list cache; if (exprs.size() < size) { - var = toAst("_"sv, x); + auto var = toAst("_"sv, x); + cache.push_back(var); while (exprs.size() < size) exprs.emplace_back(var); } ast_ptr nullNode; @@ -1551,18 +1578,20 @@ private: case id(): { auto mp = static_cast(item); auto newPair = item->new_ptr(); - switch (mp->key->getId()) { - case id(): { - auto key = _parser.toString(mp->key); - _buf << "__"sv << key; - auto newKey = toAst(clearBuf(), mp->key); - newPair->key.set(newKey); - break; + if (mp->key) { + switch (mp->key->getId()) { + case id(): { + auto key = _parser.toString(mp->key); + _buf << "__"sv << key; + auto newKey = toAst(clearBuf(), mp->key); + newPair->key.set(newKey); + break; + } + case id(): + newPair->key.set(mp->key); + break; + default: YUEE("AST node mismatch", mp->key); break; } - case id(): - newPair->key.set(mp->key); - break; - default: YUEE("AST node mismatch", mp->key); break; } newPair->value.set(mp->value); subMetaDestruct->values.push_back(newPair); @@ -5150,6 +5179,7 @@ private: str_list temp; incIndentOffset(); auto metatable = table->new_ptr(); + ast_sel metatableItem; for (auto pair : pairs) { bool isMetamethod = false; switch (pair->getId()) { @@ -5161,6 +5191,9 @@ private: case id(): { isMetamethod = true; auto mp = static_cast(pair); + if (metatableItem) { + throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->name)); + } auto name = _parser.toString(mp->name); _buf << "__"sv << name << ':' << name; auto newPair = toAst(clearBuf(), pair); @@ -5171,21 +5204,31 @@ private: isMetamethod = true; auto mp = static_cast(pair); auto newPair = pair->new_ptr(); - switch (mp->key->getId()) { - case id(): { - auto key = _parser.toString(mp->key); - _buf << "__"sv << key; - auto newKey = toAst(clearBuf(), mp->key); - newPair->key.set(newKey); - break; + if (mp->key) { + if (metatableItem) { + throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->key)); } - case id(): - newPair->key.set(mp->key); - break; - default: YUEE("AST node mismatch", mp->key); break; + switch (mp->key->getId()) { + case id(): { + auto key = _parser.toString(mp->key); + _buf << "__"sv << key; + auto newKey = toAst(clearBuf(), mp->key); + newPair->key.set(newKey); + break; + } + case id(): + newPair->key.set(mp->key); + break; + default: YUEE("AST node mismatch", mp->key); break; + } + newPair->value.set(mp->value); + metatable->pairs.push_back(newPair); + } else { + if (!metatable->pairs.empty()) { + throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->value)); + } + metatableItem.set(mp->value); } - newPair->value.set(mp->value); - metatable->pairs.push_back(newPair); break; } default: YUEE("AST node mismatch", pair); break; @@ -5194,7 +5237,7 @@ private: temp.back() = indent() + temp.back() + (pair == pairs.back() ? Empty : s(","sv)) + nll(pair); } } - if (metatable->pairs.empty()) { + if (metatable->pairs.empty() && !metatableItem) { out.push_back(s("{"sv) + nll(table) + join(temp)); decIndentOffset(); out.back() += (indent() + s("}"sv)); @@ -5211,7 +5254,16 @@ private: } tabStr += ", "sv; str_list tmp; - transform_simple_table(metatable, tmp); + if (!metatable->pairs.empty()) { + transform_simple_table(metatable, tmp); + } else switch (metatableItem->getId()) { + case id(): + transformExp(static_cast(metatableItem.get()), tmp, ExpUsage::Closure); + break; + case id(): + transformTableBlock(static_cast(metatableItem.get()), tmp); + break; + } tabStr += tmp.back(); tabStr += s(")"sv); out.push_back(tabStr); diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index ec6c997..2234a59 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -328,7 +328,7 @@ YueParser::YueParser() { unary_operator = expr('-') >> not_(set(">=") | space_one) | - expr('#') | + expr('#') >> not_(':') | expr('~') >> not_(expr('=') | space_one) | expr("not") >> not_(AlphaNum); unary_exp = *(Space >> unary_operator) >> expo_exp; @@ -525,7 +525,7 @@ YueParser::YueParser() { meta_variable_pair = sym(':') >> Variable >> expr('#'); - meta_normal_pair = (Space >> Name | sym('[') >> Exp >> sym(']')) >> expr("#:") >> + meta_normal_pair = Space >> -(Name | symx('[') >> Exp >> sym(']')) >> expr("#:") >> (Exp | TableBlock | +(SpaceBreak) >> Exp); KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair; -- cgit v1.2.3-55-g6feb