aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2021-11-22 01:48:26 +0800
committerLi Jin <dragon-fly@qq.com>2021-11-22 01:48:26 +0800
commit125f709b065acb35bcd216001720c0bb4635dd25 (patch)
tree6059f57b12de2ba852197d3e2902b1741e47b42c
parent2ff18b4fb66d25d22e5a25fb386fe171853e0b06 (diff)
downloadyuescript-125f709b065acb35bcd216001720c0bb4635dd25.tar.gz
yuescript-125f709b065acb35bcd216001720c0bb4635dd25.tar.bz2
yuescript-125f709b065acb35bcd216001720c0bb4635dd25.zip
clean up.
-rwxr-xr-xsrc/yuescript/yue_ast.h14
-rwxr-xr-xsrc/yuescript/yue_compiler.cpp196
-rwxr-xr-xsrc/yuescript/yue_parser.cpp75
-rwxr-xr-xsrc/yuescript/yue_parser.h1
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
177AST_NODE(ImportAs) 177AST_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)
181AST_END(ImportAs) 181AST_END(ImportAs)
182 182
@@ -691,7 +691,7 @@ AST_NODE(FunLit)
691AST_END(FunLit) 691AST_END(FunLit)
692 692
693AST_NODE(MacroName) 693AST_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)
696AST_END(MacroName) 696AST_END(MacroName)
697 697
@@ -701,6 +701,11 @@ AST_NODE(MacroLit)
701 AST_MEMBER(MacroLit, &argsDef, &body) 701 AST_MEMBER(MacroLit, &argsDef, &body)
702AST_END(MacroLit) 702AST_END(MacroLit)
703 703
704AST_NODE(MacroInPlace)
705 ast_ptr<true, Body_t> body;
706 AST_MEMBER(MacroInPlace, &body)
707AST_END(MacroInPlace)
708
704AST_NODE(Macro) 709AST_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
776AST_NODE(Statement) 781AST_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
61typedef std::list<std::string> str_list; 61typedef std::list<std::string> str_list;
62 62
63const std::string_view version = "0.9.0"sv; 63const std::string_view version = "0.9.1"sv;
64const std::string_view extension = "yue"sv; 64const std::string_view extension = "yue"sv;
65 65
66class YueCompilerImpl { 66class 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)