From 0ccf4408271c8a0d147e3cf25689810862e8c1db Mon Sep 17 00:00:00 2001 From: Li Jin Date: Tue, 24 Feb 2026 12:24:10 +0800 Subject: Cleaned up and fixed more comment reserving codes. --- src/yuescript/ast.hpp | 3 +- src/yuescript/yue_ast.h | 2 +- src/yuescript/yue_compiler.cpp | 240 +++++++++++++++++++++++++---------------- src/yuescript/yue_parser.cpp | 6 +- 4 files changed, 155 insertions(+), 96 deletions(-) (limited to 'src') diff --git a/src/yuescript/ast.hpp b/src/yuescript/ast.hpp index d94caca..b3b0d23 100644 --- a/src/yuescript/ast.hpp +++ b/src/yuescript/ast.hpp @@ -13,6 +13,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND #include #include +#include #include #include #include @@ -34,7 +35,7 @@ class ast; /** type of AST node stack. */ typedef std::vector ast_stack; -typedef std::list node_container; +typedef std::deque node_container; template struct Counter { diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 6919f7a..7d9a4a1 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h @@ -920,7 +920,7 @@ AST_NODE(BreakLoop) ast_sel type; ast_ptr valueList; AST_MEMBER(BreakLoop, &type, &valueList) - std::list vars; + std::deque vars; AST_END(BreakLoop) AST_NODE(PipeBody) diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 7624d81..9f13098 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -65,7 +65,7 @@ namespace yue { + ",\n[Error] "s + msg, \ node) -typedef std::list str_list; +typedef std::deque str_list; static std::unordered_set Metamethods = { "add"s, "sub"s, "mul"s, "div"s, "mod"s, @@ -78,7 +78,7 @@ static std::unordered_set Metamethods = { "close"s // Lua 5.4 }; -const std::string_view version = "0.33.3"sv; +const std::string_view version = "0.33.4"sv; const std::string_view extension = "yue"sv; class CompileError : public std::logic_error { @@ -1749,22 +1749,7 @@ private: out.push_back("\n"s); return; } - str_list temp; - for (auto node : comment->comments.objects()) { - switch (node->get_id()) { - case id(): { - auto content = static_cast(node); - temp.emplace_back(indent() + "--"s + _parser.toString(content)); - break; - } - case id(): { - auto content = static_cast(node); - temp.emplace_back(indent() + "--[["s + _parser.toString(content) + "]]"s); - break; - } - } - } - out.push_back(join(temp, " "sv) + '\n'); + out.push_back(indent() + comment->to_string(&_config) + '\n'); } void transformStatement(Statement_t* statement, str_list& out) { @@ -4477,7 +4462,7 @@ private: for (const auto& arg : vars) { finalArgs.push_back(arg); } - finalArgs.sort(); + std::sort(finalArgs.begin(), finalArgs.end()); for (const auto& arg : *ensureArgListInTheEnd) { finalArgs.push_back(arg); } @@ -4488,7 +4473,7 @@ private: } args = std::move(finalArgs); } else { - args.sort(); + std::sort(args.begin(), args.end()); if (usedVar) { args.push_back("..."s); } @@ -8217,26 +8202,23 @@ private: auto x = values.front(); str_list temp; incIndentOffset(); - auto metatable = x->new_ptr(); - ast_sel metatableItem; - ast_node* lastValueNode = values.back(); - int lastValueLine = x->m_begin.m_line; - bool prevWasEmptyLine = false; - if (!_config.reserveComment) { - for (auto it = values.rbegin(); it != values.rend(); ++it) { - auto node = *it; - if (!ast_is(node)) { - lastValueNode = node; - break; - } - } - } + auto metatable = x->new_ptr(); + struct MetatableItem { + ast_sel item; + std::vector commentOrEmpty; + }; + std::optional metatableItem; + std::vector commentOrEmpty; + std::vector tableItems; for (auto value : values) { - if (!_config.reserveComment && ast_is(value)) { - continue; - } auto item = value; switch (item->get_id()) { + case id(): + case id(): + if (_config.reserveComment) { + commentOrEmpty.emplace_back(item); + } + break; case id(): { auto pair = static_cast(item); if (pair->defVal) { @@ -8278,29 +8260,8 @@ private: break; } } - bool isMetamethod = false; - bool skipComma = false; switch (item->get_id()) { - case id(): transformExp(static_cast(item), temp, ExpUsage::Closure); break; - case id(): { - if (_config.reserveComment && !prevWasEmptyLine && value->m_begin.m_line > lastValueLine + 1) { - temp.emplace_back(Empty); - } - auto comment = static_cast(item); - temp.emplace_back(comment->to_string(&_config)); - skipComma = true; - break; - } - case id(): - temp.emplace_back(Empty); - skipComma = true; - break; - case id(): transform_variable_pair(static_cast(item), temp); break; - case id(): transform_normal_pair(static_cast(item), temp, false); break; - case id(): transformTableBlockIndent(static_cast(item), temp); break; - case id(): transformTableBlock(static_cast(item), temp); break; case id(): { - isMetamethod = true; auto mp = static_cast(item); if (metatableItem) { throw CompileError("too many metatable declarations"sv, mp->name); @@ -8309,11 +8270,16 @@ private: checkMetamethod(name, mp->name); _buf << "__"sv << name << ':' << name; auto newPair = toAst(clearBuf(), item); - metatable->pairs.push_back(newPair); + if (!commentOrEmpty.empty()) { + for (auto c : commentOrEmpty) { + metatable->values.push_back(c); + } + commentOrEmpty.clear(); + } + metatable->values.push_back(newPair); break; } case id(): { - isMetamethod = true; auto mp = static_cast(item); auto newPair = item->new_ptr(); if (mp->key) { @@ -8340,28 +8306,73 @@ private: default: YUEE("AST node mismatch", mp->key); break; } newPair->value.set(mp->value); - metatable->pairs.push_back(newPair); + if (!commentOrEmpty.empty()) { + for (auto c : commentOrEmpty) { + metatable->values.push_back(c); + } + commentOrEmpty.clear(); + } + metatable->values.push_back(newPair); } else { - if (!metatable->pairs.empty()) { + if (!metatable->values.empty()) { throw CompileError("too many metatable declarations"sv, mp->value); } - metatableItem.set(mp->value); + metatableItem = MetatableItem{}; + if (!commentOrEmpty.empty()) { + metatableItem.value().commentOrEmpty = std::move(commentOrEmpty); + } + metatableItem.value().item.set(mp->value); } break; } - default: YUEE("AST node mismatch", item); break; + case id(): + case id(): + break; + default: { + if (!commentOrEmpty.empty()) { + for (auto c : commentOrEmpty) { + tableItems.emplace_back(c); + } + commentOrEmpty.clear(); + } + tableItems.emplace_back(item); + break; + } } - if (!isMetamethod) { - if (skipComma) { - temp.back() = indent() + temp.back() + '\n'; - } else { - temp.back() = indent() + (value == lastValueNode ? temp.back() : temp.back() + ',') + nl(value); + } + + ast_node* lastValueNode = tableItems.empty() ? nullptr : tableItems.back(); + for (auto* item : tableItems) { + bool skipComma = false; + switch (item->get_id()) { + case id(): { + transformExp(static_cast(item), temp, ExpUsage::Closure); + break; + } + case id(): { + auto comment = static_cast(item); + temp.emplace_back(comment->to_string(&_config)); + skipComma = true; + break; + } + case id(): { + temp.emplace_back(Empty); + skipComma = true; + break; } + case id(): transform_variable_pair(static_cast(item), temp); break; + case id(): transform_normal_pair(static_cast(item), temp, false); break; + case id(): transformTableBlockIndent(static_cast(item), temp); break; + case id(): transformTableBlock(static_cast(item), temp); break; + default: YUEE("AST node mismatch", item); break; + } + if (skipComma) { + temp.back() = indent() + temp.back() + '\n'; + } else { + temp.back() = indent() + (item == lastValueNode ? temp.back() : temp.back() + ',') + nl(item); } - lastValueLine = value->m_end.m_line; - prevWasEmptyLine = ast_is(value); } - if (metatable->pairs.empty() && !metatableItem) { + if (metatable->values.empty() && !metatableItem) { out.push_back('{' + nl(x) + join(temp)); decIndentOffset(); out.back() += (indent() + '}'); @@ -8378,17 +8389,28 @@ private: } tabStr += ", "sv; str_list tmp; - if (!metatable->pairs.empty()) { - transform_simple_table(metatable, tmp); - } else - switch (metatableItem->get_id()) { + if (metatableItem) { + if (_config.reserveComment) { + for (auto item : metatableItem.value().commentOrEmpty) { + if (ast_is(item)) { + tmp.push_back("\n"s); + } else { + transformComment(ast_to(item), tmp); + } + } + } + auto mt = metatableItem.value().item.get(); + switch (mt->get_id()) { case id(): - transformExp(static_cast(metatableItem.get()), tmp, ExpUsage::Closure); + transformExp(static_cast(mt), tmp, ExpUsage::Closure); break; case id(): - transformTableBlock(static_cast(metatableItem.get()), tmp); + transformTableBlock(static_cast(mt), tmp); break; } + } else { + transformTableLit(metatable, tmp); + } tabStr += tmp.back(); tabStr += ')'; out.push_back(tabStr); @@ -9817,8 +9839,19 @@ private: str_list classConstVars; if (body) { str_list varDefs; + std::vector commentOrEmpty; for (auto item : body->contents.objects()) { - if (auto statement = ast_cast(item)) { + if (ast_is(item)) { + if (_config.reserveComment) { + commentOrEmpty.emplace_back(item); + } + } else if (auto statement = ast_cast(item)) { + if (!commentOrEmpty.empty()) { + for (auto c : commentOrEmpty) { + block->statementOrComments.push_back(c); + } + commentOrEmpty.clear(); + } ClassDecl_t* clsDecl = nullptr; if (auto assignment = assignmentFrom(statement)) { block->statementOrComments.push_back(statement); @@ -9937,6 +9970,8 @@ private: std::tie(clsName, newDefined, clsTextName) = defineClassVariable(clsDecl->name); if (newDefined) varDefs.push_back(clsName); } + } else { + commentOrEmpty.clear(); } } if (!varDefs.empty()) { @@ -9959,6 +9994,15 @@ private: std::list builtinFields; std::list classFields; std::list commentOrEmpty; + auto appendCommentOrEmpty = [&](std::list& target) { + if (!commentOrEmpty.empty()) { + for (auto& item : commentOrEmpty) { + auto [content, newLine, isComment] = std::move(item); + target.emplace_back(indent(1) + content, newLine, isComment); + } + commentOrEmpty.clear(); + } + }; str_list initStatements; if (body) { std::list members; @@ -9971,18 +10015,19 @@ private: for (; it != members.end(); ++it) { auto& member = *it; if (member.type == MemType::Property) { - initStatements.push_back(indent() + member.item + nl(content)); - } else if (member.type == MemType::Builtin) { if (!commentOrEmpty.empty()) { - builtinFields.insert(builtinFields.end(), commentOrEmpty.begin(), commentOrEmpty.end()); + for (auto& item : commentOrEmpty) { + auto [content, newLine, _] = std::move(item); + initStatements.emplace_back(indent() + content + newLine); + } commentOrEmpty.clear(); } + initStatements.emplace_back(indent() + member.item + nl(content)); + } else if (member.type == MemType::Builtin) { + appendCommentOrEmpty(builtinFields); builtinFields.emplace_back(indent(1) + member.item, nl(member.node), false); } else { - if (!commentOrEmpty.empty()) { - classFields.insert(classFields.end(), commentOrEmpty.begin(), commentOrEmpty.end()); - commentOrEmpty.clear(); - } + appendCommentOrEmpty(classFields); classFields.emplace_back(indent(1) + member.item, nl(member.node), false); } } @@ -9991,7 +10036,7 @@ private: case id(): { if (_config.reserveComment) { auto comment = static_cast(content); - commentOrEmpty.emplace_back(indent(1) + comment->to_string(&_config), "\n"s, true); + commentOrEmpty.emplace_back(comment->to_string(&_config), "\n"s, true); } break; } @@ -10001,8 +10046,10 @@ private: } break; } - case id(): + case id(): { + commentOrEmpty.clear(); break; + } default: YUEE("AST node mismatch", content); break; } } @@ -10010,9 +10057,20 @@ private: forceAddToScope(classVar); } forceAddToScope("self"s); - for (auto stmt_ : block->statementOrComments.objects()) { - if (auto stmt = ast_cast(stmt_)) { - transformStatement(stmt, initStatements); + for (auto s : block->statementOrComments.objects()) { + switch (s->get_id()) { + case id(): + transformStatement(static_cast(s), initStatements); + break; + case id(): + initStatements.push_back("\n"s); + break; + case id(): + transformComment(static_cast(s), initStatements); + break; + default: + YUEE("AST node mismatch", s); + break; } } if (!classFields.empty()) { diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 421acee..7ea2c97 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -905,7 +905,7 @@ YueParser::YueParser() { white >> '}' ); - table_block_inner = Seperator >> key_value_line >> *(+plain_space_break >> key_value_line); + table_block_inner = Seperator >> key_value_line >> *(line_break >> key_value_line); TableBlock = +plain_space_break >> advance_match >> ensure(table_block_inner, pop_indent); TableBlockIndent = ('*' | '-' >> space_one) >> Seperator >> disable_arg_table_block_rule( space >> key_value_list >> -(space >> ',') >> @@ -916,7 +916,7 @@ YueParser::YueParser() { ClassBlock = +plain_space_break >> advance_match >> Seperator >> - class_line >> *(+plain_space_break >> class_line) >> + class_line >> *(line_break >> class_line) >> pop_indent; ClassDecl = @@ -1007,7 +1007,7 @@ YueParser::YueParser() { MetaNormalPairDef = MetaNormalPair >> destruct_def; NormalDef = Exp >> Seperator >> destruct_def; - yue_comment_block = -EmptyLine >> YueComment >> *(line_break >> -EmptyLine >> YueComment) >> line_break; + yue_comment_block = -EmptyLine >> YueComment >> *(line_break >> -EmptyLine >> YueComment) >> line_break >> -EmptyLine | EmptyLine; key_value = VariablePair | -- cgit v1.2.3-55-g6feb