From 552c260d3c3e8d2c65125bba77b588d7e487d983 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Fri, 5 Dec 2025 17:44:20 +0800 Subject: Fixed more error messages. --- spec/inputs/import.yue | 2 +- spec/inputs/unicode/import.yue | 2 +- src/yuescript/yue_ast.cpp | 11 ++- src/yuescript/yue_ast.h | 37 +++++---- src/yuescript/yue_compiler.cpp | 181 +++++++++++++++++++++++++---------------- src/yuescript/yue_parser.cpp | 109 ++++++++++++++----------- src/yuescript/yue_parser.h | 14 ++-- 7 files changed, 213 insertions(+), 143 deletions(-) diff --git a/spec/inputs/import.yue b/spec/inputs/import.yue index 8982e6c..ee1fdfc 100644 --- a/spec/inputs/import.yue +++ b/spec/inputs/import.yue @@ -23,7 +23,7 @@ do b, c from z do - import a + import a, b c from z diff --git a/spec/inputs/unicode/import.yue b/spec/inputs/unicode/import.yue index c229edb..a7724ab 100644 --- a/spec/inputs/unicode/import.yue +++ b/spec/inputs/unicode/import.yue @@ -23,7 +23,7 @@ do 字段b, 字段c from 对象z do - import 字段a + import 字段a, 字段b 字段c from 对象z diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp index a2e3403..be0ec45 100644 --- a/src/yuescript/yue_ast.cpp +++ b/src/yuescript/yue_ast.cpp @@ -594,7 +594,7 @@ std::string Repeat_t::to_string(void* ud) const { std::string ForStepValue_t::to_string(void* ud) const { return value->to_string(ud); } -std::string For_t::to_string(void* ud) const { +std::string ForNum_t::to_string(void* ud) const { auto info = reinterpret_cast(ud); auto line = "for "s + varName->to_string(ud) + " = "s + startValue->to_string(ud) + ", "s + stopValue->to_string(ud); if (stepValue) { @@ -633,6 +633,9 @@ std::string ForEach_t::to_string(void* ud) const { return line + '\n' + block; } } +std::string For_t::to_string(void* ud) const { + return forLoop->to_string(ud); +} std::string Do_t::to_string(void* ud) const { auto info = reinterpret_cast(ud); if (body->content.is()) { @@ -784,7 +787,7 @@ static bool isInBlockExp(ast_node* node, bool last = false) { return false; } std::string Comprehension_t::to_string(void* ud) const { - if (items.size() != 2 || !ast_is(items.back())) { + if (items.size() != 2 || !ast_is(items.back())) { if (items.size() == 1) { str_list temp; for (const auto& item : items.objects()) { @@ -851,14 +854,14 @@ std::string StarExp_t::to_string(void* ud) const { std::string CompForEach_t::to_string(void* ud) const { return "for "s + nameList->to_string(ud) + " in "s + loopValue->to_string(ud); } -std::string CompFor_t::to_string(void* ud) const { +std::string CompForNum_t::to_string(void* ud) const { auto line = "for "s + varName->to_string(ud) + " = "s + startValue->to_string(ud) + ", "s + stopValue->to_string(ud); if (stepValue) { line += stepValue->to_string(ud); } return line; } -std::string CompInner_t::to_string(void* ud) const { +std::string CompFor_t::to_string(void* ud) const { str_list temp; for (auto item : items.objects()) { if (ast_is(item)) { diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 97901ec..b7cd73e 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h @@ -68,7 +68,7 @@ class Statement_t; class Body_t; class AssignableNameList_t; class StarExp_t; -class CompInner_t; +class CompFor_t; class AssignableChain_t; class UnaryExp_t; class Parens_t; @@ -358,14 +358,14 @@ AST_NODE(ForStepValue) AST_MEMBER(ForStepValue, &value) AST_END(ForStepValue) -AST_NODE(For) +AST_NODE(ForNum) ast_ptr varName; ast_ptr startValue; ast_ptr stopValue; ast_ptr stepValue; ast_sel body; - AST_MEMBER(For, &varName, &startValue, &stopValue, &stepValue, &body) -AST_END(For) + AST_MEMBER(ForNum, &varName, &startValue, &stopValue, &stepValue, &body) +AST_END(ForNum) AST_NODE(ForEach) ast_ptr nameList; @@ -374,6 +374,11 @@ AST_NODE(ForEach) AST_MEMBER(ForEach, &nameList, &loopValue, &body) AST_END(ForEach) +AST_NODE(For) + ast_sel forLoop; + AST_MEMBER(For, &forLoop) +AST_END(For) + AST_NODE(Do) ast_ptr body; AST_MEMBER(Do, &body) @@ -394,7 +399,7 @@ AST_END(Try) AST_NODE(Comprehension) ast_ptr sep; - ast_sel_list items; AST_MEMBER(Comprehension, &sep, &items) AST_END(Comprehension) @@ -407,7 +412,7 @@ AST_END(CompValue) AST_NODE(TblComprehension) ast_ptr key; ast_ptr value; - ast_ptr forLoop; + ast_ptr forLoop; AST_MEMBER(TblComprehension, &key, &value, &forLoop) AST_END(TblComprehension) @@ -422,19 +427,19 @@ AST_NODE(CompForEach) AST_MEMBER(CompForEach, &nameList, &loopValue) AST_END(CompForEach) -AST_NODE(CompFor) +AST_NODE(CompForNum) ast_ptr varName; ast_ptr startValue; ast_ptr stopValue; ast_ptr stepValue; - AST_MEMBER(CompFor, &varName, &startValue, &stopValue, &stepValue) -AST_END(CompFor) + AST_MEMBER(CompForNum, &varName, &startValue, &stopValue, &stepValue) +AST_END(CompForNum) -AST_NODE(CompInner) +AST_NODE(CompFor) ast_ptr sep; - ast_sel_list items; - AST_MEMBER(CompInner, &sep, &items) -AST_END(CompInner) + ast_sel_list items; + AST_MEMBER(CompFor, &sep, &items) +AST_END(CompFor) AST_NODE(Assign) ast_ptr sep; @@ -553,7 +558,7 @@ AST_NODE(SimpleValue) ast_sel value; @@ -919,7 +924,7 @@ AST_NODE(PipeBody) AST_END(PipeBody) AST_NODE(StatementAppendix) - ast_sel item; + ast_sel item; AST_MEMBER(StatementAppendix, &item) AST_END(StatementAppendix) @@ -949,7 +954,7 @@ AST_END(ChainAssign) AST_NODE(Statement) ast_sel Metamethods = { "close"s // Lua 5.4 }; -const std::string_view version = "0.30.2"sv; +const std::string_view version = "0.30.3"sv; const std::string_view extension = "yue"sv; class CompileError : public std::logic_error { @@ -1474,7 +1474,7 @@ private: if (simpleValue->value.is()) { return true; } else if (auto comp = simpleValue->value.as()) { - if (comp->items.size() != 2 || !ast_is(comp->items.back())) { + if (comp->items.size() != 2 || !ast_is(comp->items.back())) { return true; } } @@ -1745,7 +1745,7 @@ private: throw CompileError("while-loop line decorator is not supported here"sv, appendix->item.get()); break; } - case id(): { + case id(): { throw CompileError("for-loop line decorator is not supported here"sv, appendix->item.get()); break; } @@ -1806,8 +1806,8 @@ private: statement->content.set(expListAssign); break; } - case id(): { - auto compInner = appendix->item.to(); + case id(): { + auto compInner = appendix->item.to(); auto comp = x->new_ptr(); auto stmt = x->new_ptr(); stmt->content.set(statement->content); @@ -1877,7 +1877,7 @@ private: case id(): transformTry(static_cast(value), out, ExpUsage::Common); break; case id(): { auto comp = static_cast(value); - if (comp->items.size() == 2 && ast_is(comp->items.back())) { + if (comp->items.size() == 2 && ast_is(comp->items.back())) { transformCompCommon(comp, out); } else { specialSingleValue = false; @@ -2346,7 +2346,7 @@ private: auto elmVar = getUnusedName("_elm_"sv); _buf << varName << '[' << lenVar << "],"s << lenVar << "="s << elmVar << ',' << lenVar << "+1 for "s << elmVar << " in *nil"s; auto stmt = toAst(clearBuf(), spread); - auto comp = stmt->appendix->item.to(); + auto comp = stmt->appendix->item.to(); ast_to(comp->items.front())->loopValue.to()->value.set(spread->exp); transformStatement(stmt, temp); } else { @@ -2468,7 +2468,7 @@ private: case id(): { auto comp = static_cast(value); auto expList = assignment->expList.get(); - if (comp->items.size() == 2 && ast_is(comp->items.back())) { + if (comp->items.size() == 2 && ast_is(comp->items.back())) { std::string preDefine = getPreDefineLine(assignment); transformComprehension(comp, out, ExpUsage::Assignment, expList); out.back().insert(0, preDefine); @@ -2893,7 +2893,7 @@ private: if (auto tbA = item->get_by_path()) { tableItems = &tbA->values.objects(); } else if (auto tbB = item->get_by_path()) { - if (tbB->items.size() == 2 && ast_is(tbB->items.back())) { + if (tbB->items.size() == 2 && ast_is(tbB->items.back())) { throw CompileError("invalid destructure value"sv, tbB); } tableItems = &tbB->items.objects(); @@ -2924,7 +2924,7 @@ private: } case id(): { auto table = static_cast(node); - if (table->items.size() == 2 && ast_is(table->items.back())) { + if (table->items.size() == 2 && ast_is(table->items.back())) { throw CompileError("invalid destructure value"sv, table); } tableItems = &table->items.objects(); @@ -3295,7 +3295,7 @@ private: if (auto tab = sVal->value.as()) { destructNode = tab; } else if (auto comp = sVal->value.as()) { - if (comp->items.size() != 2 || !ast_is(comp->items.back())) { + if (comp->items.size() != 2 || !ast_is(comp->items.back())) { destructNode = comp; } } @@ -4918,7 +4918,7 @@ private: throw CompileError("while-loop line decorator is not supported here"sv, appendix->item.get()); break; } - case id(): { + case id(): { throw CompileError("for-loop line decorator is not supported here"sv, appendix->item.get()); break; } @@ -5259,7 +5259,7 @@ private: break; } } - bool lastAssignable = (expListFrom(last) || ast_is(last->content)); + bool lastAssignable = (expListFrom(last) || ast_is(last->content)); if (lastAssignable) { auto x = last; auto newAssignment = x->new_ptr(); @@ -5704,10 +5704,7 @@ private: transformRepeatInPlace(static_cast(value), out); return; case id(): - transformForInPlace(static_cast(value), out); - return; - case id(): - transformForEachInPlace(static_cast(value), out); + transformForInPlace(static_cast(value), out, nullptr); return; case id(): transformIf(static_cast(value), out, ExpUsage::Return); @@ -7425,7 +7422,7 @@ private: } } } else if (auto comp = sval->value.as()) { - if (comp->items.size() != 2 || !ast_is(comp->items.back())) { + if (comp->items.size() != 2 || !ast_is(comp->items.back())) { discrete = inExp->new_ptr(); for (ast_node* val : comp->items.objects()) { if (auto def = ast_cast(val)) { @@ -7844,8 +7841,8 @@ private: << "\n\t\t"sv << tableVar << "[]="sv << valueVar << "\n\t\t"sv << indexVar << "+=1"sv << "\n\telse "sv << tableVar << '[' << keyVar << "]="sv << valueVar; - auto forEach = toAst(clearBuf(), item); - transformForEach(forEach, temp); + auto forNode = toAst(clearBuf(), item); + transformFor(forNode, temp); break; } case id(): { @@ -7866,8 +7863,8 @@ private: _buf << "for "sv << valueVar << " in *"sv << objVar << "\n\t"sv << tableVar << '[' << indexVar << "]="sv << valueVar << "\n\t"sv << indexVar << "+=1"sv; - auto forEach = toAst(clearBuf(), item); - transformForEach(forEach, temp); + auto forNode = toAst(clearBuf(), item); + transformFor(forNode, temp); break; } case id(): @@ -8248,14 +8245,14 @@ private: void transformCompCommon(Comprehension_t* comp, str_list& out) { str_list temp; auto x = comp; - auto compInner = static_cast(comp->items.back()); - for (auto item : compInner->items.objects()) { + auto compFor = static_cast(comp->items.back()); + for (auto item : compFor->items.objects()) { switch (item->get_id()) { case id(): transformCompForEach(static_cast(item), temp); break; - case id(): - transformCompFor(static_cast(item), temp); + case id(): + transformCompForNum(static_cast(item), temp); break; case id(): transformExp(static_cast(item), temp, ExpUsage::Closure); @@ -8279,7 +8276,7 @@ private: auto value = std::move(temp.back()); temp.pop_back(); _buf << join(temp) << value; - for (size_t i = 0; i < compInner->items.objects().size(); ++i) { + for (size_t i = 0; i < compFor->items.objects().size(); ++i) { popScope(); _buf << indent() << "end"sv << nl(comp); } @@ -8288,7 +8285,7 @@ private: void transformComprehension(Comprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { auto x = comp; - if (comp->items.size() != 2 || !ast_is(comp->items.back())) { + if (comp->items.size() != 2 || !ast_is(comp->items.back())) { switch (usage) { case ExpUsage::Assignment: { auto tableLit = x->new_ptr(); @@ -8360,7 +8357,7 @@ private: default: break; } - auto compInner = static_cast(comp->items.back()); + auto compFor = static_cast(comp->items.back()); str_list temp; std::string accumVar = getUnusedName("_accum_"sv); addToScope(accumVar); @@ -8369,13 +8366,13 @@ private: lenVar = getUnusedName("_len_"sv); addToScope(lenVar); } - for (auto item : compInner->items.objects()) { + for (auto item : compFor->items.objects()) { switch (item->get_id()) { case id(): transformCompForEach(static_cast(item), temp); break; - case id(): - transformCompFor(static_cast(item), temp); + case id(): + transformCompForNum(static_cast(item), temp); break; case id(): transformExp(static_cast(item), temp, ExpUsage::Closure); @@ -8396,7 +8393,7 @@ private: } auto assignStr = std::move(temp.back()); temp.pop_back(); - for (size_t i = 0; i < compInner->items.objects().size(); ++i) { + for (size_t i = 0; i < compFor->items.objects().size(); ++i) { popScope(); } _buf << indent() << "local "sv << accumVar << " = { }"sv << nl(comp); @@ -8754,7 +8751,7 @@ private: out.push_back('(' + join(temp, ", "sv) + ')'); } - void transformForHead(Variable_t* var, Exp_t* startVal, Exp_t* stopVal, ForStepValue_t* stepVal, str_list& out) { + void transformForNumHead(Variable_t* var, Exp_t* startVal, Exp_t* stopVal, ForStepValue_t* stepVal, str_list& out) { str_list temp; std::string varName = variableToString(var); transformExp(startVal, temp, ExpUsage::Closure); @@ -8775,8 +8772,8 @@ private: out.push_back(clearBuf()); } - void transformForHead(For_t* forNode, str_list& out) { - transformForHead(forNode->varName, forNode->startValue, forNode->stopValue, forNode->stepValue, out); + void transformForNumHead(ForNum_t* forNum, str_list& out) { + transformForNumHead(forNum->varName, forNum->startValue, forNum->stopValue, forNum->stepValue, out); } void transform_plain_body(ast_node* bodyOrStmt, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { @@ -9040,46 +9037,48 @@ private: return conditionVar; } - void transformFor(For_t* forNode, str_list& out) { + void transformForNum(ForNum_t* forNum, str_list& out) { str_list temp; - transformForHead(forNode, temp); - auto breakLoopType = getBreakLoopType(forNode->body, Empty); - transformLoopBody(forNode->body, temp, breakLoopType, ExpUsage::Common); + transformForNumHead(forNum, temp); + auto breakLoopType = getBreakLoopType(forNum->body, Empty); + transformLoopBody(forNum->body, temp, breakLoopType, ExpUsage::Common); popScope(); - out.push_back(join(temp) + indent() + "end"s + nl(forNode)); + out.push_back(join(temp) + indent() + "end"s + nl(forNum)); } - std::string transformForInner(For_t* forNode, str_list& out) { - auto x = forNode; + std::string transformForNumInner(ForNum_t* forNum, str_list& out) { + auto x = forNum; std::string accum = getUnusedName("_accum_"sv); addToScope(accum); std::string len = getUnusedName("_len_"sv); addToScope(len); - auto breakLoopType = getBreakLoopType(forNode->body, accum); - _buf << indent() << "local "sv << accum << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nl(forNode); + auto breakLoopType = getBreakLoopType(forNum->body, accum); + _buf << indent() << "local "sv << accum << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nl(forNum); out.emplace_back(clearBuf()); - _buf << indent() << "local "sv << len << " = 1"sv << nl(forNode); + _buf << indent() << "local "sv << len << " = 1"sv << nl(forNum); auto& lenAssign = out.emplace_back(clearBuf()); - transformForHead(forNode, out); + transformForNumHead(forNum, out); if (hasBreakWithValue(breakLoopType)) { lenAssign.clear(); - transformLoopBody(forNode->body, out, breakLoopType, ExpUsage::Common); + transformLoopBody(forNum->body, out, breakLoopType, ExpUsage::Common); } else { auto expList = toAst(accum + '[' + len + ']', x); - auto followStmt = toAst(len + "+=1"s, forNode->body); + auto followStmt = toAst(len + "+=1"s, forNum->body); expList->followStmt = followStmt.get(); - transformLoopBody(forNode->body, out, breakLoopType, ExpUsage::Assignment, expList); + transformLoopBody(forNum->body, out, breakLoopType, ExpUsage::Assignment, expList); if (!expList->followStmtProcessed) { lenAssign.clear(); } } popScope(); - out.push_back(indent() + "end"s + nl(forNode)); + out.push_back(indent() + "end"s + nl(forNum)); return accum; } - void transformForClosure(For_t* forNode, str_list& out) { - auto simpleValue = forNode->new_ptr(); + void transformForNumClosure(ForNum_t* forNum, str_list& out) { + auto forNode = forNum->new_ptr(); + forNode->forLoop.set(forNum); + auto simpleValue = forNum->new_ptr(); simpleValue->value.set(forNode); if (transformAsUpValueFunc(newExp(simpleValue, forNode), out)) { return; @@ -9089,26 +9088,26 @@ private: pushAnonVarArg(); std::string& funcStart = temp.emplace_back(); pushScope(); - auto accum = transformForInner(forNode, temp); - temp.push_back(indent() + "return "s + accum + nl(forNode)); + auto accum = transformForNumInner(forNum, temp); + temp.push_back(indent() + "return "s + accum + nl(forNum)); popScope(); - funcStart = anonFuncStart() + nl(forNode); + funcStart = anonFuncStart() + nl(forNum); temp.push_back(indent() + anonFuncEnd()); popAnonVarArg(); popFunctionScope(); out.push_back(join(temp)); } - void transformForInPlace(For_t* forNode, str_list& out, ExpList_t* assignExpList = nullptr) { - auto x = forNode; + void transformForNumInPlace(ForNum_t* forNum, str_list& out, ExpList_t* assignExpList) { + auto x = forNum; str_list temp; bool isScoped = !currentScope().lastStatement; if (assignExpList) { if (isScoped) { - _buf << indent() << "do"sv << nl(forNode); + _buf << indent() << "do"sv << nl(forNum); pushScope(); } - auto accum = transformForInner(forNode, temp); + auto accum = transformForNumInner(forNum, temp); auto assign = x->new_ptr(); assign->values.push_back(toAst(accum, x)); auto assignment = x->new_ptr(); @@ -9117,10 +9116,10 @@ private: transformAssignment(assignment, temp); if (isScoped) { popScope(); - temp.push_back(indent() + "end"s + nl(forNode)); + temp.push_back(indent() + "end"s + nl(forNum)); } } else { - auto accum = transformForInner(forNode, temp); + auto accum = transformForNumInner(forNum, temp); auto returnNode = x->new_ptr(); returnNode->explicitReturn = false; auto expListLow = toAst(accum, x); @@ -9191,9 +9190,11 @@ private: } void transformForEachClosure(ForEach_t* forEach, str_list& out) { + auto forNode = forEach->new_ptr(); + forNode->forLoop.set(forEach); auto simpleValue = forEach->new_ptr(); - simpleValue->value.set(forEach); - if (transformAsUpValueFunc(newExp(simpleValue, forEach), out)) { + simpleValue->value.set(forNode); + if (transformAsUpValueFunc(newExp(simpleValue, forNode), out)) { return; } str_list temp; @@ -9211,7 +9212,7 @@ private: out.push_back(join(temp)); } - void transformForEachInPlace(ForEach_t* forEach, str_list& out, ExpList_t* assignExpList = nullptr) { + void transformForEachInPlace(ForEach_t* forEach, str_list& out, ExpList_t* assignExpList) { auto x = forEach; str_list temp; bool isScoped = !currentScope().lastStatement; @@ -9242,6 +9243,48 @@ private: out.push_back(join(temp)); } + void transformFor(For_t* forNode, str_list& out) { + switch (forNode->forLoop->get_id()) { + case id(): + transformForNum(static_cast(forNode->forLoop.get()), out); + break; + case id(): + transformForEach(static_cast(forNode->forLoop.get()), out); + break; + default: + YUEE("AST node mismatch", forNode->forLoop.get()); + break; + } + } + + void transformForClosure(For_t* forNode, str_list& out) { + switch (forNode->forLoop->get_id()) { + case id(): + transformForNumClosure(static_cast(forNode->forLoop.get()), out); + break; + case id(): + transformForEachClosure(static_cast(forNode->forLoop.get()), out); + break; + default: + YUEE("AST node mismatch", forNode->forLoop.get()); + break; + } + } + + void transformForInPlace(For_t* forNode, str_list& out, ExpList_t* assignExpList) { + switch (forNode->forLoop->get_id()) { + case id(): + transformForNumInPlace(static_cast(forNode->forLoop.get()), out, assignExpList); + break; + case id(): + transformForEachInPlace(static_cast(forNode->forLoop.get()), out, assignExpList); + break; + default: + YUEE("AST node mismatch", forNode->forLoop.get()); + break; + } + } + void transform_variable_pair(VariablePair_t* pair, str_list& out) { auto name = _parser.toString(pair->name); if (pair->name->name.is()) { @@ -10530,8 +10573,8 @@ private: case id(): transformCompForEach(static_cast(item), temp); break; - case id(): - transformCompFor(static_cast(item), temp); + case id(): + transformCompForNum(static_cast(item), temp); break; case id(): transformExp(static_cast(item), temp, ExpUsage::Closure); @@ -10597,8 +10640,8 @@ private: } } - void transformCompFor(CompFor_t* comp, str_list& out) { - transformForHead(comp->varName, comp->startValue, comp->stopValue, comp->stepValue, out); + void transformCompForNum(CompForNum_t* comp, str_list& out) { + transformForNumHead(comp->varName, comp->startValue, comp->stopValue, comp->stepValue, out); } void transformTableBlockIndent(TableBlockIndent_t* table, str_list& out) { diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index a7feb83..1b72a8c 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -113,7 +113,7 @@ YueParser::YueParser() { }; empty_block_error = expect_error( - "must be followed by a statement or an indented block"sv + "expected a valid statement or indented block"sv ); export_expression_error = expect_error( "invalid export expression"sv @@ -170,7 +170,7 @@ YueParser::YueParser() { "invalid import syntax, expected `import \"X.mod\" as modname` or `import \"X.mod\" as {:name}`"sv ); expected_expression_error = expect_error( - "expected expression"sv + "expected valid expression"sv ); invalid_from_import_error = expect_error( "invalid import syntax, expected `from \"X.mod\" import name` or `from mod import name`"sv @@ -202,6 +202,9 @@ YueParser::YueParser() { invalid_import_literal_error = expect_error( "invalid import path literal, expected a dotted path like X.Y.Z"sv ); + expected_indentifier_error = expect_error( + "expected valid identifer"sv + ); #define ensure(patt, finally) ((patt) >> (finally) | (finally) >> cut) @@ -382,22 +385,24 @@ YueParser::YueParser() { local_const_item = Variable | SimpleTable | TableLit | Comprehension; LocalAttrib = ( ConstAttrib >> Seperator >> space >> local_const_item >> *(space >> ',' >> space >> local_const_item) | - CloseAttrib >> Seperator >> space >> Variable >> *(space >> ',' >> space >> Variable) + CloseAttrib >> Seperator >> space >> must_variable >> *(space >> ',' >> space >> must_variable) ) >> space >> Assign; - ColonImportName = '\\' >> space >> Variable; - import_name = ColonImportName | Variable; - import_name_list = Seperator >> *space_break >> space >> import_name >> *((+space_break | space >> ',' >> *space_break) >> space >> import_name); + ColonImportName = '\\' >> must_variable; + import_name = not_(key("from")) >> (ColonImportName | must_variable); + import_name_list = Seperator >> *space_break >> space >> import_name >> *( + (+space_break | space >> ',' >> *space_break) >> space >> import_name + ); ImportFrom = import_name_list >> *space_break >> space >> key("from") >> space >> (ImportLiteral | not_(String) >> must_exp); - from_import_name_list_line = import_name >> *(space >> ',' >> space >> import_name); + from_import_name_list_line = import_name >> *(space >> ',' >> space >> not_(line_break) >> import_name); from_import_name_in_block = +space_break >> advance_match >> ensure(space >> from_import_name_list_line >> *(-(space >> ',') >> +space_break >> check_indent_match >> space >> from_import_name_list_line), pop_indent); FromImport = key("from") >> space >> ( ImportLiteral | not_(String) >> Exp | invalid_from_import_error ) >> *space_break >> space >> ( key("import") | invalid_from_import_error ) >> space >> Seperator >> ( - from_import_name_list_line >> -(space >> ',') >> -from_import_name_in_block | from_import_name_in_block | + from_import_name_list_line >> -(space >> ',') >> -from_import_name_in_block | invalid_from_import_error ); @@ -432,16 +437,18 @@ YueParser::YueParser() { -(space >> ',') >> -import_tab_lines >> white >> - '}' + end_braces_expression ) | ( Seperator >> import_tab_key_value >> *(space >> ',' >> space >> import_tab_key_value) ); - ImportAs = ImportLiteral >> -(space >> key("as") >> space >> (ImportTabLit | Variable | ImportAllMacro | invalid_import_as_syntax_error)); + ImportAs = ImportLiteral >> -(space >> key("as") >> space >> ( + ImportTabLit | Variable | ImportAllMacro | invalid_import_as_syntax_error + )); - ImportGlobal = Seperator >> UnicodeName >> *('.' >> UnicodeName) >> -(space >> key("as") >> space >> Variable); + ImportGlobal = Seperator >> UnicodeName >> *('.' >> UnicodeName) >> space >> not_(',' | key("from")) >> -(key("as") >> space >> must_variable); - Import = key("import") >> space >> (ImportAs | ImportFrom | ImportGlobal | invalid_import_syntax_error) | FromImport; + Import = key("import") >> space >> (ImportGlobal | ImportAs | ImportFrom | invalid_import_syntax_error) | FromImport; Label = "::" >> (and_(LuaKeyword >> "::") >> keyword_as_label_error | UnicodeName >> "::"); @@ -511,13 +518,15 @@ YueParser::YueParser() { ForStepValue = ',' >> space >> must_exp; for_args = Variable >> space >> '=' >> space >> must_exp >> space >> ',' >> space >> must_exp >> space >> -ForStepValue; - For = for_key >> space >> disable_do_chain_arg_table_block_rule(for_args) >> space >> opt_body_with("do"); + ForNum = disable_do_chain_arg_table_block_rule(for_args) >> space >> opt_body_with("do"); for_in = StarExp | ExpList | expected_expression_error; - ForEach = for_key >> space >> AssignableNameList >> space >> key("in") >> space >> + ForEach = AssignableNameList >> space >> key("in") >> space >> disable_do_chain_arg_table_block_rule(for_in) >> space >> opt_body_with("do"); + For = for_key >> space >> (ForNum | ForEach); + Do = pl::user(key("do"), [](const item_t& item) { State* st = reinterpret_cast(item.user_data); return st->noDoStack.empty() || !st->noDoStack.back(); @@ -599,7 +608,7 @@ YueParser::YueParser() { return true; }); - CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> (Variable >> space >> in_block | invalid_try_syntax_error); + CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> must_variable >> space >> (in_block | invalid_try_syntax_error); Try = key("try") >> -ExistentialOp >> space >> (in_block | Exp | invalid_try_syntax_error) >> -CatchBlock; list_value = @@ -622,24 +631,28 @@ YueParser::YueParser() { list_lit_lines = +space_break >> list_lit_line >> *(-(space >> ',') >> space_break >> list_lit_line) >> -(space >> ','); + end_brackets_expression = ']' | brackets_expression_error; + Comprehension = '[' >> not_('[') >> Seperator >> space >> ( disable_for_rule(list_value) >> space >> ( - CompInner >> space >> ']' | - (list_value_list >> -(space >> ',') | space >> ',') >> -list_lit_lines >> white >> ']' + CompFor >> space >> end_brackets_expression | + (list_value_list >> -(space >> ',') | space >> ',') >> -list_lit_lines >> white >> end_brackets_expression ) | - list_lit_lines >> white >> ']' | + list_lit_lines >> white >> end_brackets_expression | white >> ']' >> not_(space >> '=') ); - CompValue = ',' >> space >> Exp; - TblComprehension = and_('{') >> ('{' >> space >> disable_for_rule(Exp >> space >> -(CompValue >> space)) >> CompInner >> space >> '}' | braces_expression_error); + end_braces_expression = '}' | braces_expression_error; - CompInner = Seperator >> (CompForEach | CompFor) >> *(space >> comp_clause); + CompValue = ',' >> space >> must_exp; + TblComprehension = '{' >> space >> disable_for_rule(Exp >> space >> -(CompValue >> space)) >> (CompFor | braces_expression_error) >> space >> end_braces_expression; + + CompFor = key("for") >> space >> Seperator >> (CompForNum | CompForEach) >> *(space >> comp_clause); StarExp = '*' >> space >> must_exp; - CompForEach = key("for") >> space >> AssignableNameList >> space >> key("in") >> space >> (StarExp | must_exp); - CompFor = key("for") >> space >> Variable >> space >> '=' >> space >> must_exp >> space >> ',' >> space >> must_exp >> -ForStepValue; - comp_clause = CompFor | CompForEach | key("when") >> space >> must_exp; + CompForEach = AssignableNameList >> space >> key("in") >> space >> (StarExp | must_exp); + CompForNum = Variable >> space >> '=' >> space >> must_exp >> space >> ',' >> space >> must_exp >> -ForStepValue; + comp_clause = key("when") >> space >> must_exp | key("for") >> space >> (CompForNum | CompForEach); Assign = '=' >> space >> Seperator >> ( With | If | Switch | TableBlock | @@ -794,7 +807,7 @@ YueParser::YueParser() { Metamethod = '<' >> space >> meta_index >> space >> '>'; ExistentialOp = '?' >> not_('?'); - TableAppendingOp = and_('[') >> ("[]" | brackets_expression_error); + TableAppendingOp = and_('[') >> "[]"; PlainItem = +any_char; chain_call = ( @@ -819,7 +832,7 @@ YueParser::YueParser() { chain_with_colon = +chain_item >> -colon_chain; chain_items = chain_with_colon | colon_chain; - index = '[' >> not_('[') >> space >> (ReversedIndex >> and_(space >> ']') | Exp) >> space >> (']' | brackets_expression_error); + index = '[' >> not_('[') >> space >> (ReversedIndex >> and_(space >> ']') | Exp) >> space >> ']'; ReversedIndex = '#' >> space >> -('-' >> space >> Exp); chain_item = Invoke >> -ExistentialOp | @@ -859,10 +872,8 @@ YueParser::YueParser() { SpreadExp | NormalDef; - table_value_list = table_value >> *(space >> ',' >> space >> table_value); - table_lit_line = ( - push_indent_match >> (space >> table_value_list >> pop_indent | pop_indent) + push_indent_match >> (space >> not_(line_break | '}') >> (table_value | expected_expression_error) >> *(space >> ',' >> space >> table_value) >> pop_indent | pop_indent) ) | ( space ); @@ -871,9 +882,11 @@ YueParser::YueParser() { TableLit = '{' >> Seperator >> - -(space >> table_value_list >> -(space >> ',')) >> - -table_lit_lines >> - white >> '}'; + -(space >> table_value >> *(space >> ',' >> space >> table_value) >> -(space >> ',')) >> + ( + table_lit_lines >> white >> end_braces_expression | + white >> '}' + ); table_block_inner = Seperator >> key_value_line >> *(+space_break >> key_value_line); TableBlock = +space_break >> advance_match >> ensure(table_block_inner, pop_indent); @@ -955,22 +968,20 @@ YueParser::YueParser() { invalid_export_syntax_error ) >> not_(space >> StatementAppendix); - check_keyword_as_identifier = and_(LuaKeyword >> not_alpha_num) >> keyword_as_identifier_syntax_error; - - VariablePair = ':' >> (Variable | check_keyword_as_identifier); + VariablePair = ':' >> Variable; NormalPair = ( KeyName | '[' >> not_('[') >> space >> Exp >> space >> ']' | String - ) >> ':' >> not_(':') >> space >> - (Exp | TableBlock | +space_break >> space >> Exp | check_keyword_as_identifier); + ) >> ':' >> not_(':' | '=' >> not_('>')) >> space >> + (Exp | TableBlock | +space_break >> space >> Exp | expected_expression_error); - MetaVariablePair = ":<" >> space >> Variable >> space >> '>'; + MetaVariablePair = ":<" >> space >> must_variable >> space >> '>'; MetaNormalPair = '<' >> space >> -meta_index >> space >> ">:" >> space >> - (Exp | TableBlock | +space_break >> space >> Exp | check_keyword_as_identifier); + (Exp | TableBlock | +space_break >> space >> Exp | expected_expression_error); destruct_def = -(space >> '=' >> space >> Exp); VariablePairDef = VariablePair >> destruct_def; @@ -1010,7 +1021,7 @@ YueParser::YueParser() { white >> VarArg >> -(space >> '`' >> space >> Name) >> check_vararg_position ); - OuterVarShadow = key("using") >> space >> (NameList | key("nil")); + OuterVarShadow = key("using") >> space >> (key("nil") | NameList); FnArgsDef = '(' >> *space_break >> -FnArgDefList >> -(white >> OuterVarShadow) >> white >> -(and_(',') >> unexpected_comma_error) >> ')'; FnArrow = expr("->") | "=>"; @@ -1028,13 +1039,15 @@ YueParser::YueParser() { MacroLit = -(macro_args_def >> space) >> "->" >> space >> Body; MacroFunc = MacroName >> (Invoke | InvokeArgs); Macro = key("macro") >> space >> ( - UnicodeName >> space >> '=' >> space >> (MacroLit | MacroFunc) | + UnicodeName >> space >> '=' >> space >> (MacroLit | MacroFunc | expected_expression_error) | invalid_macro_definition_error ); MacroInPlace = '$' >> space >> "->" >> space >> Body; - NameList = Seperator >> Variable >> *(space >> ',' >> space >> Variable); - NameOrDestructure = Variable | TableLit | Comprehension | SimpleTable; + must_variable = Variable | and_(LuaKeyword >> not_alpha_num) >> keyword_as_identifier_syntax_error | expected_indentifier_error; + + NameList = Seperator >> must_variable >> *(space >> ',' >> space >> must_variable); + NameOrDestructure = Variable | TableLit | Comprehension | SimpleTable | expected_expression_error; AssignableNameList = Seperator >> NameOrDestructure >> *(space >> ',' >> space >> NameOrDestructure); FnArrowBack = '<' >> set("-="); @@ -1074,7 +1087,7 @@ YueParser::YueParser() { SimpleValue = TableLit | ConstValue | If | Switch | Try | With | - ClassDecl | ForEach | For | While | Repeat | Do | + ClassDecl | For | While | Repeat | Do | UnaryValue | TblComprehension | Comprehension | FunLit | Num | VarArg; @@ -1085,10 +1098,10 @@ YueParser::YueParser() { ChainAssign = Seperator >> Exp >> +(space >> '=' >> space >> Exp >> space >> and_('=')) >> space >> Assign; - StatementAppendix = (IfLine | WhileLine | CompInner) >> space; + StatementAppendix = (IfLine | WhileLine | CompFor) >> space; Statement = ( - Import | While | Repeat | For | ForEach | + Import | While | Repeat | For | Return | Local | Global | Export | Macro | MacroInPlace | BreakLoop | Label | Goto | ShortTabAppending | LocalAttrib | Backcall | PipeBody | ExpListAssign | ChainAssign | @@ -1133,7 +1146,9 @@ YueParser::YueParser() { BlockEnd = Block >> plain_white >> stop; File = -shebang >> -Block >> plain_white >> stop; - lax_line = advance_match >> ensure(*(not_(stop) >> any()), pop_indent) | line >> and_(stop) | check_indent_match >> *(not_(stop) >> any()); + lax_line = advance_match >> ensure(*(not_(stop) >> any()), pop_indent) | + line >> and_(stop) | + check_indent_match >> *(not_(stop) >> any()); } // clang-format on diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 3a726c3..24ae490 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h @@ -178,9 +178,15 @@ private: NONE_AST_RULE(invalid_with_syntax_error); NONE_AST_RULE(invalid_try_syntax_error); NONE_AST_RULE(keyword_as_identifier_syntax_error); - NONE_AST_RULE(check_keyword_as_identifier); NONE_AST_RULE(invalid_number_literal_error); NONE_AST_RULE(invalid_import_literal_error); + NONE_AST_RULE(expected_indentifier_error); + + NONE_AST_RULE(must_exp); + NONE_AST_RULE(must_unary_exp); + NONE_AST_RULE(must_variable); + NONE_AST_RULE(end_braces_expression); + NONE_AST_RULE(end_brackets_expression); NONE_AST_RULE(inc_exp_level); NONE_AST_RULE(dec_exp_level); @@ -290,7 +296,6 @@ private: NONE_AST_RULE(table_value); NONE_AST_RULE(table_lit_lines); NONE_AST_RULE(table_lit_line); - NONE_AST_RULE(table_value_list); NONE_AST_RULE(table_block_inner); NONE_AST_RULE(class_line); NONE_AST_RULE(key_value_line); @@ -306,8 +311,6 @@ private: NONE_AST_RULE(expo_value); NONE_AST_RULE(expo_exp); NONE_AST_RULE(exp_not_tab); - NONE_AST_RULE(must_exp); - NONE_AST_RULE(must_unary_exp); NONE_AST_RULE(local_const_item); NONE_AST_RULE(comment_line); NONE_AST_RULE(yue_line_comment); @@ -370,6 +373,7 @@ private: AST_RULE(Repeat); AST_RULE(ForStepValue); AST_RULE(For); + AST_RULE(ForNum); AST_RULE(ForEach); AST_RULE(Do); AST_RULE(CatchBlock); @@ -379,8 +383,8 @@ private: AST_RULE(TblComprehension); AST_RULE(StarExp); AST_RULE(CompForEach); + AST_RULE(CompForNum); AST_RULE(CompFor); - AST_RULE(CompInner); AST_RULE(Assign); AST_RULE(UpdateOp); AST_RULE(Update); -- cgit v1.2.3-55-g6feb