diff options
author | Li Jin <dragon-fly@qq.com> | 2021-11-22 01:48:26 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2021-11-22 01:48:26 +0800 |
commit | 125f709b065acb35bcd216001720c0bb4635dd25 (patch) | |
tree | 6059f57b12de2ba852197d3e2902b1741e47b42c | |
parent | 2ff18b4fb66d25d22e5a25fb386fe171853e0b06 (diff) | |
download | yuescript-125f709b065acb35bcd216001720c0bb4635dd25.tar.gz yuescript-125f709b065acb35bcd216001720c0bb4635dd25.tar.bz2 yuescript-125f709b065acb35bcd216001720c0bb4635dd25.zip |
clean up.
-rwxr-xr-x | src/yuescript/yue_ast.h | 14 | ||||
-rwxr-xr-x | src/yuescript/yue_compiler.cpp | 196 | ||||
-rwxr-xr-x | src/yuescript/yue_parser.cpp | 75 | ||||
-rwxr-xr-x | src/yuescript/yue_parser.h | 1 |
4 files changed, 145 insertions, 141 deletions
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 719b1cd..fe9c7b9 100755 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
@@ -176,7 +176,7 @@ AST_END(ImportTabLit) | |||
176 | 176 | ||
177 | AST_NODE(ImportAs) | 177 | AST_NODE(ImportAs) |
178 | ast_ptr<true, ImportLiteral_t> literal; | 178 | ast_ptr<true, ImportLiteral_t> literal; |
179 | ast_sel<false, Variable_t, ImportTabLit_t> target; | 179 | ast_sel<false, Variable_t, ImportTabLit_t, import_all_macro_t> target; |
180 | AST_MEMBER(ImportAs, &literal, &target) | 180 | AST_MEMBER(ImportAs, &literal, &target) |
181 | AST_END(ImportAs) | 181 | AST_END(ImportAs) |
182 | 182 | ||
@@ -691,7 +691,7 @@ AST_NODE(FunLit) | |||
691 | AST_END(FunLit) | 691 | AST_END(FunLit) |
692 | 692 | ||
693 | AST_NODE(MacroName) | 693 | AST_NODE(MacroName) |
694 | ast_ptr<false, Name_t> name; | 694 | ast_ptr<true, Name_t> name; |
695 | AST_MEMBER(MacroName, &name) | 695 | AST_MEMBER(MacroName, &name) |
696 | AST_END(MacroName) | 696 | AST_END(MacroName) |
697 | 697 | ||
@@ -701,6 +701,11 @@ AST_NODE(MacroLit) | |||
701 | AST_MEMBER(MacroLit, &argsDef, &body) | 701 | AST_MEMBER(MacroLit, &argsDef, &body) |
702 | AST_END(MacroLit) | 702 | AST_END(MacroLit) |
703 | 703 | ||
704 | AST_NODE(MacroInPlace) | ||
705 | ast_ptr<true, Body_t> body; | ||
706 | AST_MEMBER(MacroInPlace, &body) | ||
707 | AST_END(MacroInPlace) | ||
708 | |||
704 | AST_NODE(Macro) | 709 | AST_NODE(Macro) |
705 | ast_ptr<true, Name_t> name; | 710 | ast_ptr<true, Name_t> name; |
706 | ast_ptr<true, MacroLit_t> macroLit; | 711 | ast_ptr<true, MacroLit_t> macroLit; |
@@ -775,8 +780,9 @@ AST_END(statement_sep) | |||
775 | 780 | ||
776 | AST_NODE(Statement) | 781 | AST_NODE(Statement) |
777 | ast_sel<true, Import_t, While_t, Repeat_t, For_t, ForEach_t, | 782 | ast_sel<true, Import_t, While_t, Repeat_t, For_t, ForEach_t, |
778 | Return_t, Local_t, Global_t, Export_t, Macro_t, BreakLoop_t, | 783 | Return_t, Local_t, Global_t, Export_t, Macro_t, MacroInPlace_t, |
779 | Label_t, Goto_t, Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t> content; | 784 | BreakLoop_t, Label_t, Goto_t, Backcall_t, LocalAttrib_t, |
785 | PipeBody_t, ExpListAssign_t> content; | ||
780 | ast_ptr<false, statement_appendix_t> appendix; | 786 | ast_ptr<false, statement_appendix_t> appendix; |
781 | ast_ptr<false, statement_sep_t> needSep; | 787 | ast_ptr<false, statement_sep_t> needSep; |
782 | AST_MEMBER(Statement, &content, &appendix, &needSep) | 788 | AST_MEMBER(Statement, &content, &appendix, &needSep) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 14e33a5..b3f6bdd 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -60,7 +60,7 @@ using namespace parserlib; | |||
60 | 60 | ||
61 | typedef std::list<std::string> str_list; | 61 | typedef std::list<std::string> str_list; |
62 | 62 | ||
63 | const std::string_view version = "0.9.0"sv; | 63 | const std::string_view version = "0.9.1"sv; |
64 | const std::string_view extension = "yue"sv; | 64 | const std::string_view extension = "yue"sv; |
65 | 65 | ||
66 | class YueCompilerImpl { | 66 | class YueCompilerImpl { |
@@ -1007,6 +1007,7 @@ private: | |||
1007 | case id<Global_t>(): transformGlobal(static_cast<Global_t*>(content), out); break; | 1007 | case id<Global_t>(): transformGlobal(static_cast<Global_t*>(content), out); break; |
1008 | case id<Export_t>(): transformExport(static_cast<Export_t*>(content), out); break; | 1008 | case id<Export_t>(): transformExport(static_cast<Export_t*>(content), out); break; |
1009 | case id<Macro_t>(): transformMacro(static_cast<Macro_t*>(content), out, false); break; | 1009 | case id<Macro_t>(): transformMacro(static_cast<Macro_t*>(content), out, false); break; |
1010 | case id<MacroInPlace_t>(): transformMacroInPlace(static_cast<MacroInPlace_t*>(content)); break; | ||
1010 | case id<BreakLoop_t>(): transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; | 1011 | case id<BreakLoop_t>(): transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; |
1011 | case id<Label_t>(): transformLabel(static_cast<Label_t*>(content), out); break; | 1012 | case id<Label_t>(): transformLabel(static_cast<Label_t*>(content), out); break; |
1012 | case id<Goto_t>(): transformGoto(static_cast<Goto_t*>(content), out); break; | 1013 | case id<Goto_t>(): transformGoto(static_cast<Goto_t*>(content), out); break; |
@@ -3919,6 +3920,55 @@ private: | |||
3919 | } | 3920 | } |
3920 | } | 3921 | } |
3921 | 3922 | ||
3923 | void transformMacroInPlace(MacroInPlace_t* macroInPlace) { | ||
3924 | #ifdef YUE_NO_MACRO | ||
3925 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, macroInPlace)); | ||
3926 | #else // YUE_NO_MACRO | ||
3927 | auto x = macroInPlace; | ||
3928 | pushCurrentModule(); // cur | ||
3929 | int top = lua_gettop(L) - 1; | ||
3930 | DEFER(lua_settop(L, top)); | ||
3931 | lua_pop(L, 1); // empty | ||
3932 | auto fcodes = _parser.toString(macroInPlace).substr(1); | ||
3933 | Utils::trim(fcodes); | ||
3934 | pushYue("loadstring"sv); // loadstring | ||
3935 | lua_pushlstring(L, fcodes.c_str(), fcodes.size()); // loadstring codes | ||
3936 | lua_pushliteral(L, "=(macro in-place)"); // loadstring codes chunk | ||
3937 | pushOptions(macroInPlace->m_begin.m_line - 1); // loadstring codes chunk options | ||
3938 | if (lua_pcall(L, 3, 2, 0) != 0) { // loadstring(codes,chunk,options), f err | ||
3939 | std::string err = lua_tostring(L, -1); | ||
3940 | throw std::logic_error(_info.errorMessage("failed to load macro codes\n"s + err, x)); | ||
3941 | } // f err | ||
3942 | if (lua_isnil(L, -2) != 0) { // f == nil, f err | ||
3943 | std::string err = lua_tostring(L, -1); | ||
3944 | throw std::logic_error(_info.errorMessage("failed to load macro codes, at (macro in-place): "s + err, x)); | ||
3945 | } | ||
3946 | lua_pop(L, 1); // f | ||
3947 | pushYue("pcall"sv); // f pcall | ||
3948 | lua_insert(L, -2); // pcall f | ||
3949 | if (lua_pcall(L, 1, 2, 0) != 0) { // f(), success macroFunc | ||
3950 | std::string err = lua_tostring(L, -1); | ||
3951 | throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, x)); | ||
3952 | } // success res | ||
3953 | if (lua_toboolean(L, -2) == 0) { | ||
3954 | std::string err = lua_tostring(L, -1); | ||
3955 | throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, x)); | ||
3956 | } // true macroFunc | ||
3957 | lua_remove(L, -2); // macroFunc | ||
3958 | pushYue("pcall"sv); // macroFunc pcall | ||
3959 | lua_insert(L, -2); // pcall macroFunc | ||
3960 | bool success = lua_pcall(L, 1, 2, 0) == 0; | ||
3961 | if (!success) { // err | ||
3962 | std::string err = lua_tostring(L, -1); | ||
3963 | throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); | ||
3964 | } // success err | ||
3965 | if (lua_toboolean(L, -2) == 0) { | ||
3966 | std::string err = lua_tostring(L, -1); | ||
3967 | throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); | ||
3968 | } | ||
3969 | #endif // YUE_NO_MACRO | ||
3970 | } | ||
3971 | |||
3922 | #ifndef YUE_NO_MACRO | 3972 | #ifndef YUE_NO_MACRO |
3923 | std::string expandBuiltinMacro(const std::string& name, ast_node* x) { | 3973 | std::string expandBuiltinMacro(const std::string& name, ast_node* x) { |
3924 | if (name == "LINE"sv) { | 3974 | if (name == "LINE"sv) { |
@@ -3933,8 +3983,8 @@ private: | |||
3933 | std::tuple<std::string,std::string,str_list> expandMacroStr(ChainValue_t* chainValue) { | 3983 | std::tuple<std::string,std::string,str_list> expandMacroStr(ChainValue_t* chainValue) { |
3934 | const auto& chainList = chainValue->items.objects(); | 3984 | const auto& chainList = chainValue->items.objects(); |
3935 | auto x = ast_to<Callable_t>(chainList.front())->item.to<MacroName_t>(); | 3985 | auto x = ast_to<Callable_t>(chainList.front())->item.to<MacroName_t>(); |
3936 | auto macroName = x->name ? _parser.toString(x->name) : Empty; | 3986 | auto macroName = _parser.toString(x->name); |
3937 | if (!macroName.empty() && !_useModule) { | 3987 | if (!_useModule) { |
3938 | auto code = expandBuiltinMacro(macroName, x); | 3988 | auto code = expandBuiltinMacro(macroName, x); |
3939 | if (!code.empty()) return {Empty, code, {}}; | 3989 | if (!code.empty()) return {Empty, code, {}}; |
3940 | throw std::logic_error(_info.errorMessage("can not resolve macro"sv, x)); | 3990 | throw std::logic_error(_info.errorMessage("can not resolve macro"sv, x)); |
@@ -3942,57 +3992,6 @@ private: | |||
3942 | pushCurrentModule(); // cur | 3992 | pushCurrentModule(); // cur |
3943 | int top = lua_gettop(L) - 1; | 3993 | int top = lua_gettop(L) - 1; |
3944 | DEFER(lua_settop(L, top)); | 3994 | DEFER(lua_settop(L, top)); |
3945 | if (macroName.empty()) { | ||
3946 | lua_pop(L, 1); // empty | ||
3947 | const node_container* args = nullptr; | ||
3948 | auto item = *(++chainList.begin()); | ||
3949 | if (auto invoke = ast_cast<Invoke_t>(item)) { | ||
3950 | args = &invoke->args.objects(); | ||
3951 | } else { | ||
3952 | args = &ast_to<InvokeArgs_t>(item)->args.objects(); | ||
3953 | } | ||
3954 | if (args->size() != 1) { | ||
3955 | throw std::logic_error(_info.errorMessage("in-place macro must be followed by a compile time function"sv, x)); | ||
3956 | } | ||
3957 | auto fcodes = _parser.toString(args->back()); | ||
3958 | Utils::trim(fcodes); | ||
3959 | pushYue("loadstring"sv); // loadstring | ||
3960 | lua_pushlstring(L, fcodes.c_str(), fcodes.size()); // loadstring codes | ||
3961 | lua_pushliteral(L, "=(macro in-place)"); // loadstring codes chunk | ||
3962 | pushOptions(args->back()->m_begin.m_line - 1); // loadstring codes chunk options | ||
3963 | if (lua_pcall(L, 3, 2, 0) != 0) { // loadstring(codes,chunk,options), f err | ||
3964 | std::string err = lua_tostring(L, -1); | ||
3965 | throw std::logic_error(_info.errorMessage("failed to load macro codes\n"s + err, x)); | ||
3966 | } // f err | ||
3967 | if (lua_isnil(L, -2) != 0) { // f == nil, f err | ||
3968 | std::string err = lua_tostring(L, -1); | ||
3969 | throw std::logic_error(_info.errorMessage("failed to load macro codes, at (macro in-place): "s + err, x)); | ||
3970 | } | ||
3971 | lua_pop(L, 1); // f | ||
3972 | pushYue("pcall"sv); // f pcall | ||
3973 | lua_insert(L, -2); // pcall f | ||
3974 | if (lua_pcall(L, 1, 2, 0) != 0) { // f(), success macroFunc | ||
3975 | std::string err = lua_tostring(L, -1); | ||
3976 | throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, x)); | ||
3977 | } // success res | ||
3978 | if (lua_toboolean(L, -2) == 0) { | ||
3979 | std::string err = lua_tostring(L, -1); | ||
3980 | throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, x)); | ||
3981 | } // true macroFunc | ||
3982 | lua_remove(L, -2); // macroFunc | ||
3983 | pushYue("pcall"sv); // macroFunc pcall | ||
3984 | lua_insert(L, -2); // pcall macroFunc | ||
3985 | bool success = lua_pcall(L, 1, 2, 0) == 0; | ||
3986 | if (!success) { // err | ||
3987 | std::string err = lua_tostring(L, -1); | ||
3988 | throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); | ||
3989 | } // success err | ||
3990 | if (lua_toboolean(L, -2) == 0) { | ||
3991 | std::string err = lua_tostring(L, -1); | ||
3992 | throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); | ||
3993 | } | ||
3994 | return {Empty, Empty, {}}; | ||
3995 | } | ||
3996 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macroName | 3995 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macroName |
3997 | lua_rawget(L, -2); // cur[macroName], cur macroFunc | 3996 | lua_rawget(L, -2); // cur[macroName], cur macroFunc |
3998 | if (lua_isfunction(L, -1) == 0) { | 3997 | if (lua_isfunction(L, -1) == 0) { |
@@ -6097,38 +6096,49 @@ private: | |||
6097 | auto name = moduleNameFrom(import->literal); | 6096 | auto name = moduleNameFrom(import->literal); |
6098 | import->target.set(toAst<Variable_t>(name, x)); | 6097 | import->target.set(toAst<Variable_t>(name, x)); |
6099 | } | 6098 | } |
6100 | if (auto tabLit = import->target.as<ImportTabLit_t>()) { | 6099 | if (ast_is<import_all_macro_t, ImportTabLit_t>(import->target)) { |
6101 | auto newTab = x->new_ptr<ImportTabLit_t>(); | 6100 | bool importAllMacro = import->target.is<import_all_macro_t>(); |
6102 | #ifndef YUE_NO_MACRO | ||
6103 | bool importAllMacro = false; | ||
6104 | std::list<std::pair<std::string,std::string>> macroPairs; | 6101 | std::list<std::pair<std::string,std::string>> macroPairs; |
6105 | for (auto item : tabLit->items.objects()) { | 6102 | auto newTab = x->new_ptr<ImportTabLit_t>(); |
6106 | switch (item->getId()) { | 6103 | if (auto tabLit = import->target.as<ImportTabLit_t>()) { |
6107 | case id<MacroName_t>(): { | 6104 | for (auto item : tabLit->items.objects()) { |
6108 | auto macroName = static_cast<MacroName_t*>(item); | 6105 | switch (item->getId()) { |
6109 | auto name = _parser.toString(macroName->name); | 6106 | #ifdef YUE_NO_MACRO |
6110 | macroPairs.emplace_back(name, name); | 6107 | case id<MacroName_t>(): |
6111 | break; | 6108 | case id<macro_name_pair_t>(): |
6112 | } | 6109 | case id<import_all_macro_t>(): { |
6113 | case id<macro_name_pair_t>(): { | 6110 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, item)); |
6114 | auto pair = static_cast<macro_name_pair_t*>(item); | 6111 | break; |
6115 | macroPairs.emplace_back(_parser.toString(pair->key->name), _parser.toString(pair->value->name)); | 6112 | } |
6116 | break; | 6113 | #else // YUE_NO_MACRO |
6114 | case id<MacroName_t>(): { | ||
6115 | auto macroName = static_cast<MacroName_t*>(item); | ||
6116 | auto name = _parser.toString(macroName->name); | ||
6117 | macroPairs.emplace_back(name, name); | ||
6118 | break; | ||
6119 | } | ||
6120 | case id<macro_name_pair_t>(): { | ||
6121 | auto pair = static_cast<macro_name_pair_t*>(item); | ||
6122 | macroPairs.emplace_back(_parser.toString(pair->key->name), _parser.toString(pair->value->name)); | ||
6123 | break; | ||
6124 | } | ||
6125 | case id<import_all_macro_t>(): | ||
6126 | if (importAllMacro) throw std::logic_error(_info.errorMessage("import all macro symbol duplicated"sv, item)); | ||
6127 | importAllMacro = true; | ||
6128 | break; | ||
6129 | #endif // YUE_NO_MACRO | ||
6130 | case id<variable_pair_t>(): | ||
6131 | case id<normal_pair_t>(): | ||
6132 | case id<meta_variable_pair_t>(): | ||
6133 | case id<meta_normal_pair_t>(): | ||
6134 | case id<Exp_t>(): | ||
6135 | newTab->items.push_back(item); | ||
6136 | break; | ||
6137 | default: YUEE("AST node mismatch", item); break; | ||
6117 | } | 6138 | } |
6118 | case id<import_all_macro_t>(): | ||
6119 | if (importAllMacro) throw std::logic_error(_info.errorMessage("import all macro symbol duplicated"sv, item)); | ||
6120 | importAllMacro = true; | ||
6121 | break; | ||
6122 | case id<variable_pair_t>(): | ||
6123 | case id<normal_pair_t>(): | ||
6124 | case id<meta_variable_pair_t>(): | ||
6125 | case id<meta_normal_pair_t>(): | ||
6126 | case id<Exp_t>(): | ||
6127 | newTab->items.push_back(item); | ||
6128 | break; | ||
6129 | default: YUEE("AST node mismatch", item); break; | ||
6130 | } | 6139 | } |
6131 | } | 6140 | } |
6141 | #ifndef YUE_NO_MACRO | ||
6132 | if (importAllMacro || !macroPairs.empty()) { | 6142 | if (importAllMacro || !macroPairs.empty()) { |
6133 | auto moduleName = _parser.toString(import->literal); | 6143 | auto moduleName = _parser.toString(import->literal); |
6134 | Utils::replace(moduleName, "'"sv, ""sv); | 6144 | Utils::replace(moduleName, "'"sv, ""sv); |
@@ -6188,21 +6198,8 @@ private: | |||
6188 | } | 6198 | } |
6189 | } | 6199 | } |
6190 | #else // YUE_NO_MACRO | 6200 | #else // YUE_NO_MACRO |
6191 | for (auto item : tabLit->items.objects()) { | 6201 | if (importAllMacro) { |
6192 | switch (item->getId()) { | 6202 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, import->target)); |
6193 | case id<MacroName_t>(): | ||
6194 | case id<macro_name_pair_t>(): | ||
6195 | case id<import_all_macro_t>(): { | ||
6196 | throw std::logic_error(_info.errorMessage("macro feature not supported"sv, item)); | ||
6197 | break; | ||
6198 | } | ||
6199 | case id<variable_pair_t>(): | ||
6200 | case id<normal_pair_t>(): | ||
6201 | case id<Exp_t>(): | ||
6202 | newTab->items.push_back(item); | ||
6203 | break; | ||
6204 | default: YUEE("AST node mismatch", item); break; | ||
6205 | } | ||
6206 | } | 6203 | } |
6207 | #endif // YUE_NO_MACRO | 6204 | #endif // YUE_NO_MACRO |
6208 | if (newTab->items.empty()) { | 6205 | if (newTab->items.empty()) { |
@@ -6220,13 +6217,14 @@ private: | |||
6220 | auto chainValue = x->new_ptr<ChainValue_t>(); | 6217 | auto chainValue = x->new_ptr<ChainValue_t>(); |
6221 | chainValue->items.push_back(callable); | 6218 | chainValue->items.push_back(callable); |
6222 | value->item.set(chainValue); | 6219 | value->item.set(chainValue); |
6223 | } else { | 6220 | } else if (auto tabLit = ast_cast<ImportTabLit_t>(target)) { |
6224 | auto tabLit = ast_to<ImportTabLit_t>(target); | ||
6225 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | 6221 | auto simpleValue = x->new_ptr<SimpleValue_t>(); |
6226 | auto tableLit = x->new_ptr<TableLit_t>(); | 6222 | auto tableLit = x->new_ptr<TableLit_t>(); |
6227 | tableLit->values.dup(tabLit->items); | 6223 | tableLit->values.dup(tabLit->items); |
6228 | simpleValue->value.set(tableLit); | 6224 | simpleValue->value.set(tableLit); |
6229 | value->item.set(simpleValue); | 6225 | value->item.set(simpleValue); |
6226 | } else { | ||
6227 | return; | ||
6230 | } | 6228 | } |
6231 | auto exp = newExp(value, x); | 6229 | auto exp = newExp(value, x); |
6232 | auto assignList = x->new_ptr<ExpList_t>(); | 6230 | auto assignList = x->new_ptr<ExpList_t>(); |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 5628062..9257fab 100755 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
@@ -71,12 +71,12 @@ YueParser::YueParser() { | |||
71 | #define sym(str) (Space >> str) | 71 | #define sym(str) (Space >> str) |
72 | #define symx(str) expr(str) | 72 | #define symx(str) expr(str) |
73 | #define ensure(patt, finally) ((patt) >> (finally) | (finally) >> Cut) | 73 | #define ensure(patt, finally) ((patt) >> (finally) | (finally) >> Cut) |
74 | #define key(str) (Space >> str >> not_(AlphaNum)) | 74 | #define key(str) (str >> not_(AlphaNum)) |
75 | #define disable_do(patt) (DisableDo >> ((patt) >> EnableDo | EnableDo >> Cut)) | 75 | #define disable_do(patt) (DisableDo >> ((patt) >> EnableDo | EnableDo >> Cut)) |
76 | #define disable_chain(patt) (DisableChain >> ((patt) >> EnableChain | EnableChain >> Cut)) | 76 | #define disable_chain(patt) (DisableChain >> ((patt) >> EnableChain | EnableChain >> Cut)) |
77 | #define disable_do_chain(patt) (DisableDoChain >> ((patt) >> EnableDoChain | EnableDoChain >> Cut)) | 77 | #define disable_do_chain(patt) (DisableDoChain >> ((patt) >> EnableDoChain | EnableDoChain >> Cut)) |
78 | #define disable_arg_table_block(patt) (DisableArgTableBlock >> ((patt) >> EnableArgTableBlock | EnableArgTableBlock >> Cut)) | 78 | #define disable_arg_table_block(patt) (DisableArgTableBlock >> ((patt) >> EnableArgTableBlock | EnableArgTableBlock >> Cut)) |
79 | #define plain_body_with(str) (-key(str) >> InBlock | key(str) >> Statement) | 79 | #define plain_body_with(str) (-(Space >> key(str)) >> InBlock | Space >> key(str) >> Statement) |
80 | #define plain_body (InBlock | Statement) | 80 | #define plain_body (InBlock | Statement) |
81 | 81 | ||
82 | Variable = pl::user(Name, [](const item_t& item) { | 82 | Variable = pl::user(Name, [](const item_t& item) { |
@@ -182,12 +182,12 @@ YueParser::YueParser() { | |||
182 | Attrib = (expr("const") | expr("close")) >> not_(AlphaNum); | 182 | Attrib = (expr("const") | expr("close")) >> not_(AlphaNum); |
183 | Local = key("local") >> (Space >> local_flag | local_values); | 183 | Local = key("local") >> (Space >> local_flag | local_values); |
184 | 184 | ||
185 | LocalAttrib = Space >> Attrib >> NameList >> Assign; | 185 | LocalAttrib = Attrib >> NameList >> Assign; |
186 | 186 | ||
187 | colon_import_name = sym('\\') >> Space >> Variable; | 187 | colon_import_name = sym('\\') >> Space >> Variable; |
188 | ImportName = colon_import_name | Space >> Variable; | 188 | ImportName = colon_import_name | Space >> Variable; |
189 | ImportNameList = Seperator >> *SpaceBreak >> ImportName >> *((+SpaceBreak | sym(',') >> *SpaceBreak) >> ImportName); | 189 | ImportNameList = Seperator >> *SpaceBreak >> ImportName >> *((+SpaceBreak | sym(',') >> *SpaceBreak) >> ImportName); |
190 | ImportFrom = ImportNameList >> *SpaceBreak >> key("from") >> Exp; | 190 | ImportFrom = ImportNameList >> *SpaceBreak >> Space >> key("from") >> Exp; |
191 | 191 | ||
192 | import_literal_inner = (range('a', 'z') | range('A', 'Z') | set("_-")) >> *(AlphaNum | '-'); | 192 | import_literal_inner = (range('a', 'z') | range('A', 'Z') | set("_-")) >> *(AlphaNum | '-'); |
193 | import_literal_chain = Seperator >> import_literal_inner >> *(expr('.') >> import_literal_inner); | 193 | import_literal_chain = Seperator >> import_literal_inner >> *(expr('.') >> import_literal_inner); |
@@ -208,11 +208,11 @@ YueParser::YueParser() { | |||
208 | -import_tab_lines >> | 208 | -import_tab_lines >> |
209 | White >> sym('}') | KeyValue >> *(sym(',') >> KeyValue)); | 209 | White >> sym('}') | KeyValue >> *(sym(',') >> KeyValue)); |
210 | 210 | ||
211 | ImportAs = ImportLiteral >> -(key("as") >> (ImportTabLit | Space >> Variable)); | 211 | ImportAs = ImportLiteral >> -(Space >> key("as") >> Space >> (ImportTabLit | Variable | import_all_macro)); |
212 | 212 | ||
213 | Import = key("import") >> (ImportAs | ImportFrom); | 213 | Import = key("import") >> (ImportAs | ImportFrom); |
214 | 214 | ||
215 | Label = Space >> expr("::") >> LabelName >> expr("::"); | 215 | Label = expr("::") >> LabelName >> expr("::"); |
216 | 216 | ||
217 | Goto = key("goto") >> Space >> LabelName; | 217 | Goto = key("goto") >> Space >> LabelName; |
218 | 218 | ||
@@ -222,9 +222,9 @@ YueParser::YueParser() { | |||
222 | 222 | ||
223 | WithExp = ExpList >> -Assign; | 223 | WithExp = ExpList >> -Assign; |
224 | 224 | ||
225 | With = key("with") >> -existential_op >> disable_do_chain(WithExp) >> plain_body_with("do"); | 225 | With = Space >> key("with") >> -existential_op >> disable_do_chain(WithExp) >> plain_body_with("do"); |
226 | SwitchCase = key("when") >> disable_chain(ExpList) >> plain_body_with("then"); | 226 | SwitchCase = Space >> key("when") >> disable_chain(ExpList) >> plain_body_with("then"); |
227 | SwitchElse = key("else") >> plain_body; | 227 | SwitchElse = Space >> key("else") >> plain_body; |
228 | 228 | ||
229 | SwitchBlock = *EmptyLine >> | 229 | SwitchBlock = *EmptyLine >> |
230 | Advance >> Seperator >> | 230 | Advance >> Seperator >> |
@@ -233,18 +233,18 @@ YueParser::YueParser() { | |||
233 | -(+SpaceBreak >> SwitchElse) >> | 233 | -(+SpaceBreak >> SwitchElse) >> |
234 | PopIndent; | 234 | PopIndent; |
235 | 235 | ||
236 | Switch = key("switch") >> disable_do(Exp) >> -key("do") | 236 | Switch = Space >> key("switch") >> disable_do(Exp) >> -(Space >> key("do")) |
237 | >> -Space >> Break >> SwitchBlock; | 237 | >> -Space >> Break >> SwitchBlock; |
238 | 238 | ||
239 | IfCond = disable_chain(Exp >> -Assign); | 239 | IfCond = disable_chain(Exp >> -Assign); |
240 | IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> key("elseif") >> IfCond >> plain_body_with("then"); | 240 | IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("elseif") >> IfCond >> plain_body_with("then"); |
241 | IfElse = -(Break >> *EmptyLine >> CheckIndent) >> key("else") >> plain_body; | 241 | IfElse = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("else") >> plain_body; |
242 | IfType = (expr("if") | expr("unless")) >> not_(AlphaNum); | 242 | IfType = (expr("if") | expr("unless")) >> not_(AlphaNum); |
243 | If = Space >> IfType >> IfCond >> plain_body_with("then") >> *IfElseIf >> -IfElse; | 243 | If = Space >> IfType >> IfCond >> plain_body_with("then") >> *IfElseIf >> -IfElse; |
244 | 244 | ||
245 | WhileType = (expr("while") | expr("until")) >> not_(AlphaNum); | 245 | WhileType = (expr("while") | expr("until")) >> not_(AlphaNum); |
246 | While = Space >> WhileType >> disable_do_chain(Exp) >> plain_body_with("do"); | 246 | While = WhileType >> disable_do_chain(Exp) >> plain_body_with("do"); |
247 | Repeat = key("repeat") >> Body >> Break >> *EmptyLine >> CheckIndent >> key("until") >> Exp; | 247 | Repeat = key("repeat") >> Body >> Break >> *EmptyLine >> CheckIndent >> Space >> key("until") >> Exp; |
248 | 248 | ||
249 | for_step_value = sym(',') >> Exp; | 249 | for_step_value = sym(',') >> Exp; |
250 | for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; | 250 | for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; |
@@ -253,10 +253,10 @@ YueParser::YueParser() { | |||
253 | 253 | ||
254 | for_in = star_exp | ExpList; | 254 | for_in = star_exp | ExpList; |
255 | 255 | ||
256 | ForEach = key("for") >> AssignableNameList >> key("in") >> | 256 | ForEach = key("for") >> AssignableNameList >> Space >> key("in") >> |
257 | disable_do_chain(for_in) >> plain_body_with("do"); | 257 | disable_do_chain(for_in) >> plain_body_with("do"); |
258 | 258 | ||
259 | Do = pl::user(key("do"), [](const item_t& item) { | 259 | Do = pl::user(Space >> key("do"), [](const item_t& item) { |
260 | State* st = reinterpret_cast<State*>(item.user_data); | 260 | State* st = reinterpret_cast<State*>(item.user_data); |
261 | return st->doStack.empty() || st->doStack.top(); | 261 | return st->doStack.empty() || st->doStack.top(); |
262 | }) >> Body; | 262 | }) >> Body; |
@@ -299,15 +299,15 @@ YueParser::YueParser() { | |||
299 | return true; | 299 | return true; |
300 | }); | 300 | }); |
301 | 301 | ||
302 | Comprehension = sym('[') >> Exp >> CompInner >> sym(']'); | 302 | Comprehension = sym('[') >> Exp >> Space >> CompInner >> sym(']'); |
303 | comp_value = sym(',') >> Exp; | 303 | comp_value = sym(',') >> Exp; |
304 | TblComprehension = sym('{') >> Exp >> -comp_value >> CompInner >> sym('}'); | 304 | TblComprehension = sym('{') >> Exp >> -comp_value >> Space >> CompInner >> sym('}'); |
305 | 305 | ||
306 | CompInner = Seperator >> (CompForEach | CompFor) >> *CompClause; | 306 | CompInner = Seperator >> (CompForEach | CompFor) >> *CompClause; |
307 | star_exp = sym('*') >> Exp; | 307 | star_exp = sym('*') >> Exp; |
308 | CompForEach = key("for") >> AssignableNameList >> key("in") >> (star_exp | Exp); | 308 | CompForEach = key("for") >> AssignableNameList >> Space >> key("in") >> (star_exp | Exp); |
309 | CompFor = key("for") >> Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; | 309 | CompFor = key("for") >> Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; |
310 | CompClause = CompFor | CompForEach | key("when") >> Exp; | 310 | CompClause = Space >> (CompFor | CompForEach | key("when") >> Exp); |
311 | 311 | ||
312 | Assign = sym('=') >> Seperator >> (With | If | Switch | TableBlock | Exp >> *(Space >> set(",;") >> Exp)); | 312 | Assign = sym('=') >> Seperator >> (With | If | Switch | TableBlock | Exp >> *(Space >> set(",;") >> Exp)); |
313 | 313 | ||
@@ -491,10 +491,10 @@ YueParser::YueParser() { | |||
491 | ClassBlock = +SpaceBreak >> Advance >> Seperator >> ClassLine >> *(+SpaceBreak >> ClassLine) >> PopIndent; | 491 | ClassBlock = +SpaceBreak >> Advance >> Seperator >> ClassLine >> *(+SpaceBreak >> ClassLine) >> PopIndent; |
492 | 492 | ||
493 | ClassDecl = | 493 | ClassDecl = |
494 | key("class") >> not_(expr(':')) >> | 494 | Space >> key("class") >> not_(expr(':')) >> |
495 | -Assignable >> | 495 | -Assignable >> |
496 | -(key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> | 496 | -(Space >> key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> |
497 | -(key("using") >> PreventIndent >> ensure(ExpList, PopIndent)) >> | 497 | -(Space >> key("using") >> PreventIndent >> ensure(ExpList, PopIndent)) >> |
498 | -ClassBlock; | 498 | -ClassBlock; |
499 | 499 | ||
500 | global_values = NameList >> -(sym('=') >> (TableBlock | ExpListLow)); | 500 | global_values = NameList >> -(sym('=') >> (TableBlock | ExpListLow)); |
@@ -507,13 +507,13 @@ YueParser::YueParser() { | |||
507 | State* st = reinterpret_cast<State*>(item.user_data); | 507 | State* st = reinterpret_cast<State*>(item.user_data); |
508 | st->exportCount++; | 508 | st->exportCount++; |
509 | return true; | 509 | return true; |
510 | }) >> (pl::user(export_default >> Exp, [](const item_t& item) { | 510 | }) >> (pl::user(Space >> export_default >> Exp, [](const item_t& item) { |
511 | State* st = reinterpret_cast<State*>(item.user_data); | 511 | State* st = reinterpret_cast<State*>(item.user_data); |
512 | bool isValid = !st->exportDefault && st->exportCount == 1; | 512 | bool isValid = !st->exportDefault && st->exportCount == 1; |
513 | st->exportDefault = true; | 513 | st->exportDefault = true; |
514 | return isValid; | 514 | return isValid; |
515 | }) | 515 | }) |
516 | | (not_(export_default) >> pl::user(true_(), [](const item_t& item) { | 516 | | (not_(Space >> export_default) >> pl::user(true_(), [](const item_t& item) { |
517 | State* st = reinterpret_cast<State*>(item.user_data); | 517 | State* st = reinterpret_cast<State*>(item.user_data); |
518 | if (st->exportDefault && st->exportCount > 1) { | 518 | if (st->exportDefault && st->exportCount > 1) { |
519 | return false; | 519 | return false; |
@@ -521,7 +521,7 @@ YueParser::YueParser() { | |||
521 | return true; | 521 | return true; |
522 | } | 522 | } |
523 | }) >> ExpList >> -Assign) | 523 | }) >> ExpList >> -Assign) |
524 | | Macro) >> not_(Space >> statement_appendix); | 524 | | Space >> Macro) >> not_(Space >> statement_appendix); |
525 | 525 | ||
526 | variable_pair = sym(':') >> Variable >> not_('#'); | 526 | variable_pair = sym(':') >> Variable >> not_('#'); |
527 | 527 | ||
@@ -560,16 +560,17 @@ YueParser::YueParser() { | |||
560 | ) | 560 | ) |
561 | ); | 561 | ); |
562 | 562 | ||
563 | outer_var_shadow = key("using") >> (NameList | Space >> expr("nil")); | 563 | outer_var_shadow = Space >> key("using") >> (NameList | Space >> expr("nil")); |
564 | 564 | ||
565 | FnArgsDef = sym('(') >> White >> -FnArgDefList >> -outer_var_shadow >> White >> sym(')'); | 565 | FnArgsDef = sym('(') >> White >> -FnArgDefList >> -outer_var_shadow >> White >> sym(')'); |
566 | fn_arrow = expr("->") | expr("=>"); | 566 | fn_arrow = expr("->") | expr("=>"); |
567 | FunLit = -FnArgsDef >> Space >> fn_arrow >> -Body; | 567 | FunLit = -FnArgsDef >> Space >> fn_arrow >> -Body; |
568 | 568 | ||
569 | MacroName = expr('$') >> -Name; | 569 | MacroName = expr('$') >> Name; |
570 | macro_args_def = sym('(') >> White >> -FnArgDefList >> White >> sym(')'); | 570 | macro_args_def = sym('(') >> White >> -FnArgDefList >> White >> sym(')'); |
571 | MacroLit = -macro_args_def >> Space >> expr("->") >> Body; | 571 | MacroLit = -macro_args_def >> Space >> expr("->") >> Body; |
572 | Macro = key("macro") >> Space >> Name >> sym('=') >> MacroLit; | 572 | Macro = key("macro") >> Space >> Name >> sym('=') >> MacroLit; |
573 | MacroInPlace = expr('$') >> Space >> expr("->") >> Body; | ||
573 | 574 | ||
574 | NameList = Seperator >> Space >> Variable >> *(sym(',') >> Space >> Variable); | 575 | NameList = Seperator >> Space >> Variable >> *(sym(',') >> Space >> Variable); |
575 | NameOrDestructure = Space >> Variable | TableLit; | 576 | NameOrDestructure = Space >> Variable | TableLit; |
@@ -578,7 +579,7 @@ YueParser::YueParser() { | |||
578 | fn_arrow_back = expr('<') >> set("-="); | 579 | fn_arrow_back = expr('<') >> set("-="); |
579 | Backcall = -FnArgsDef >> Space >> fn_arrow_back >> Space >> ChainValue; | 580 | Backcall = -FnArgsDef >> Space >> fn_arrow_back >> Space >> ChainValue; |
580 | 581 | ||
581 | PipeBody = Seperator >> Space >> PipeOperator >> unary_exp >> *(+SpaceBreak >> CheckIndent >> Space >> PipeOperator >> unary_exp); | 582 | PipeBody = Seperator >> PipeOperator >> unary_exp >> *(+SpaceBreak >> CheckIndent >> Space >> PipeOperator >> unary_exp); |
582 | 583 | ||
583 | ExpList = Seperator >> Exp >> *(sym(',') >> Exp); | 584 | ExpList = Seperator >> Exp >> *(sym(',') >> Exp); |
584 | ExpListLow = Seperator >> Exp >> *(Space >> set(",;") >> Exp); | 585 | ExpListLow = Seperator >> Exp >> *(Space >> set(",;") >> Exp); |
@@ -606,24 +607,22 @@ YueParser::YueParser() { | |||
606 | 607 | ||
607 | const_value = (expr("nil") | expr("true") | expr("false")) >> not_(AlphaNum); | 608 | const_value = (expr("nil") | expr("true") | expr("false")) >> not_(AlphaNum); |
608 | 609 | ||
609 | SimpleValue = | 610 | SimpleValue = Space >> (const_value | |
610 | (Space >> const_value) | | ||
611 | If | Switch | With | ClassDecl | ForEach | For | While | Do | | 611 | If | Switch | With | ClassDecl | ForEach | For | While | Do | |
612 | (Space >> unary_value) | | 612 | unary_value | TblComprehension | TableLit | Comprehension | |
613 | TblComprehension | TableLit | Comprehension | FunLit | | 613 | FunLit | Num); |
614 | (Space >> Num); | ||
615 | 614 | ||
616 | ExpListAssign = ExpList >> -(Update | Assign); | 615 | ExpListAssign = ExpList >> -(Update | Assign); |
617 | 616 | ||
618 | if_line = key("if") >> Exp >> -Assign; | 617 | if_line = Space >> key("if") >> Exp >> -Assign; |
619 | unless_line = key("unless") >> Exp; | 618 | unless_line = Space >> key("unless") >> Exp; |
620 | 619 | ||
621 | statement_appendix = (if_line | unless_line | CompInner) >> Space; | 620 | statement_appendix = (if_line | unless_line | CompInner) >> Space; |
622 | statement_sep = and_(*SpaceBreak >> CheckIndent >> Space >> (set("($'\"") | expr("[[") | expr("[="))); | 621 | statement_sep = and_(*SpaceBreak >> CheckIndent >> Space >> (set("($'\"") | expr("[[") | expr("[="))); |
623 | Statement = ( | 622 | Statement = Space >> ( |
624 | Import | While | Repeat | For | ForEach | | 623 | Import | While | Repeat | For | ForEach | |
625 | Return | Local | Global | Export | Macro | | 624 | Return | Local | Global | Export | Macro | |
626 | Space >> BreakLoop | Label | Goto | LocalAttrib | | 625 | MacroInPlace | BreakLoop | Label | Goto | LocalAttrib | |
627 | Backcall | PipeBody | ExpListAssign | 626 | Backcall | PipeBody | ExpListAssign |
628 | ) >> Space >> | 627 | ) >> Space >> |
629 | -statement_appendix >> -statement_sep; | 628 | -statement_appendix >> -statement_sep; |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 22527d9..c752461 100755 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
@@ -303,6 +303,7 @@ private: | |||
303 | AST_RULE(MacroName) | 303 | AST_RULE(MacroName) |
304 | AST_RULE(MacroLit) | 304 | AST_RULE(MacroLit) |
305 | AST_RULE(Macro) | 305 | AST_RULE(Macro) |
306 | AST_RULE(MacroInPlace) | ||
306 | AST_RULE(NameOrDestructure) | 307 | AST_RULE(NameOrDestructure) |
307 | AST_RULE(AssignableNameList) | 308 | AST_RULE(AssignableNameList) |
308 | AST_RULE(InvokeArgs) | 309 | AST_RULE(InvokeArgs) |