diff options
| author | Li Jin <dragon-fly@qq.com> | 2025-07-17 18:02:39 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2025-07-17 18:02:39 +0800 |
| commit | c03bf36db11bcd90034b0e67bd1f5c8c0765eb7f (patch) | |
| tree | 18d18739cb2b99600f0d93fb9d8e7097a8584a7e /src | |
| parent | 281149d74af1d218cc43fe57b1d68d3759ce6d0c (diff) | |
| download | yuescript-c03bf36db11bcd90034b0e67bd1f5c8c0765eb7f.tar.gz yuescript-c03bf36db11bcd90034b0e67bd1f5c8c0765eb7f.tar.bz2 yuescript-c03bf36db11bcd90034b0e67bd1f5c8c0765eb7f.zip | |
Added YAML multiline string and macro argument checking.
Diffstat (limited to '')
| -rw-r--r-- | src/yuescript/yue_ast.cpp | 24 | ||||
| -rw-r--r-- | src/yuescript/yue_ast.h | 28 | ||||
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 142 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.cpp | 34 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.h | 5 |
5 files changed, 221 insertions, 12 deletions
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp index da99d07..bacdc01 100644 --- a/src/yuescript/yue_ast.cpp +++ b/src/yuescript/yue_ast.cpp | |||
| @@ -962,6 +962,30 @@ std::string DoubleString_t::to_string(void* ud) const { | |||
| 962 | } | 962 | } |
| 963 | return '"' + join(temp) + '"'; | 963 | return '"' + join(temp) + '"'; |
| 964 | } | 964 | } |
| 965 | std::string YAMLLineInner_t::to_string(void* ud) const { | ||
| 966 | auto info = reinterpret_cast<YueFormat*>(ud); | ||
| 967 | return info->convert(this); | ||
| 968 | } | ||
| 969 | std::string YAMLLineContent_t::to_string(void* ud) const { | ||
| 970 | if (content.is<Exp_t>()) { | ||
| 971 | return "#{"s + content->to_string(ud) + '}'; | ||
| 972 | } | ||
| 973 | return content->to_string(ud); | ||
| 974 | } | ||
| 975 | std::string YAMLLine_t::to_string(void* ud) const { | ||
| 976 | str_list temp; | ||
| 977 | for (auto seg : segments.objects()) { | ||
| 978 | temp.emplace_back(seg->to_string(ud)); | ||
| 979 | } | ||
| 980 | return join(temp); | ||
| 981 | } | ||
| 982 | std::string YAMLMultiline_t::to_string(void* ud) const { | ||
| 983 | str_list temp; | ||
| 984 | for (auto seg : lines.objects()) { | ||
| 985 | temp.emplace_back(seg->to_string(ud)); | ||
| 986 | } | ||
| 987 | return "|\n" + join(temp, "\n"sv); | ||
| 988 | } | ||
| 965 | std::string String_t::to_string(void* ud) const { | 989 | std::string String_t::to_string(void* ud) const { |
| 966 | return str->to_string(ud); | 990 | return str->to_string(ud); |
| 967 | } | 991 | } |
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index d396d82..c529f34 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
| @@ -591,8 +591,28 @@ AST_NODE(DoubleString) | |||
| 591 | AST_MEMBER(DoubleString, &sep, &segments) | 591 | AST_MEMBER(DoubleString, &sep, &segments) |
| 592 | AST_END(DoubleString) | 592 | AST_END(DoubleString) |
| 593 | 593 | ||
| 594 | AST_LEAF(YAMLLineInner) | ||
| 595 | AST_END(YAMLLineInner) | ||
| 596 | |||
| 597 | AST_NODE(YAMLLineContent) | ||
| 598 | ast_sel<true, YAMLLineInner_t, Exp_t> content; | ||
| 599 | AST_MEMBER(YAMLLineContent, &content) | ||
| 600 | AST_END(YAMLLineContent) | ||
| 601 | |||
| 602 | AST_NODE(YAMLLine) | ||
| 603 | ast_ptr<true, Seperator_t> sep; | ||
| 604 | ast_list<false, YAMLLineContent_t> segments; | ||
| 605 | AST_MEMBER(YAMLLine, &sep, &segments) | ||
| 606 | AST_END(YAMLLine) | ||
| 607 | |||
| 608 | AST_NODE(YAMLMultiline) | ||
| 609 | ast_ptr<true, Seperator_t> sep; | ||
| 610 | ast_list<true, YAMLLine_t> lines; | ||
| 611 | AST_MEMBER(YAMLMultiline, &sep, &lines) | ||
| 612 | AST_END(YAMLMultiline) | ||
| 613 | |||
| 594 | AST_NODE(String) | 614 | AST_NODE(String) |
| 595 | ast_sel<true, DoubleString_t, SingleString_t, LuaString_t> str; | 615 | ast_sel<true, DoubleString_t, SingleString_t, LuaString_t, YAMLMultiline_t> str; |
| 596 | AST_MEMBER(String, &str) | 616 | AST_MEMBER(String, &str) |
| 597 | AST_END(String) | 617 | AST_END(String) |
| 598 | 618 | ||
| @@ -752,15 +772,17 @@ AST_END(Export) | |||
| 752 | AST_NODE(FnArgDef) | 772 | AST_NODE(FnArgDef) |
| 753 | ast_sel<true, Variable_t, SelfItem_t> name; | 773 | ast_sel<true, Variable_t, SelfItem_t> name; |
| 754 | ast_ptr<false, ExistentialOp_t> op; | 774 | ast_ptr<false, ExistentialOp_t> op; |
| 775 | ast_ptr<false, Name_t> label; | ||
| 755 | ast_ptr<false, Exp_t> defaultValue; | 776 | ast_ptr<false, Exp_t> defaultValue; |
| 756 | AST_MEMBER(FnArgDef, &name, &op, &defaultValue) | 777 | AST_MEMBER(FnArgDef, &name, &op, &label, &defaultValue) |
| 757 | AST_END(FnArgDef) | 778 | AST_END(FnArgDef) |
| 758 | 779 | ||
| 759 | AST_NODE(FnArgDefList) | 780 | AST_NODE(FnArgDefList) |
| 760 | ast_ptr<true, Seperator_t> sep; | 781 | ast_ptr<true, Seperator_t> sep; |
| 761 | ast_list<false, FnArgDef_t> definitions; | 782 | ast_list<false, FnArgDef_t> definitions; |
| 762 | ast_ptr<false, VarArg_t> varArg; | 783 | ast_ptr<false, VarArg_t> varArg; |
| 763 | AST_MEMBER(FnArgDefList, &sep, &definitions, &varArg) | 784 | ast_ptr<false, Name_t> label; |
| 785 | AST_MEMBER(FnArgDefList, &sep, &definitions, &varArg, &label) | ||
| 764 | AST_END(FnArgDefList) | 786 | AST_END(FnArgDefList) |
| 765 | 787 | ||
| 766 | AST_NODE(OuterVarShadow) | 788 | AST_NODE(OuterVarShadow) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 9f5a41e..35d99bd 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 | ||
| 81 | const std::string_view version = "0.29.0"sv; | 81 | const std::string_view version = "0.29.1"sv; |
| 82 | const std::string_view extension = "yue"sv; | 82 | const std::string_view extension = "yue"sv; |
| 83 | 83 | ||
| 84 | class CompileError : public std::logic_error { | 84 | class CompileError : public std::logic_error { |
| @@ -5418,18 +5418,29 @@ private: | |||
| 5418 | auto macroLit = macro->decl.to<MacroLit_t>(); | 5418 | auto macroLit = macro->decl.to<MacroLit_t>(); |
| 5419 | auto argsDef = macroLit->argsDef.get(); | 5419 | auto argsDef = macroLit->argsDef.get(); |
| 5420 | str_list newArgs; | 5420 | str_list newArgs; |
| 5421 | str_list argChecks; | ||
| 5422 | bool hasCheck = false; | ||
| 5421 | if (argsDef) { | 5423 | if (argsDef) { |
| 5422 | for (auto def_ : argsDef->definitions.objects()) { | 5424 | for (auto def_ : argsDef->definitions.objects()) { |
| 5423 | auto def = static_cast<FnArgDef_t*>(def_); | 5425 | auto def = static_cast<FnArgDef_t*>(def_); |
| 5424 | if (def->name.is<SelfItem_t>()) { | 5426 | if (def->name.is<SelfItem_t>()) { |
| 5425 | throw CompileError("self name is not supported for macro function argument"sv, def->name); | 5427 | throw CompileError("self name is not supported for macro function argument"sv, def->name); |
| 5426 | } else { | 5428 | } else { |
| 5429 | if (def->op) throw CompileError("invalid existence checking"sv, def->op); | ||
| 5430 | if (def->label) { | ||
| 5431 | hasCheck = true; | ||
| 5432 | const auto& astName = argChecks.emplace_back(_parser.toString(def->label)); | ||
| 5433 | if (!_parser.hasAST(astName)) { | ||
| 5434 | throw CompileError("invalid AST name"sv, def->label); | ||
| 5435 | } | ||
| 5436 | } else { | ||
| 5437 | argChecks.emplace_back(); | ||
| 5438 | } | ||
| 5427 | std::string defVal; | 5439 | std::string defVal; |
| 5428 | if (def->defaultValue) { | 5440 | if (def->defaultValue) { |
| 5429 | defVal = _parser.toString(def->defaultValue); | 5441 | defVal = _parser.toString(def->defaultValue); |
| 5430 | Utils::trim(defVal); | 5442 | Utils::trim(defVal); |
| 5431 | defVal.insert(0, "=[==========["sv); | 5443 | defVal = '=' + Utils::toLuaString(defVal); |
| 5432 | defVal.append("]==========]"sv); | ||
| 5433 | } | 5444 | } |
| 5434 | newArgs.emplace_back(_parser.toString(def->name) + defVal); | 5445 | newArgs.emplace_back(_parser.toString(def->name) + defVal); |
| 5435 | } | 5446 | } |
| @@ -5438,6 +5449,14 @@ private: | |||
| 5438 | newArgs.emplace_back(_parser.toString(argsDef->varArg)); | 5449 | newArgs.emplace_back(_parser.toString(argsDef->varArg)); |
| 5439 | } | 5450 | } |
| 5440 | } | 5451 | } |
| 5452 | if (argsDef->label) { | ||
| 5453 | hasCheck = true; | ||
| 5454 | const auto& astName = _parser.toString(argsDef->label); | ||
| 5455 | if (!_parser.hasAST(astName)) { | ||
| 5456 | throw CompileError("invalid AST name"sv, argsDef->label); | ||
| 5457 | } | ||
| 5458 | argChecks.emplace_back("..."s + astName); | ||
| 5459 | } | ||
| 5441 | std::string macroCodes = "_ENV=require('yue').macro_env\n("s + join(newArgs, ","sv) + ")->"s + _parser.toString(macroLit->body); | 5460 | std::string macroCodes = "_ENV=require('yue').macro_env\n("s + join(newArgs, ","sv) + ")->"s + _parser.toString(macroLit->body); |
| 5442 | auto chunkName = "=(macro "s + macroName + ')'; | 5461 | auto chunkName = "=(macro "s + macroName + ')'; |
| 5443 | pushCurrentModule(); // cur | 5462 | pushCurrentModule(); // cur |
| @@ -5467,6 +5486,24 @@ private: | |||
| 5467 | throw CompileError("failed to generate macro function\n"s + err, macroLit); | 5486 | throw CompileError("failed to generate macro function\n"s + err, macroLit); |
| 5468 | } // cur true macro | 5487 | } // cur true macro |
| 5469 | lua_remove(L, -2); // cur macro | 5488 | lua_remove(L, -2); // cur macro |
| 5489 | if (hasCheck) { | ||
| 5490 | lua_createtable(L, 0, 0); // cur macro checks | ||
| 5491 | int i = 1; | ||
| 5492 | for (const auto& check : argChecks) { | ||
| 5493 | if (check.empty()) { | ||
| 5494 | lua_pushboolean(L, 0); | ||
| 5495 | lua_rawseti(L, -2, i); | ||
| 5496 | } else { | ||
| 5497 | lua_pushlstring(L, check.c_str(), check.size()); | ||
| 5498 | lua_rawseti(L, -2, i); | ||
| 5499 | } | ||
| 5500 | i++; | ||
| 5501 | } | ||
| 5502 | lua_createtable(L, 2, 0); // cur macro checks macrotab | ||
| 5503 | lua_insert(L, -3); // cur macrotab macro checks | ||
| 5504 | lua_rawseti(L, -3, 1); // macrotab[1] = checks, cur macrotab macro | ||
| 5505 | lua_rawseti(L, -2, 2); // macrotab[2] = macro, cur macrotab | ||
| 5506 | } // cur macro | ||
| 5470 | if (exporting && _config.exporting && !_config.module.empty()) { | 5507 | if (exporting && _config.exporting && !_config.module.empty()) { |
| 5471 | pushModuleTable(_config.module); // cur macro module | 5508 | pushModuleTable(_config.module); // cur macro module |
| 5472 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro module name | 5509 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro module name |
| @@ -5624,7 +5661,11 @@ private: | |||
| 5624 | auto def = static_cast<FnArgDef_t*>(_def); | 5661 | auto def = static_cast<FnArgDef_t*>(_def); |
| 5625 | auto& arg = argItems.emplace_back(); | 5662 | auto& arg = argItems.emplace_back(); |
| 5626 | switch (def->name->get_id()) { | 5663 | switch (def->name->get_id()) { |
| 5627 | case id<Variable_t>(): arg.name = variableToString(static_cast<Variable_t*>(def->name.get())); break; | 5664 | case id<Variable_t>(): { |
| 5665 | if (def->op) throw CompileError("invalid existence checking"sv, def->op); | ||
| 5666 | arg.name = variableToString(static_cast<Variable_t*>(def->name.get())); | ||
| 5667 | break; | ||
| 5668 | } | ||
| 5628 | case id<SelfItem_t>(): { | 5669 | case id<SelfItem_t>(): { |
| 5629 | assignSelf = true; | 5670 | assignSelf = true; |
| 5630 | if (def->op) { | 5671 | if (def->op) { |
| @@ -6748,7 +6789,25 @@ private: | |||
| 6748 | break; | 6789 | break; |
| 6749 | } | 6790 | } |
| 6750 | } | 6791 | } |
| 6751 | if (!lua_isfunction(L, -1)) { | 6792 | str_list checks; |
| 6793 | if (lua_istable(L, -1)) { | ||
| 6794 | lua_rawgeti(L, -1, 1); // cur macrotab checks | ||
| 6795 | int len = lua_objlen(L, -1); | ||
| 6796 | for (int i = 1; i <= len; i++) { | ||
| 6797 | lua_rawgeti(L, -1, i); | ||
| 6798 | if (lua_toboolean(L, -1) == 0) { | ||
| 6799 | checks.emplace_back(); | ||
| 6800 | } else { | ||
| 6801 | size_t str_len = 0; | ||
| 6802 | auto str = lua_tolstring(L, -1, &str_len); | ||
| 6803 | checks.emplace_back(std::string{str, str_len}); | ||
| 6804 | } | ||
| 6805 | lua_pop(L, 1); | ||
| 6806 | } | ||
| 6807 | lua_pop(L, 1); | ||
| 6808 | lua_rawgeti(L, -1, 2); // cur macrotab macroFunc | ||
| 6809 | lua_remove(L, -2); // cur macroFunc | ||
| 6810 | } else if (!lua_isfunction(L, -1)) { | ||
| 6752 | auto code = expandBuiltinMacro(macroName, x); | 6811 | auto code = expandBuiltinMacro(macroName, x); |
| 6753 | if (!code.empty()) return code; | 6812 | if (!code.empty()) return code; |
| 6754 | if (macroName == "is_ast"sv) { | 6813 | if (macroName == "is_ast"sv) { |
| @@ -6796,8 +6855,31 @@ private: | |||
| 6796 | if (!lua_checkstack(L, argStrs.size())) { | 6855 | if (!lua_checkstack(L, argStrs.size())) { |
| 6797 | throw CompileError("too much macro params"s, x); | 6856 | throw CompileError("too much macro params"s, x); |
| 6798 | } | 6857 | } |
| 6858 | auto checkIt = checks.begin(); | ||
| 6859 | node_container::const_iterator argIt; | ||
| 6860 | if (args) { | ||
| 6861 | argIt = args->begin(); | ||
| 6862 | } | ||
| 6799 | for (const auto& arg : argStrs) { | 6863 | for (const auto& arg : argStrs) { |
| 6864 | if (checkIt != checks.end()) { | ||
| 6865 | if (checkIt->empty()) { | ||
| 6866 | ++checkIt; | ||
| 6867 | } else { | ||
| 6868 | if ((*checkIt)[0] == '.') { | ||
| 6869 | auto astName = checkIt->substr(3); | ||
| 6870 | if (!_parser.match(astName, arg)) { | ||
| 6871 | throw CompileError("expecting \""s + astName + "\", AST mismatch"s, *argIt); | ||
| 6872 | } | ||
| 6873 | } else { | ||
| 6874 | if (!_parser.match(*checkIt, arg)) { | ||
| 6875 | throw CompileError("expecting \""s + *checkIt + "\", AST mismatch"s, *argIt); | ||
| 6876 | } | ||
| 6877 | ++checkIt; | ||
| 6878 | } | ||
| 6879 | } | ||
| 6880 | } | ||
| 6800 | lua_pushlstring(L, arg.c_str(), arg.size()); | 6881 | lua_pushlstring(L, arg.c_str(), arg.size()); |
| 6882 | ++argIt; | ||
| 6801 | } // cur pcall macroFunc args... | 6883 | } // cur pcall macroFunc args... |
| 6802 | bool success = lua_pcall(L, static_cast<int>(argStrs.size()), 1, 0) == 0; | 6884 | bool success = lua_pcall(L, static_cast<int>(argStrs.size()), 1, 0) == 0; |
| 6803 | if (!success) { // cur err | 6885 | if (!success) { // cur err |
| @@ -9096,12 +9178,62 @@ private: | |||
| 9096 | out.push_back(temp.empty() ? "\"\""s : join(temp, " .. "sv)); | 9178 | out.push_back(temp.empty() ? "\"\""s : join(temp, " .. "sv)); |
| 9097 | } | 9179 | } |
| 9098 | 9180 | ||
| 9181 | void transformYAMLMultiline(YAMLMultiline_t* multiline, str_list& out) { | ||
| 9182 | std::optional<std::string_view> indent; | ||
| 9183 | str_list temp; | ||
| 9184 | for (auto line_ : multiline->lines.objects()) { | ||
| 9185 | auto line = static_cast<YAMLLine_t*>(line_); | ||
| 9186 | if (!line->segments.empty()) { | ||
| 9187 | str_list segs; | ||
| 9188 | for (auto seg_ : line->segments.objects()) { | ||
| 9189 | auto content = static_cast<YAMLLineContent_t*>(seg_)->content.get(); | ||
| 9190 | switch (content->get_id()) { | ||
| 9191 | case id<YAMLLineInner_t>(): { | ||
| 9192 | auto str = _parser.toString(content); | ||
| 9193 | Utils::replace(str, "\r\n"sv, "\n"sv); | ||
| 9194 | Utils::replace(str, "\n"sv, "\\n"sv); | ||
| 9195 | Utils::replace(str, "\\#"sv, "#"sv); | ||
| 9196 | segs.push_back('\"' + str + '\"'); | ||
| 9197 | break; | ||
| 9198 | } | ||
| 9199 | case id<Exp_t>(): { | ||
| 9200 | transformExp(static_cast<Exp_t*>(content), segs, ExpUsage::Closure); | ||
| 9201 | segs.back() = globalVar("tostring"sv, content, AccessType::Read) + '(' + segs.back() + ')'; | ||
| 9202 | break; | ||
| 9203 | } | ||
| 9204 | default: YUEE("AST node mismatch", content); break; | ||
| 9205 | } | ||
| 9206 | } | ||
| 9207 | auto lineStr = join(segs, " .. "sv); | ||
| 9208 | if (!indent) { | ||
| 9209 | auto pos = lineStr.find_first_not_of("\t "sv, 1); | ||
| 9210 | if (pos == std::string::npos) { | ||
| 9211 | throw CompileError("expecting first line indent"sv, line); | ||
| 9212 | } | ||
| 9213 | indent = std::string_view{lineStr.c_str(), pos}; | ||
| 9214 | } else { | ||
| 9215 | if (std::string_view{lineStr}.substr(0, indent.value().size()) != indent.value()) { | ||
| 9216 | throw CompileError("inconsistent indent"sv, line); | ||
| 9217 | } | ||
| 9218 | } | ||
| 9219 | lineStr = '"' + lineStr.substr(indent.value().size()); | ||
| 9220 | temp.push_back(lineStr); | ||
| 9221 | } | ||
| 9222 | } | ||
| 9223 | auto str = join(temp, " .. '\\n' .. "sv); | ||
| 9224 | Utils::replace(str, "\" .. '\\n' .. \""sv, "\\n"sv); | ||
| 9225 | Utils::replace(str, "\" .. '\\n'"sv, "\\n\""sv); | ||
| 9226 | Utils::replace(str, "'\\n' .. \""sv, "\"\\n"sv); | ||
| 9227 | out.push_back(str); | ||
| 9228 | } | ||
| 9229 | |||
| 9099 | void transformString(String_t* string, str_list& out) { | 9230 | void transformString(String_t* string, str_list& out) { |
| 9100 | auto str = string->str.get(); | 9231 | auto str = string->str.get(); |
| 9101 | switch (str->get_id()) { | 9232 | switch (str->get_id()) { |
| 9102 | case id<SingleString_t>(): transformSingleString(static_cast<SingleString_t*>(str), out); break; | 9233 | case id<SingleString_t>(): transformSingleString(static_cast<SingleString_t*>(str), out); break; |
| 9103 | case id<DoubleString_t>(): transformDoubleString(static_cast<DoubleString_t*>(str), out); break; | 9234 | case id<DoubleString_t>(): transformDoubleString(static_cast<DoubleString_t*>(str), out); break; |
| 9104 | case id<LuaString_t>(): transformLuaString(static_cast<LuaString_t*>(str), out); break; | 9235 | case id<LuaString_t>(): transformLuaString(static_cast<LuaString_t*>(str), out); break; |
| 9236 | case id<YAMLMultiline_t>(): transformYAMLMultiline(static_cast<YAMLMultiline_t*>(str), out); break; | ||
| 9105 | default: YUEE("AST node mismatch", str); break; | 9237 | default: YUEE("AST node mismatch", str); break; |
| 9106 | } | 9238 | } |
| 9107 | } | 9239 | } |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 1011a49..eebc676 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -639,7 +639,15 @@ YueParser::YueParser() { | |||
| 639 | DoubleStringInner = +(not_("#{") >> double_string_plain); | 639 | DoubleStringInner = +(not_("#{") >> double_string_plain); |
| 640 | DoubleStringContent = DoubleStringInner | interp; | 640 | DoubleStringContent = DoubleStringInner | interp; |
| 641 | DoubleString = '"' >> Seperator >> *DoubleStringContent >> '"'; | 641 | DoubleString = '"' >> Seperator >> *DoubleStringContent >> '"'; |
| 642 | String = DoubleString | SingleString | LuaString; | 642 | |
| 643 | YAMLLineInner = +('\\' >> set("\"\\#") | not_("#{" | stop) >> any_char); | ||
| 644 | YAMLLineContent = YAMLLineInner | interp; | ||
| 645 | YAMLLine = check_indent_match >> Seperator >> +YAMLLineContent | | ||
| 646 | advance_match >> Seperator >> ensure(+YAMLLineContent, pop_indent) | | ||
| 647 | Seperator >> *set(" \t") >> and_(line_break); | ||
| 648 | YAMLMultiline = '|' >> Seperator >> +space_break >> advance_match >> ensure(YAMLLine >> *(*set(" \t") >> line_break >> YAMLLine), pop_indent); | ||
| 649 | |||
| 650 | String = DoubleString | SingleString | LuaString | YAMLMultiline; | ||
| 643 | 651 | ||
| 644 | lua_string_open = '[' >> *expr('=') >> '['; | 652 | lua_string_open = '[' >> *expr('=') >> '['; |
| 645 | lua_string_close = ']' >> *expr('=') >> ']'; | 653 | lua_string_close = ']' >> *expr('=') >> ']'; |
| @@ -883,11 +891,11 @@ YueParser::YueParser() { | |||
| 883 | 891 | ||
| 884 | fn_arg_def_lit_lines = fn_arg_def_lit_line >> *(-(space >> ',') >> space_break >> fn_arg_def_lit_line); | 892 | fn_arg_def_lit_lines = fn_arg_def_lit_line >> *(-(space >> ',') >> space_break >> fn_arg_def_lit_line); |
| 885 | 893 | ||
| 886 | FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '=' >> space >> Exp); | 894 | FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '`' >> space >> Name) >> -(space >> '=' >> space >> Exp); |
| 887 | 895 | ||
| 888 | FnArgDefList = Seperator >> ( | 896 | FnArgDefList = Seperator >> ( |
| 889 | fn_arg_def_lit_lines >> -(-(space >> ',') >> white >> VarArg) | | 897 | fn_arg_def_lit_lines >> -(-(space >> ',') >> white >> VarArg >> -(space >> '`' >> space >> Name)) | |
| 890 | white >> VarArg | 898 | white >> VarArg >> -(space >> '`' >> space >> Name) |
| 891 | ); | 899 | ); |
| 892 | 900 | ||
| 893 | OuterVarShadow = key("using") >> space >> (NameList | key("nil")); | 901 | OuterVarShadow = key("using") >> space >> (NameList | key("nil")); |
| @@ -1176,6 +1184,24 @@ void trim(std::string& str) { | |||
| 1176 | str.erase(0, str.find_first_not_of(" \t\r\n")); | 1184 | str.erase(0, str.find_first_not_of(" \t\r\n")); |
| 1177 | str.erase(str.find_last_not_of(" \t\r\n") + 1); | 1185 | str.erase(str.find_last_not_of(" \t\r\n") + 1); |
| 1178 | } | 1186 | } |
| 1187 | |||
| 1188 | std::string toLuaString(const std::string& input) { | ||
| 1189 | std::string luaStr = "\""; | ||
| 1190 | for (char c : input) { | ||
| 1191 | switch (c) { | ||
| 1192 | case '\"': luaStr += "\\\""; break; | ||
| 1193 | case '\\': luaStr += "\\\\"; break; | ||
| 1194 | case '\n': luaStr += "\\n"; break; | ||
| 1195 | case '\r': luaStr += "\\r"; break; | ||
| 1196 | case '\t': luaStr += "\\t"; break; | ||
| 1197 | default: | ||
| 1198 | luaStr += c; | ||
| 1199 | break; | ||
| 1200 | } | ||
| 1201 | } | ||
| 1202 | luaStr += "\""; | ||
| 1203 | return luaStr; | ||
| 1204 | } | ||
| 1179 | } // namespace Utils | 1205 | } // namespace Utils |
| 1180 | 1206 | ||
| 1181 | std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { | 1207 | std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 1057626..15f9277 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
| @@ -378,6 +378,10 @@ private: | |||
| 378 | AST_RULE(DoubleStringInner); | 378 | AST_RULE(DoubleStringInner); |
| 379 | AST_RULE(DoubleStringContent); | 379 | AST_RULE(DoubleStringContent); |
| 380 | AST_RULE(DoubleString); | 380 | AST_RULE(DoubleString); |
| 381 | AST_RULE(YAMLLineInner); | ||
| 382 | AST_RULE(YAMLLineContent); | ||
| 383 | AST_RULE(YAMLLine); | ||
| 384 | AST_RULE(YAMLMultiline); | ||
| 381 | AST_RULE(String); | 385 | AST_RULE(String); |
| 382 | AST_RULE(Parens); | 386 | AST_RULE(Parens); |
| 383 | AST_RULE(DotChainItem); | 387 | AST_RULE(DotChainItem); |
| @@ -453,6 +457,7 @@ private: | |||
| 453 | namespace Utils { | 457 | namespace Utils { |
| 454 | void replace(std::string& str, std::string_view from, std::string_view to); | 458 | void replace(std::string& str, std::string_view from, std::string_view to); |
| 455 | void trim(std::string& str); | 459 | void trim(std::string& str); |
| 460 | std::string toLuaString(const std::string& input); | ||
| 456 | } // namespace Utils | 461 | } // namespace Utils |
| 457 | 462 | ||
| 458 | } // namespace yue | 463 | } // namespace yue |
