From 43dde2fff316051d03968e8efd313f19b53112fc Mon Sep 17 00:00:00 2001 From: Li Jin Date: Fri, 21 Nov 2025 12:21:04 +0800 Subject: Updated syntax. * Added error check for mixed use of tabs and spaces. * Supported SimpleTable destructuring for ForEach syntax. --- src/yuescript/yue_ast.h | 2 +- src/yuescript/yue_compiler.cpp | 26 +++++++++++++----------- src/yuescript/yue_parser.cpp | 46 ++++++++++++++++++++++++++++-------------- src/yuescript/yue_parser.h | 1 + 4 files changed, 47 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 0008fd6..5f04fa0 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h @@ -848,7 +848,7 @@ AST_NODE(Macro) AST_END(Macro) AST_NODE(NameOrDestructure) - ast_sel item; + ast_sel item; AST_MEMBER(NameOrDestructure, &item) AST_END(NameOrDestructure) diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index d6db3fc..55ab4ec 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -78,7 +78,7 @@ static std::unordered_set Metamethods = { "close"s // Lua 5.4 }; -const std::string_view version = "0.29.8"sv; +const std::string_view version = "0.29.9"sv; const std::string_view extension = "yue"sv; class CompileError : public std::logic_error { @@ -8427,13 +8427,8 @@ private: varConstAfter = vars.back(); } break; - case id(): { - auto desVar = getUnusedName("_des_"sv); - destructPairs.emplace_back(item, toAst(desVar, x)); - vars.push_back(desVar); - varAfter.push_back(desVar); - break; - } + case id(): + case id(): case id(): { auto desVar = getUnusedName("_des_"sv); destructPairs.emplace_back(item, toAst(desVar, x)); @@ -8642,11 +8637,18 @@ private: if (!destructPairs.empty()) { temp.clear(); for (auto& pair : destructPairs) { - auto sValue = x->new_ptr(); - sValue->value.set(pair.first); - auto exp = newExp(sValue, x); auto expList = x->new_ptr(); - expList->exprs.push_back(exp); + if (ast_is(pair.first)) { + auto value = x->new_ptr(); + value->item.set(pair.first); + auto exp = newExp(value, x); + expList->exprs.push_back(exp); + } else { + auto sValue = x->new_ptr(); + sValue->value.set(pair.first); + auto exp = newExp(sValue, x); + expList->exprs.push_back(exp); + } auto assign = x->new_ptr(); assign->values.push_back(pair.second); auto assignment = x->new_ptr(); diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index fccb6fb..cbba115 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -232,27 +232,43 @@ YueParser::YueParser() { KeyName = SelfItem | Name | UnicodeName; VarArg = "..."; - check_indent = pl::user(plain_space, [](const item_t& item) { + auto getIndent = [](const item_t& item) -> int { + if (item.begin->m_it == item.end->m_it) return 0; + State* st = reinterpret_cast(item.user_data); + bool useTab = false; + if (st->useTab) { + useTab = st->useTab.value(); + } else { + useTab = *item.begin->m_it == '\t'; + st->useTab = useTab; + } int indent = 0; - for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) { - switch (*i) { - case ' ': indent++; break; - case '\t': indent += 4; break; + if (useTab) { + for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) { + switch (*i) { + case '\t': indent += 4; break; + default: throw ParserError("can not mix the use of tabs and spaces as indents"sv, item.begin); break; + } + } + } else { + for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) { + switch (*i) { + case ' ': indent++; break; + default: throw ParserError("can not mix the use of tabs and spaces as indents"sv, item.begin); break; + } } } + return indent; + }; + + check_indent = pl::user(plain_space, [getIndent](const item_t& item) { State* st = reinterpret_cast(item.user_data); - return st->indents.top() == indent; + return st->indents.top() == getIndent(item); }); check_indent_match = and_(check_indent); - advance = pl::user(plain_space, [](const item_t& item) { - int indent = 0; - for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) { - switch (*i) { - case ' ': indent++; break; - case '\t': indent += 4; break; - } - } + advance = pl::user(plain_space, [getIndent](const item_t& item) { + int indent = getIndent(item); State* st = reinterpret_cast(item.user_data); int top = st->indents.top(); if (top != -1 && indent > top) { @@ -921,7 +937,7 @@ YueParser::YueParser() { MacroInPlace = '$' >> space >> "->" >> space >> Body; NameList = Seperator >> Variable >> *(space >> ',' >> space >> Variable); - NameOrDestructure = Variable | TableLit | Comprehension; + NameOrDestructure = Variable | TableLit | Comprehension | SimpleTable; AssignableNameList = Seperator >> NameOrDestructure >> *(space >> ',' >> space >> NameOrDestructure); FnArrowBack = '<' >> set("-="); diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 4c546b1..d5c37e2 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h @@ -119,6 +119,7 @@ protected: int expLevel = 0; size_t stringOpen = 0; std::string buffer; + std::optional useTab; std::stack indents; std::vector noDoStack; std::vector noChainBlockStack; -- cgit v1.2.3-55-g6feb