diff options
| author | Li Jin <dragon-fly@qq.com> | 2025-12-08 10:21:10 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2025-12-08 10:21:10 +0800 |
| commit | bb563257953628a9849c8532a684b5064bf8e655 (patch) | |
| tree | a3604194c8e10d04246eb751143cf5da18356067 | |
| parent | 552c260d3c3e8d2c65125bba77b588d7e487d983 (diff) | |
| download | yuescript-main.tar.gz yuescript-main.tar.bz2 yuescript-main.zip | |
Diffstat (limited to '')
| -rw-r--r-- | spec/inputs/syntax.yue | 4 | ||||
| -rw-r--r-- | spec/inputs/unicode/syntax.yue | 4 | ||||
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 20 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.cpp | 43 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.h | 2 |
5 files changed, 51 insertions, 22 deletions
diff --git a/spec/inputs/syntax.yue b/spec/inputs/syntax.yue index 4c0c56c..eee518a 100644 --- a/spec/inputs/syntax.yue +++ b/spec/inputs/syntax.yue | |||
| @@ -392,7 +392,7 @@ invokeA( | |||
| 392 | v = { | 392 | v = { |
| 393 | a -1 | 393 | a -1 |
| 394 | a( | 394 | a( |
| 395 | -1) | 395 | -1) |
| 396 | a \ | 396 | a \ |
| 397 | - 1 | 397 | - 1 |
| 398 | a-1 | 398 | a-1 |
| @@ -405,7 +405,7 @@ v = { | |||
| 405 | 405 | ||
| 406 | a ~1 | 406 | a ~1 |
| 407 | a( | 407 | a( |
| 408 | ~1) | 408 | ~1) |
| 409 | a \ | 409 | a \ |
| 410 | ~ 1 | 410 | ~ 1 |
| 411 | a~1 | 411 | a~1 |
diff --git a/spec/inputs/unicode/syntax.yue b/spec/inputs/unicode/syntax.yue index 8a98416..01d5c87 100644 --- a/spec/inputs/unicode/syntax.yue +++ b/spec/inputs/unicode/syntax.yue | |||
| @@ -376,7 +376,7 @@ with 对象 | |||
| 376 | 变量v = { | 376 | 变量v = { |
| 377 | 变量a -1 | 377 | 变量a -1 |
| 378 | 变量a( | 378 | 变量a( |
| 379 | -1) | 379 | -1) |
| 380 | 变量a \ | 380 | 变量a \ |
| 381 | - 1 | 381 | - 1 |
| 382 | 变量a-1 | 382 | 变量a-1 |
| @@ -389,7 +389,7 @@ with 对象 | |||
| 389 | 389 | ||
| 390 | 变量a ~1 | 390 | 变量a ~1 |
| 391 | 变量a( | 391 | 变量a( |
| 392 | ~1) | 392 | ~1) |
| 393 | 变量a \ | 393 | 变量a \ |
| 394 | ~ 1 | 394 | ~ 1 |
| 395 | 变量a~1 | 395 | 变量a~1 |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 753ba7b..77643d3 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -876,6 +876,10 @@ private: | |||
| 876 | return false; | 876 | return false; |
| 877 | } | 877 | } |
| 878 | 878 | ||
| 879 | bool isListComp(Comprehension_t* comp) const { | ||
| 880 | return comp->items.size() == 2 && ast_is<CompFor_t>(comp->items.back()); | ||
| 881 | } | ||
| 882 | |||
| 879 | void markVarLocalConst(const std::string& name) { | 883 | void markVarLocalConst(const std::string& name) { |
| 880 | auto& scope = _scopes.back(); | 884 | auto& scope = _scopes.back(); |
| 881 | scope.vars->insert_or_assign(name, VarType::LocalConst); | 885 | scope.vars->insert_or_assign(name, VarType::LocalConst); |
| @@ -1474,7 +1478,7 @@ private: | |||
| 1474 | if (simpleValue->value.is<TableLit_t>()) { | 1478 | if (simpleValue->value.is<TableLit_t>()) { |
| 1475 | return true; | 1479 | return true; |
| 1476 | } else if (auto comp = simpleValue->value.as<Comprehension_t>()) { | 1480 | } else if (auto comp = simpleValue->value.as<Comprehension_t>()) { |
| 1477 | if (comp->items.size() != 2 || !ast_is<CompFor_t>(comp->items.back())) { | 1481 | if (!isListComp(comp)) { |
| 1478 | return true; | 1482 | return true; |
| 1479 | } | 1483 | } |
| 1480 | } | 1484 | } |
| @@ -1877,7 +1881,7 @@ private: | |||
| 1877 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Common); break; | 1881 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Common); break; |
| 1878 | case id<Comprehension_t>(): { | 1882 | case id<Comprehension_t>(): { |
| 1879 | auto comp = static_cast<Comprehension_t*>(value); | 1883 | auto comp = static_cast<Comprehension_t*>(value); |
| 1880 | if (comp->items.size() == 2 && ast_is<CompFor_t>(comp->items.back())) { | 1884 | if (isListComp(comp)) { |
| 1881 | transformCompCommon(comp, out); | 1885 | transformCompCommon(comp, out); |
| 1882 | } else { | 1886 | } else { |
| 1883 | specialSingleValue = false; | 1887 | specialSingleValue = false; |
| @@ -2468,7 +2472,7 @@ private: | |||
| 2468 | case id<Comprehension_t>(): { | 2472 | case id<Comprehension_t>(): { |
| 2469 | auto comp = static_cast<Comprehension_t*>(value); | 2473 | auto comp = static_cast<Comprehension_t*>(value); |
| 2470 | auto expList = assignment->expList.get(); | 2474 | auto expList = assignment->expList.get(); |
| 2471 | if (comp->items.size() == 2 && ast_is<CompFor_t>(comp->items.back())) { | 2475 | if (isListComp(comp)) { |
| 2472 | std::string preDefine = getPreDefineLine(assignment); | 2476 | std::string preDefine = getPreDefineLine(assignment); |
| 2473 | transformComprehension(comp, out, ExpUsage::Assignment, expList); | 2477 | transformComprehension(comp, out, ExpUsage::Assignment, expList); |
| 2474 | out.back().insert(0, preDefine); | 2478 | out.back().insert(0, preDefine); |
| @@ -2893,7 +2897,7 @@ private: | |||
| 2893 | if (auto tbA = item->get_by_path<TableLit_t>()) { | 2897 | if (auto tbA = item->get_by_path<TableLit_t>()) { |
| 2894 | tableItems = &tbA->values.objects(); | 2898 | tableItems = &tbA->values.objects(); |
| 2895 | } else if (auto tbB = item->get_by_path<Comprehension_t>()) { | 2899 | } else if (auto tbB = item->get_by_path<Comprehension_t>()) { |
| 2896 | if (tbB->items.size() == 2 && ast_is<CompFor_t>(tbB->items.back())) { | 2900 | if (isListComp(tbB)) { |
| 2897 | throw CompileError("invalid destructure value"sv, tbB); | 2901 | throw CompileError("invalid destructure value"sv, tbB); |
| 2898 | } | 2902 | } |
| 2899 | tableItems = &tbB->items.objects(); | 2903 | tableItems = &tbB->items.objects(); |
| @@ -2924,7 +2928,7 @@ private: | |||
| 2924 | } | 2928 | } |
| 2925 | case id<Comprehension_t>(): { | 2929 | case id<Comprehension_t>(): { |
| 2926 | auto table = static_cast<Comprehension_t*>(node); | 2930 | auto table = static_cast<Comprehension_t*>(node); |
| 2927 | if (table->items.size() == 2 && ast_is<CompFor_t>(table->items.back())) { | 2931 | if (isListComp(table)) { |
| 2928 | throw CompileError("invalid destructure value"sv, table); | 2932 | throw CompileError("invalid destructure value"sv, table); |
| 2929 | } | 2933 | } |
| 2930 | tableItems = &table->items.objects(); | 2934 | tableItems = &table->items.objects(); |
| @@ -3295,7 +3299,7 @@ private: | |||
| 3295 | if (auto tab = sVal->value.as<TableLit_t>()) { | 3299 | if (auto tab = sVal->value.as<TableLit_t>()) { |
| 3296 | destructNode = tab; | 3300 | destructNode = tab; |
| 3297 | } else if (auto comp = sVal->value.as<Comprehension_t>()) { | 3301 | } else if (auto comp = sVal->value.as<Comprehension_t>()) { |
| 3298 | if (comp->items.size() != 2 || !ast_is<CompFor_t>(comp->items.back())) { | 3302 | if (!isListComp(comp)) { |
| 3299 | destructNode = comp; | 3303 | destructNode = comp; |
| 3300 | } | 3304 | } |
| 3301 | } | 3305 | } |
| @@ -7422,7 +7426,7 @@ private: | |||
| 7422 | } | 7426 | } |
| 7423 | } | 7427 | } |
| 7424 | } else if (auto comp = sval->value.as<Comprehension_t>()) { | 7428 | } else if (auto comp = sval->value.as<Comprehension_t>()) { |
| 7425 | if (comp->items.size() != 2 || !ast_is<CompFor_t>(comp->items.back())) { | 7429 | if (!isListComp(comp)) { |
| 7426 | discrete = inExp->new_ptr<ExpList_t>(); | 7430 | discrete = inExp->new_ptr<ExpList_t>(); |
| 7427 | for (ast_node* val : comp->items.objects()) { | 7431 | for (ast_node* val : comp->items.objects()) { |
| 7428 | if (auto def = ast_cast<NormalDef_t>(val)) { | 7432 | if (auto def = ast_cast<NormalDef_t>(val)) { |
| @@ -8285,7 +8289,7 @@ private: | |||
| 8285 | 8289 | ||
| 8286 | void transformComprehension(Comprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 8290 | void transformComprehension(Comprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
| 8287 | auto x = comp; | 8291 | auto x = comp; |
| 8288 | if (comp->items.size() != 2 || !ast_is<CompFor_t>(comp->items.back())) { | 8292 | if (!isListComp(comp)) { |
| 8289 | switch (usage) { | 8293 | switch (usage) { |
| 8290 | case ExpUsage::Assignment: { | 8294 | case ExpUsage::Assignment: { |
| 8291 | auto tableLit = x->new_ptr<TableLit_t>(); | 8295 | auto tableLit = x->new_ptr<TableLit_t>(); |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 1b72a8c..1999721 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -50,6 +50,15 @@ public: | |||
| 50 | } \ | 50 | } \ |
| 51 | } while (false) | 51 | } while (false) |
| 52 | 52 | ||
| 53 | #define RaiseErrorI(msg, item) \ | ||
| 54 | do { \ | ||
| 55 | if (reinterpret_cast<State*>(item.user_data)->lax) { \ | ||
| 56 | return -1; \ | ||
| 57 | } else { \ | ||
| 58 | throw ParserError(msg, item.begin); \ | ||
| 59 | } \ | ||
| 60 | } while (false) | ||
| 61 | |||
| 53 | // clang-format off | 62 | // clang-format off |
| 54 | YueParser::YueParser() { | 63 | YueParser::YueParser() { |
| 55 | plain_space = *set(" \t"); | 64 | plain_space = *set(" \t"); |
| @@ -316,14 +325,14 @@ YueParser::YueParser() { | |||
| 316 | for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) { | 325 | for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) { |
| 317 | switch (*i) { | 326 | switch (*i) { |
| 318 | case '\t': indent += 4; break; | 327 | case '\t': indent += 4; break; |
| 319 | default: RaiseError("can not mix the use of tabs and spaces as indents"sv, item); break; | 328 | default: RaiseErrorI("can not mix the use of tabs and spaces as indents"sv, item); break; |
| 320 | } | 329 | } |
| 321 | } | 330 | } |
| 322 | } else { | 331 | } else { |
| 323 | for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) { | 332 | for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) { |
| 324 | switch (*i) { | 333 | switch (*i) { |
| 325 | case ' ': indent++; break; | 334 | case ' ': indent++; break; |
| 326 | default: RaiseError("can not mix the use of tabs and spaces as indents"sv, item); break; | 335 | default: RaiseErrorI("can not mix the use of tabs and spaces as indents"sv, item); break; |
| 327 | } | 336 | } |
| 328 | } | 337 | } |
| 329 | } | 338 | } |
| @@ -357,6 +366,12 @@ YueParser::YueParser() { | |||
| 357 | } | 366 | } |
| 358 | } | 367 | } |
| 359 | State* st = reinterpret_cast<State*>(item.user_data); | 368 | State* st = reinterpret_cast<State*>(item.user_data); |
| 369 | if (st->indents.empty()) { | ||
| 370 | RaiseError("unknown indent level"sv, item); | ||
| 371 | } | ||
| 372 | if (st->indents.top() > indent) { | ||
| 373 | RaiseError("unexpected dedent"sv, item); | ||
| 374 | } | ||
| 360 | st->indents.push(indent); | 375 | st->indents.push(indent); |
| 361 | return true; | 376 | return true; |
| 362 | }); | 377 | }); |
| @@ -1014,16 +1029,24 @@ YueParser::YueParser() { | |||
| 1014 | 1029 | ||
| 1015 | FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '`' >> space >> Name) >> -(space >> '=' >> space >> Exp) | TableLit | SimpleTable; | 1030 | FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '`' >> space >> Name) >> -(space >> '=' >> space >> Exp) | TableLit | SimpleTable; |
| 1016 | 1031 | ||
| 1017 | check_vararg_position = and_(white >> ')') | white >> -(',' >> white) >> vararg_position_error; | 1032 | check_vararg_position = and_(white >> (')' | key("using"))) | white >> -(',' >> white) >> vararg_position_error; |
| 1018 | 1033 | ||
| 1019 | FnArgDefList = Seperator >> ( | 1034 | var_arg_def = ( |
| 1020 | fn_arg_def_lit_lines >> -(-(space >> ',') >> white >> VarArg >> -(space >> '`' >> space >> Name) >> check_vararg_position) | | 1035 | VarArg | |
| 1021 | white >> VarArg >> -(space >> '`' >> space >> Name) >> check_vararg_position | 1036 | +space_break >> push_indent_match >> ensure(space >> VarArg >> -(space >> '`' >> space >> Name), pop_indent) |
| 1022 | ); | 1037 | ) >> check_vararg_position; |
| 1038 | |||
| 1039 | FnArgDefList = Seperator >> | ||
| 1040 | -fn_arg_def_list >> | ||
| 1041 | -(-(space >> ',') >> +space_break >> fn_arg_def_lit_lines) >> | ||
| 1042 | -(-(space >> ',') >> space >> var_arg_def); | ||
| 1023 | 1043 | ||
| 1024 | OuterVarShadow = key("using") >> space >> (key("nil") | NameList); | 1044 | OuterVarShadow = key("using") >> space >> (key("nil") | NameList); |
| 1025 | 1045 | ||
| 1026 | FnArgsDef = '(' >> *space_break >> -FnArgDefList >> -(white >> OuterVarShadow) >> white >> -(and_(',') >> unexpected_comma_error) >> ')'; | 1046 | outer_var_shadow_def = OuterVarShadow | |
| 1047 | +space_break >> push_indent_match >> ensure(space >> OuterVarShadow, pop_indent); | ||
| 1048 | |||
| 1049 | FnArgsDef = '(' >> space >> -FnArgDefList >> -(space >> outer_var_shadow_def) >> white >> -(and_(',') >> unexpected_comma_error) >> ')'; | ||
| 1027 | FnArrow = expr("->") | "=>"; | 1050 | FnArrow = expr("->") | "=>"; |
| 1028 | FunLit = pl::user(true_(), [](const item_t& item) { | 1051 | FunLit = pl::user(true_(), [](const item_t& item) { |
| 1029 | State* st = reinterpret_cast<State*>(item.user_data); | 1052 | State* st = reinterpret_cast<State*>(item.user_data); |
| @@ -1035,11 +1058,11 @@ YueParser::YueParser() { | |||
| 1035 | ) >> space >> FnArrow >> -(space >> Body); | 1058 | ) >> space >> FnArrow >> -(space >> Body); |
| 1036 | 1059 | ||
| 1037 | MacroName = '$' >> UnicodeName; | 1060 | MacroName = '$' >> UnicodeName; |
| 1038 | macro_args_def = '(' >> white >> -FnArgDefList >> white >> -(and_(',') >> unexpected_comma_error) >> ')'; | 1061 | macro_args_def = '(' >> space >> -FnArgDefList >> white >> -(and_(',') >> unexpected_comma_error) >> ')'; |
| 1039 | MacroLit = -(macro_args_def >> space) >> "->" >> space >> Body; | 1062 | MacroLit = -(macro_args_def >> space) >> "->" >> space >> Body; |
| 1040 | MacroFunc = MacroName >> (Invoke | InvokeArgs); | 1063 | MacroFunc = MacroName >> (Invoke | InvokeArgs); |
| 1041 | Macro = key("macro") >> space >> ( | 1064 | Macro = key("macro") >> space >> ( |
| 1042 | UnicodeName >> space >> '=' >> space >> (MacroLit | MacroFunc | expected_expression_error) | | 1065 | UnicodeName >> space >> '=' >> space >> (MacroLit | MacroFunc | invalid_macro_definition_error) | |
| 1043 | invalid_macro_definition_error | 1066 | invalid_macro_definition_error |
| 1044 | ); | 1067 | ); |
| 1045 | MacroInPlace = '$' >> space >> "->" >> space >> Body; | 1068 | MacroInPlace = '$' >> space >> "->" >> space >> Body; |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 24ae490..b68742f 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
| @@ -280,6 +280,8 @@ private: | |||
| 280 | NONE_AST_RULE(fn_arg_def_lit_lines); | 280 | NONE_AST_RULE(fn_arg_def_lit_lines); |
| 281 | NONE_AST_RULE(destruct_def); | 281 | NONE_AST_RULE(destruct_def); |
| 282 | NONE_AST_RULE(macro_args_def); | 282 | NONE_AST_RULE(macro_args_def); |
| 283 | NONE_AST_RULE(var_arg_def); | ||
| 284 | NONE_AST_RULE(outer_var_shadow_def); | ||
| 283 | NONE_AST_RULE(chain_call); | 285 | NONE_AST_RULE(chain_call); |
| 284 | NONE_AST_RULE(chain_call_list); | 286 | NONE_AST_RULE(chain_call_list); |
| 285 | NONE_AST_RULE(chain_index_chain); | 287 | NONE_AST_RULE(chain_index_chain); |
