aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2026-04-23 17:04:06 +0800
committerLi Jin <dragon-fly@qq.com>2026-04-23 17:04:06 +0800
commitacb80dec2706359027c0461073aded3420eaec56 (patch)
treede4e3393e6af6911f1e292fa2a4677e788062f04 /src
parent7805872d0a1705fa2fc296b6c37a40f675a39591 (diff)
downloadyuescript-acb80dec2706359027c0461073aded3420eaec56.tar.gz
yuescript-acb80dec2706359027c0461073aded3420eaec56.tar.bz2
yuescript-acb80dec2706359027c0461073aded3420eaec56.zip
Add annotation statements and expand annotation tests
Diffstat (limited to 'src')
-rw-r--r--src/yuescript/yue_ast.cpp3
-rw-r--r--src/yuescript/yue_ast.h9
-rw-r--r--src/yuescript/yue_compiler.cpp114
-rw-r--r--src/yuescript/yue_parser.cpp4
-rw-r--r--src/yuescript/yue_parser.h1
5 files changed, 105 insertions, 26 deletions
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp
index e5f8d12..23f3820 100644
--- a/src/yuescript/yue_ast.cpp
+++ b/src/yuescript/yue_ast.cpp
@@ -1530,6 +1530,9 @@ std::string MacroFunc_t::to_string(void* ud) const {
1530std::string Macro_t::to_string(void* ud) const { 1530std::string Macro_t::to_string(void* ud) const {
1531 return "macro "s + name->to_string(ud) + " = "s + decl->to_string(ud); 1531 return "macro "s + name->to_string(ud) + " = "s + decl->to_string(ud);
1532} 1532}
1533std::string Annotation_t::to_string(void* ud) const {
1534 return "$["s + name->to_string(ud) + (invoke ? invoke->to_string(ud) : ""s) + "]"s;
1535}
1533std::string MacroInPlace_t::to_string(void* ud) const { 1536std::string MacroInPlace_t::to_string(void* ud) const {
1534 auto info = reinterpret_cast<YueFormat*>(ud); 1537 auto info = reinterpret_cast<YueFormat*>(ud);
1535 auto line = "$ ->"s; 1538 auto line = "$ ->"s;
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index 7d9a4a1..65568af 100644
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -853,6 +853,12 @@ AST_NODE(Macro)
853 AST_MEMBER(Macro, &name, &decl) 853 AST_MEMBER(Macro, &name, &decl)
854AST_END(Macro) 854AST_END(Macro)
855 855
856AST_NODE(Annotation)
857 ast_ptr<true, UnicodeName_t> name;
858 ast_sel<false, Invoke_t, InvokeArgs_t> invoke;
859 AST_MEMBER(Annotation, &name, &invoke)
860AST_END(Annotation)
861
856AST_NODE(NameOrDestructure) 862AST_NODE(NameOrDestructure)
857 ast_sel<true, Variable_t, SimpleTable_t, TableLit_t, Comprehension_t> item; 863 ast_sel<true, Variable_t, SimpleTable_t, TableLit_t, Comprehension_t> item;
858 AST_MEMBER(NameOrDestructure, &item) 864 AST_MEMBER(NameOrDestructure, &item)
@@ -961,7 +967,8 @@ AST_END(ChainAssign)
961AST_NODE(Statement) 967AST_NODE(Statement)
962 ast_sel<true, 968 ast_sel<true,
963 Import_t, While_t, Repeat_t, For_t, 969 Import_t, While_t, Repeat_t, For_t,
964 Return_t, Local_t, Global_t, Export_t, Macro_t, MacroInPlace_t, 970 Return_t, Local_t, Global_t, Export_t,
971 Macro_t, MacroInPlace_t, Annotation_t,
965 BreakLoop_t, Label_t, Goto_t, ShortTabAppending_t, 972 BreakLoop_t, Label_t, Goto_t, ShortTabAppending_t,
966 Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t, ChainAssign_t 973 Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t, ChainAssign_t
967 > content; 974 > content;
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 76d6b0f..844d61e 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -78,7 +78,7 @@ static std::unordered_set<std::string> Metamethods = {
78 "close"s // Lua 5.4 78 "close"s // Lua 5.4
79}; 79};
80 80
81const std::string_view version = "0.33.10"sv; 81const std::string_view version = "0.34.0"sv;
82const std::string_view extension = "yue"sv; 82const std::string_view extension = "yue"sv;
83 83
84class CompileError : public std::logic_error { 84class CompileError : public std::logic_error {
@@ -5386,7 +5386,8 @@ private:
5386 if (!nodes.empty()) { 5386 if (!nodes.empty()) {
5387 str_list temp; 5387 str_list temp;
5388 auto lastStmt = lastStatementFrom(nodes); 5388 auto lastStmt = lastStatementFrom(nodes);
5389 for (auto node : nodes) { 5389 for (auto nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt) {
5390 auto node = *nodeIt;
5390 if (auto comment = ast_cast<YueComment_t>(node)) { 5391 if (auto comment = ast_cast<YueComment_t>(node)) {
5391 transformComment(comment, temp); 5392 transformComment(comment, temp);
5392 continue; 5393 continue;
@@ -5398,7 +5399,8 @@ private:
5398 } else if (!ast_is<Statement_t>(node)) { 5399 } else if (!ast_is<Statement_t>(node)) {
5399 continue; 5400 continue;
5400 } 5401 }
5401 auto transformNode = [&]() { 5402 std::function<void()> transformNode;
5403 transformNode = [&]() {
5402 currentScope().lastStatement = (node == lastStmt) && currentScope().mode == GlobalMode::None; 5404 currentScope().lastStatement = (node == lastStmt) && currentScope().mode == GlobalMode::None;
5403 auto stmt = static_cast<Statement_t*>(node); 5405 auto stmt = static_cast<Statement_t*>(node);
5404 if (auto importNode = stmt->content.as<Import_t>(); 5406 if (auto importNode = stmt->content.as<Import_t>();
@@ -5418,6 +5420,56 @@ private:
5418 _importedGlobal->importContent = importNode->content.get(); 5420 _importedGlobal->importContent = importNode->content.get();
5419 } 5421 }
5420 } 5422 }
5423 } else if (auto annotation = stmt->content.as<Annotation_t>()) {
5424#ifndef YUE_NO_MACRO
5425 auto next = nodeIt;
5426 ++next;
5427 if (next == nodes.end() || !ast_is<Statement_t>(*next)) {
5428 throw CompileError("annotation must be followed by a statement"sv, node);
5429 }
5430 if (static_cast<Statement_t*>(*next)->content.is<Return_t>()) {
5431 throw CompileError("annotation can not be applied to a return statement"sv, node);
5432 }
5433 auto callable = annotation->new_ptr<Callable_t>();
5434 auto macroName = annotation->new_ptr<MacroName_t>();
5435 macroName->name.set(annotation->name);
5436 callable->item.set(macroName);
5437 auto chainValue = annotation->new_ptr<ChainValue_t>();
5438 chainValue->items.push_back(callable);
5439 if (annotation->invoke) {
5440 chainValue->items.push_back(annotation->invoke);
5441 }
5442 auto stmtCode = YueFormat{}.toString(*next);
5443 ast_ptr<false, ast_node> macroNode;
5444 std::unique_ptr<input> codes;
5445 std::string luaCodes;
5446 str_list localVars;
5447 bool before = false;
5448 std::tie(macroNode, codes, luaCodes, localVars, before) = expandMacro(chainValue, ExpUsage::Common, false, stmtCode);
5449 if (!before) {
5450 ++nodeIt;
5451 node = *nodeIt;
5452 transformNode();
5453 }
5454 if (!macroNode) {
5455 temp.push_back(luaCodes);
5456 if (!localVars.empty()) {
5457 for (const auto& var : localVars) {
5458 addToScope(var);
5459 }
5460 }
5461 } else {
5462 if (!macroNode.to<Block_t>()->statementOrComments.empty()) {
5463 auto doBody = macroNode->new_ptr<Body_t>();
5464 doBody->content.set(macroNode);
5465 auto doNode = macroNode->new_ptr<Do_t>();
5466 doNode->body.set(doBody);
5467 transformDo(doNode, temp, ExpUsage::Common);
5468 }
5469 }
5470#else // YUE_NO_MACRO
5471 throw CompileError("macro feature not supported"sv, annotation);
5472#endif // YUE_NO_MACRO
5421 } else { 5473 } else {
5422 transformStatement(stmt, temp); 5474 transformStatement(stmt, temp);
5423 } 5475 }
@@ -5659,7 +5711,7 @@ private:
5659 pushCurrentModule(); // cur 5711 pushCurrentModule(); // cur
5660 int top = lua_gettop(L) - 1; 5712 int top = lua_gettop(L) - 1;
5661 DEFER(lua_settop(L, top)); 5713 DEFER(lua_settop(L, top));
5662 if (auto builtinCode = expandMacroChain(chainValue)) { 5714 if (auto builtinCode = expandMacroChain(chainValue, Empty)) {
5663 throw CompileError("macro generating function must return a function"sv, chainValue); 5715 throw CompileError("macro generating function must return a function"sv, chainValue);
5664 } // cur res 5716 } // cur res
5665 if (lua_isfunction(L, -1) == 0) { 5717 if (lua_isfunction(L, -1) == 0) {
@@ -7039,7 +7091,7 @@ private:
7039 return Empty; 7091 return Empty;
7040 } 7092 }
7041 7093
7042 std::optional<std::string> expandMacroChain(ChainValue_t* chainValue) { 7094 std::optional<std::string> expandMacroChain(ChainValue_t* chainValue, const std::string& extraCode) {
7043 const auto& chainList = chainValue->items.objects(); 7095 const auto& chainList = chainValue->items.objects();
7044 auto x = ast_to<Callable_t>(chainList.front())->item.to<MacroName_t>(); 7096 auto x = ast_to<Callable_t>(chainList.front())->item.to<MacroName_t>();
7045 auto macroName = _parser.toString(x->name); 7097 auto macroName = _parser.toString(x->name);
@@ -7088,7 +7140,7 @@ private:
7088 auto chainValue = exp->get_by_path<UnaryExp_t, Value_t, ChainValue_t>(); 7140 auto chainValue = exp->get_by_path<UnaryExp_t, Value_t, ChainValue_t>();
7089 BREAK_IF(!chainValue); 7141 BREAK_IF(!chainValue);
7090 BREAK_IF(!isMacroChain(chainValue)); 7142 BREAK_IF(!isMacroChain(chainValue));
7091 str = std::get<1>(expandMacroStr(chainValue)); 7143 str = std::get<1>(expandMacroStr(chainValue, Empty));
7092 BLOCK_END 7144 BLOCK_END
7093 } 7145 }
7094 } 7146 }
@@ -7184,7 +7236,11 @@ private:
7184 if (args) { 7236 if (args) {
7185 argIt = args->begin(); 7237 argIt = args->begin();
7186 } 7238 }
7239 if (!extraCode.empty()) {
7240 argStrs.push_back(extraCode);
7241 }
7187 for (const auto& arg : argStrs) { 7242 for (const auto& arg : argStrs) {
7243 ast_node* currentArg = args && argIt != args->end() ? *argIt : chainValue;
7188 if (checkIt != checks.end()) { 7244 if (checkIt != checks.end()) {
7189 if (checkIt->empty()) { 7245 if (checkIt->empty()) {
7190 ++checkIt; 7246 ++checkIt;
@@ -7192,18 +7248,20 @@ private:
7192 if ((*checkIt)[0] == '.') { 7248 if ((*checkIt)[0] == '.') {
7193 auto astName = checkIt->substr(3); 7249 auto astName = checkIt->substr(3);
7194 if (!_parser.match(astName, arg)) { 7250 if (!_parser.match(astName, arg)) {
7195 throw CompileError("expecting \""s + astName + "\", AST mismatch"s, *argIt); 7251 throw CompileError("expecting \""s + astName + "\", AST mismatch"s, currentArg);
7196 } 7252 }
7197 } else { 7253 } else {
7198 if (!_parser.match(*checkIt, arg)) { 7254 if (!_parser.match(*checkIt, arg)) {
7199 throw CompileError("expecting \""s + *checkIt + "\", AST mismatch"s, *argIt); 7255 throw CompileError("expecting \""s + *checkIt + "\", AST mismatch"s, currentArg);
7200 } 7256 }
7201 ++checkIt; 7257 ++checkIt;
7202 } 7258 }
7203 } 7259 }
7204 } 7260 }
7205 lua_pushlstring(L, arg.c_str(), arg.size()); 7261 lua_pushlstring(L, arg.c_str(), arg.size());
7206 ++argIt; 7262 if (args && argIt != args->end()) {
7263 ++argIt;
7264 }
7207 } // cur pcall macroFunc args... 7265 } // cur pcall macroFunc args...
7208 bool success = lua_pcall(L, static_cast<int>(argStrs.size()), 1, 0) == 0; 7266 bool success = lua_pcall(L, static_cast<int>(argStrs.size()), 1, 0) == 0;
7209 if (!success) { // cur err 7267 if (!success) { // cur err
@@ -7218,21 +7276,22 @@ private:
7218 return std::nullopt; 7276 return std::nullopt;
7219 } 7277 }
7220 7278
7221 std::tuple<std::string, std::string, str_list> expandMacroStr(ChainValue_t* chainValue) { 7279 std::tuple<std::string, std::string, str_list, bool> expandMacroStr(ChainValue_t* chainValue, const std::string& extraCode) {
7222 auto x = chainValue->items.front(); 7280 auto x = chainValue->items.front();
7223 pushCurrentModule(); // cur 7281 pushCurrentModule(); // cur
7224 int top = lua_gettop(L) - 1; 7282 int top = lua_gettop(L) - 1;
7225 DEFER(lua_settop(L, top)); 7283 DEFER(lua_settop(L, top));
7226 auto builtinCode = expandMacroChain(chainValue); 7284 auto builtinCode = expandMacroChain(chainValue, extraCode);
7227 if (builtinCode) { 7285 if (builtinCode) {
7228 return {Empty, builtinCode.value(), {}}; 7286 return {Empty, builtinCode.value(), {}, false};
7229 } // cur res 7287 } // cur res
7230 if (lua_isstring(L, -1) == 0 && lua_istable(L, -1) == 0) { 7288 if (lua_isstring(L, -1) == 0 && lua_istable(L, -1) == 0) {
7231 throw CompileError("macro function must return a string or a table"sv, x); 7289 throw CompileError("macro function must return a string or a table"sv, x);
7232 } // cur res 7290 } // cur res
7233 std::string codes; 7291 std::string codes;
7234 std::string type; 7292 std::string type = "yue"s;
7235 str_list localVars; 7293 str_list localVars;
7294 bool before = false;
7236 if (lua_istable(L, -1) != 0) { // cur tab 7295 if (lua_istable(L, -1) != 0) { // cur tab
7237 lua_getfield(L, -1, "code"); // cur tab code 7296 lua_getfield(L, -1, "code"); // cur tab code
7238 if (lua_isstring(L, -1) != 0) { 7297 if (lua_isstring(L, -1) != 0) {
@@ -7245,8 +7304,8 @@ private:
7245 if (lua_isstring(L, -1) != 0) { 7304 if (lua_isstring(L, -1) != 0) {
7246 type = lua_tostring(L, -1); 7305 type = lua_tostring(L, -1);
7247 } 7306 }
7248 if (type != "lua"sv && type != "text"sv) { 7307 if (type != "yue"sv && type != "lua"sv && type != "text"sv) {
7249 throw CompileError("macro table must contain field \"type\" of value \"lua\" or \"text\""sv, x); 7308 throw CompileError("macro table must contain field \"type\" of value \"yue\", \"lua\" or \"text\""sv, x);
7250 } 7309 }
7251 lua_pop(L, 1); // cur tab 7310 lua_pop(L, 1); // cur tab
7252 if (type == "text"sv) { 7311 if (type == "text"sv) {
@@ -7269,20 +7328,26 @@ private:
7269 } 7328 }
7270 lua_pop(L, 1); // cur tab 7329 lua_pop(L, 1); // cur tab
7271 } 7330 }
7331 lua_getfield(L, -1, "before"); // cur tab before
7332 if (lua_toboolean(L, -1) != 0) {
7333 before = true;
7334 }
7335 lua_pop(L, 1);
7272 } else { // cur code 7336 } else { // cur code
7273 codes = lua_tostring(L, -1); 7337 codes = lua_tostring(L, -1);
7274 } 7338 }
7275 Utils::trim(codes); 7339 Utils::trim(codes);
7276 Utils::replace(codes, "\r\n"sv, "\n"sv); 7340 Utils::replace(codes, "\r\n"sv, "\n"sv);
7277 return {type, codes, std::move(localVars)}; 7341 return {type, codes, std::move(localVars), before};
7278 } 7342 }
7279 7343
7280 std::tuple<ast_ptr<false, ast_node>, std::unique_ptr<input>, std::string, str_list> expandMacro(ChainValue_t* chainValue, ExpUsage usage, bool allowBlockMacroReturn) { 7344 std::tuple<ast_ptr<false, ast_node>, std::unique_ptr<input>, std::string, str_list, bool> expandMacro(ChainValue_t* chainValue, ExpUsage usage, bool allowBlockMacroReturn, const std::string& extraCode) {
7281 auto x = ast_to<Callable_t>(chainValue->items.front())->item.to<MacroName_t>(); 7345 auto x = ast_to<Callable_t>(chainValue->items.front())->item.to<MacroName_t>();
7282 const auto& chainList = chainValue->items.objects(); 7346 const auto& chainList = chainValue->items.objects();
7283 std::string type, codes; 7347 std::string type, codes;
7284 str_list localVars; 7348 str_list localVars;
7285 std::tie(type, codes, localVars) = expandMacroStr(chainValue); 7349 bool before = false;
7350 std::tie(type, codes, localVars, before) = expandMacroStr(chainValue, extraCode);
7286 bool isBlock = (usage == ExpUsage::Common) && (chainList.size() < 2 || (chainList.size() == 2 && ast_is<Invoke_t, InvokeArgs_t>(chainList.back()))); 7351 bool isBlock = (usage == ExpUsage::Common) && (chainList.size() < 2 || (chainList.size() == 2 && ast_is<Invoke_t, InvokeArgs_t>(chainList.back())));
7287 ParseInfo info; 7352 ParseInfo info;
7288 if (type == "lua"sv) { 7353 if (type == "lua"sv) {
@@ -7298,7 +7363,7 @@ private:
7298 codes.insert(0, indent() + "do"s + nl(chainValue)); 7363 codes.insert(0, indent() + "do"s + nl(chainValue));
7299 codes.append(_newLine + indent() + "end"s + nl(chainValue)); 7364 codes.append(_newLine + indent() + "end"s + nl(chainValue));
7300 } 7365 }
7301 return {nullptr, nullptr, std::move(codes), std::move(localVars)}; 7366 return {nullptr, nullptr, std::move(codes), std::move(localVars), before};
7302 } else { 7367 } else {
7303 auto expCode = "return ("s + codes + ')'; 7368 auto expCode = "return ("s + codes + ')';
7304 if (luaL_loadbuffer(L, expCode.c_str(), expCode.size(), macroChunk.c_str()) != 0) { 7369 if (luaL_loadbuffer(L, expCode.c_str(), expCode.size(), macroChunk.c_str()) != 0) {
@@ -7320,7 +7385,7 @@ private:
7320 newChain->items.push_back(*it); 7385 newChain->items.push_back(*it);
7321 } 7386 }
7322 } 7387 }
7323 return {exp, nullptr, Empty, std::move(localVars)}; 7388 return {exp, nullptr, Empty, std::move(localVars), before};
7324 } 7389 }
7325 } else if (type == "text"sv) { 7390 } else if (type == "text"sv) {
7326 if (!isBlock) { 7391 if (!isBlock) {
@@ -7329,7 +7394,7 @@ private:
7329 if (!codes.empty()) { 7394 if (!codes.empty()) {
7330 codes.append(_newLine); 7395 codes.append(_newLine);
7331 } 7396 }
7332 return {nullptr, nullptr, std::move(codes), std::move(localVars)}; 7397 return {nullptr, nullptr, std::move(codes), std::move(localVars), before};
7333 } else { 7398 } else {
7334 if (!codes.empty()) { 7399 if (!codes.empty()) {
7335 if (isBlock) { 7400 if (isBlock) {
@@ -7395,10 +7460,10 @@ private:
7395 auto block = blockEnd->block.get(); 7460 auto block = blockEnd->block.get();
7396 info.node.set(block); 7461 info.node.set(block);
7397 } 7462 }
7398 return {info.node, std::move(info.codes), Empty, std::move(localVars)}; 7463 return {info.node, std::move(info.codes), Empty, std::move(localVars), before};
7399 } else { 7464 } else {
7400 if (!isBlock) throw CompileError("failed to expand empty macro as expr"sv, x); 7465 if (!isBlock) throw CompileError("failed to expand empty macro as expr"sv, x);
7401 return {x->new_ptr<Block_t>().get(), std::move(info.codes), Empty, std::move(localVars)}; 7466 return {x->new_ptr<Block_t>().get(), std::move(info.codes), Empty, std::move(localVars), before};
7402 } 7467 }
7403 } 7468 }
7404 } 7469 }
@@ -7411,7 +7476,8 @@ private:
7411 std::unique_ptr<input> codes; 7476 std::unique_ptr<input> codes;
7412 std::string luaCodes; 7477 std::string luaCodes;
7413 str_list localVars; 7478 str_list localVars;
7414 std::tie(node, codes, luaCodes, localVars) = expandMacro(chainValue, usage, allowBlockMacroReturn); 7479 bool before = false;
7480 std::tie(node, codes, luaCodes, localVars, before) = expandMacro(chainValue, usage, allowBlockMacroReturn, Empty);
7415 if (!node) { 7481 if (!node) {
7416 out.push_back(luaCodes); 7482 out.push_back(luaCodes);
7417 if (!localVars.empty()) { 7483 if (!localVars.empty()) {
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index 7ea2c97..8ab667d 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -1072,6 +1072,8 @@ YueParser::YueParser() {
1072 ); 1072 );
1073 MacroInPlace = '$' >> space >> "->" >> space >> Body; 1073 MacroInPlace = '$' >> space >> "->" >> space >> Body;
1074 1074
1075 Annotation = "$[" >> space >> UnicodeName >> -(Invoke | InvokeArgs) >> space >> ']';
1076
1075 must_variable = Variable | and_(LuaKeyword >> not_alpha_num) >> keyword_as_identifier_syntax_error | expected_indentifier_error; 1077 must_variable = Variable | and_(LuaKeyword >> not_alpha_num) >> keyword_as_identifier_syntax_error | expected_indentifier_error;
1076 1078
1077 NameList = Seperator >> must_variable >> *(space >> ',' >> space >> must_variable); 1079 NameList = Seperator >> must_variable >> *(space >> ',' >> space >> must_variable);
@@ -1128,7 +1130,7 @@ YueParser::YueParser() {
1128 StatementAppendix = IfLine | WhileLine | CompFor; 1130 StatementAppendix = IfLine | WhileLine | CompFor;
1129 Statement = ( 1131 Statement = (
1130 ( 1132 (
1131 Import | Export | Global | Macro | MacroInPlace | Label 1133 Import | Export | Global | Macro | MacroInPlace | Annotation | Label
1132 ) | ( 1134 ) | (
1133 Local | While | Repeat | For | Return | 1135 Local | While | Repeat | For | Return |
1134 BreakLoop | Goto | ShortTabAppending | 1136 BreakLoop | Goto | ShortTabAppending |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h
index 07153fb..cfcbb48 100644
--- a/src/yuescript/yue_parser.h
+++ b/src/yuescript/yue_parser.h
@@ -464,6 +464,7 @@ private:
464 AST_RULE(MacroFunc); 464 AST_RULE(MacroFunc);
465 AST_RULE(Macro); 465 AST_RULE(Macro);
466 AST_RULE(MacroInPlace); 466 AST_RULE(MacroInPlace);
467 AST_RULE(Annotation);
467 AST_RULE(NameOrDestructure); 468 AST_RULE(NameOrDestructure);
468 AST_RULE(AssignableNameList); 469 AST_RULE(AssignableNameList);
469 AST_RULE(InvokeArgs); 470 AST_RULE(InvokeArgs);