aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2022-06-12 00:16:35 +0800
committerLi Jin <dragon-fly@qq.com>2022-06-12 00:16:35 +0800
commit1fa4049fc55986af8615ea836a60ac8cae255ad6 (patch)
treeba2e35613b32ca3bd46f6d6ff932de2a457328ea
parent4350d4b094c2c7202b7ad79d15187c1402bd13eb (diff)
downloadyuescript-1fa4049fc55986af8615ea836a60ac8cae255ad6.tar.gz
yuescript-1fa4049fc55986af8615ea836a60ac8cae255ad6.tar.bz2
yuescript-1fa4049fc55986af8615ea836a60ac8cae255ad6.zip
fix issue #105.
-rw-r--r--spec/inputs/with.yue14
-rw-r--r--spec/outputs/with.lua26
-rwxr-xr-xsrc/yuescript/yue_ast.h9
-rwxr-xr-xsrc/yuescript/yue_compiler.cpp31
-rwxr-xr-xsrc/yuescript/yue_parser.cpp23
-rwxr-xr-xsrc/yuescript/yue_parser.h3
6 files changed, 87 insertions, 19 deletions
diff --git a/spec/inputs/with.yue b/spec/inputs/with.yue
index fe140ac..6f3e3ba 100644
--- a/spec/inputs/with.yue
+++ b/spec/inputs/with.yue
@@ -123,6 +123,20 @@ do
123 y = .end.of.function 123 y = .end.of.function
124 124
125do 125do
126 with tb
127 [1] = [2]?\func!
128 ["%a-b-c%"] = 123
129 [ [[x y z]]] = [var]
130 print [ [3]]
131 with [4]
132 [1] = 1
133 [] = "abc"
134 [] =
135 type: "hello"
136 * name: "xyz"
137 value: 998
138
139do
126 global mask 140 global mask
127 with? mask = SolidRect width: w, height: h, color: 0x66000000 141 with? mask = SolidRect width: w, height: h, color: 0x66000000
128 .touchEnabled = true 142 .touchEnabled = true
diff --git a/spec/outputs/with.lua b/spec/outputs/with.lua
index f172b01..9dcaca3 100644
--- a/spec/outputs/with.lua
+++ b/spec/outputs/with.lua
@@ -165,6 +165,32 @@ do
165end 165end
166do 166do
167 do 167 do
168 local _with_0 = tb
169 do
170 local _obj_0 = _with_0[2]
171 if _obj_0 ~= nil then
172 _with_0[1] = _obj_0:func()
173 end
174 end
175 _with_0["%a-b-c%"] = 123
176 _with_0[ [[x y z]]] = _with_0[var]
177 print(_with_0[_with_0[3]])
178 do
179 local _with_1 = _with_0[4]
180 _with_1[1] = 1
181 end
182 _with_0[#_with_0 + 1] = "abc"
183 _with_0[#_with_0 + 1] = {
184 type = "hello",
185 {
186 name = "xyz",
187 value = 998
188 }
189 }
190 end
191end
192do
193 do
168 local _with_0 = SolidRect({ 194 local _with_0 = SolidRect({
169 width = w, 195 width = w,
170 height = h, 196 height = h,
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index 38e97ad..571c18e 100755
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -197,6 +197,11 @@ AST_NODE(Goto)
197 AST_MEMBER(Goto, &label) 197 AST_MEMBER(Goto, &label)
198AST_END(Goto, "goto"sv) 198AST_END(Goto, "goto"sv)
199 199
200AST_NODE(ShortTabAppending)
201 ast_ptr<true, Assign_t> assign;
202 AST_MEMBER(ShortTabAppending, &assign)
203AST_END(ShortTabAppending, "short_table_appending"sv)
204
200class FnArgsDef_t; 205class FnArgsDef_t;
201 206
202AST_LEAF(fn_arrow_back) 207AST_LEAF(fn_arrow_back)
@@ -804,8 +809,8 @@ AST_END(statement_sep, "statement_sep"sv)
804AST_NODE(Statement) 809AST_NODE(Statement)
805 ast_sel<true, Import_t, While_t, Repeat_t, For_t, ForEach_t, 810 ast_sel<true, Import_t, While_t, Repeat_t, For_t, ForEach_t,
806 Return_t, Local_t, Global_t, Export_t, Macro_t, MacroInPlace_t, 811 Return_t, Local_t, Global_t, Export_t, Macro_t, MacroInPlace_t,
807 BreakLoop_t, Label_t, Goto_t, Backcall_t, LocalAttrib_t, 812 BreakLoop_t, Label_t, Goto_t, ShortTabAppending_t,
808 PipeBody_t, ExpListAssign_t> content; 813 Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t> content;
809 ast_ptr<false, statement_appendix_t> appendix; 814 ast_ptr<false, statement_appendix_t> appendix;
810 ast_ptr<false, statement_sep_t> needSep; 815 ast_ptr<false, statement_sep_t> needSep;
811 AST_MEMBER(Statement, &content, &appendix, &needSep) 816 AST_MEMBER(Statement, &content, &appendix, &needSep)
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index d270455..8535b43 100755
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -56,7 +56,7 @@ using namespace parserlib;
56 56
57typedef std::list<std::string> str_list; 57typedef std::list<std::string> str_list;
58 58
59const std::string_view version = "0.11.0"sv; 59const std::string_view version = "0.11.1"sv;
60const std::string_view extension = "yue"sv; 60const std::string_view extension = "yue"sv;
61 61
62class YueCompilerImpl { 62class YueCompilerImpl {
@@ -806,8 +806,10 @@ private:
806 case id<SelfName_t>(): 806 case id<SelfName_t>():
807 return true; 807 return true;
808 } 808 }
809 } else if (firstItem->getId() == id<DotChainItem_t>()) { 809 } else switch (firstItem->getId()) {
810 return true; 810 case id<DotChainItem_t>():
811 case id<Exp_t>():
812 return true;
811 } 813 }
812 } else { 814 } else {
813 if (std::find_if(chainItems.begin(), chainItems.end(), [](ast_node* node) { 815 if (std::find_if(chainItems.begin(), chainItems.end(), [](ast_node* node) {
@@ -1055,6 +1057,7 @@ private:
1055 case id<BreakLoop_t>(): transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; 1057 case id<BreakLoop_t>(): transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break;
1056 case id<Label_t>(): transformLabel(static_cast<Label_t*>(content), out); break; 1058 case id<Label_t>(): transformLabel(static_cast<Label_t*>(content), out); break;
1057 case id<Goto_t>(): transformGoto(static_cast<Goto_t*>(content), out); break; 1059 case id<Goto_t>(): transformGoto(static_cast<Goto_t*>(content), out); break;
1060 case id<ShortTabAppending_t>(): transformShortTabAppending(static_cast<ShortTabAppending_t*>(content), out); break;
1058 case id<LocalAttrib_t>(): transformLocalAttrib(static_cast<LocalAttrib_t*>(content), out); break; 1061 case id<LocalAttrib_t>(): transformLocalAttrib(static_cast<LocalAttrib_t*>(content), out); break;
1059 case id<PipeBody_t>(): throw std::logic_error(_info.errorMessage("pipe chain must be following a value"sv, x)); break; 1062 case id<PipeBody_t>(): throw std::logic_error(_info.errorMessage("pipe chain must be following a value"sv, x)); break;
1060 case id<ExpListAssign_t>(): { 1063 case id<ExpListAssign_t>(): {
@@ -1278,6 +1281,13 @@ private:
1278 temp.push_back(clearBuf()); 1281 temp.push_back(clearBuf());
1279 } else if (ast_is<table_appending_op_t>(chainValue->items.back())) { 1282 } else if (ast_is<table_appending_op_t>(chainValue->items.back())) {
1280 chainValue->items.pop_back(); 1283 chainValue->items.pop_back();
1284 if (chainValue->items.empty()) {
1285 if (_withVars.empty()) {
1286 throw std::logic_error(_info.errorMessage("short table appending must be called within a with block"sv, x));
1287 } else {
1288 chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), chainValue));
1289 }
1290 }
1281 auto varName = singleVariableFrom(chainValue); 1291 auto varName = singleVariableFrom(chainValue);
1282 bool isScoped = false; 1292 bool isScoped = false;
1283 if (varName.empty() || !isLocal(varName)) { 1293 if (varName.empty() || !isLocal(varName)) {
@@ -3797,6 +3807,7 @@ private:
3797 switch (chainList.front()->getId()) { 3807 switch (chainList.front()->getId()) {
3798 case id<DotChainItem_t>(): 3808 case id<DotChainItem_t>():
3799 case id<ColonChainItem_t>(): 3809 case id<ColonChainItem_t>():
3810 case id<Exp_t>():
3800 if (_withVars.empty()) { 3811 if (_withVars.empty()) {
3801 throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, chainList.front())); 3812 throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, chainList.front()));
3802 } else { 3813 } else {
@@ -3943,8 +3954,9 @@ private:
3943 switch (x->getId()) { 3954 switch (x->getId()) {
3944 case id<DotChainItem_t>(): 3955 case id<DotChainItem_t>():
3945 case id<ColonChainItem_t>(): 3956 case id<ColonChainItem_t>():
3957 case id<Exp_t>():
3946 if (_withVars.empty()) { 3958 if (_withVars.empty()) {
3947 throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x)); 3959 throw std::logic_error(_info.errorMessage("short dot/colon and indexing syntax must be called within a with block"sv, x));
3948 } else { 3960 } else {
3949 temp.push_back(_withVars.top()); 3961 temp.push_back(_withVars.top());
3950 } 3962 }
@@ -4440,7 +4452,7 @@ private:
4440 void transformChainValue(ChainValue_t* chainValue, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr, bool allowBlockMacroReturn = false) { 4452 void transformChainValue(ChainValue_t* chainValue, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr, bool allowBlockMacroReturn = false) {
4441 if (isMacroChain(chainValue)) { 4453 if (isMacroChain(chainValue)) {
4442#ifndef YUE_NO_MACRO 4454#ifndef YUE_NO_MACRO
4443 ast_ptr<false,ast_node> node; 4455 ast_ptr<false, ast_node> node;
4444 std::unique_ptr<input> codes; 4456 std::unique_ptr<input> codes;
4445 std::string luaCodes; 4457 std::string luaCodes;
4446 str_list localVars; 4458 str_list localVars;
@@ -7181,6 +7193,15 @@ private:
7181 void transformGoto(Goto_t* gotoNode, str_list& out) { 7193 void transformGoto(Goto_t* gotoNode, str_list& out) {
7182 out.push_back(indent() + "goto "s + _parser.toString(gotoNode->label) + nll(gotoNode)); 7194 out.push_back(indent() + "goto "s + _parser.toString(gotoNode->label) + nll(gotoNode));
7183 } 7195 }
7196
7197 void transformShortTabAppending(ShortTabAppending_t* tab, str_list& out) {
7198 if (_withVars.empty()) {
7199 throw std::logic_error(_info.errorMessage("short table appending syntax must be called within a with block"sv, tab));
7200 }
7201 auto assignment = toAst<ExpListAssign_t>(_withVars.top() + "[]=nil"s, tab);
7202 assignment->action.set(tab->assign);
7203 transformAssignment(assignment, out);
7204 }
7184}; 7205};
7185 7206
7186const std::string YueCompilerImpl::Empty; 7207const std::string YueCompilerImpl::Empty;
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index 54dd174..5c42963 100755
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -216,6 +216,8 @@ YueParser::YueParser() {
216 216
217 Goto = key("goto") >> Space >> LabelName; 217 Goto = key("goto") >> Space >> LabelName;
218 218
219 ShortTabAppending = expr("[]") >> Assign;
220
219 BreakLoop = (expr("break") | expr("continue")) >> not_(AlphaNum); 221 BreakLoop = (expr("break") | expr("continue")) >> not_(AlphaNum);
220 222
221 Return = key("return") >> -(TableBlock | ExpListLow); 223 Return = key("return") >> -(TableBlock | ExpListLow);
@@ -335,7 +337,7 @@ YueParser::YueParser() {
335 337
336 Update = Space >> update_op >> expr("=") >> Exp; 338 Update = Space >> update_op >> expr("=") >> Exp;
337 339
338 Assignable = AssignableChain | Space >> Variable | Space >> SelfName; 340 Assignable = Space >> (AssignableChain | Variable | SelfName);
339 341
340 unary_value = unary_operator >> *(Space >> unary_operator) >> Value; 342 unary_value = unary_operator >> *(Space >> unary_operator) >> Value;
341 343
@@ -382,16 +384,16 @@ YueParser::YueParser() {
382 return true; 384 return true;
383 }); 385 });
384 386
385 chain_line = CheckIndent >> (chain_item | Space >> (chain_dot_chain | ColonChain)) >> -InvokeArgs; 387 chain_line = CheckIndent >> Space >> (chain_dot_chain | ColonChain) >> -InvokeArgs;
386 chain_block = pl::user(true_(), [](const item_t& item) { 388 chain_block = pl::user(true_(), [](const item_t& item) {
387 State* st = reinterpret_cast<State*>(item.user_data); 389 State* st = reinterpret_cast<State*>(item.user_data);
388 return st->noChainBlockStack.empty() || !st->noChainBlockStack.top(); 390 return st->noChainBlockStack.empty() || !st->noChainBlockStack.top();
389 }) >> +SpaceBreak >> Advance >> ensure( 391 }) >> +SpaceBreak >> Advance >> ensure(
390 chain_line >> *(+SpaceBreak >> chain_line), PopIndent); 392 chain_line >> *(+SpaceBreak >> chain_line), PopIndent);
391 ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -(InvokeArgs | chain_block) >> -table_appending_op; 393 ChainValue = Space >> Seperator >> (Chain | Callable) >> -existential_op >> -(InvokeArgs | chain_block) >> -table_appending_op;
392 394
393 simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue); 395 simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue);
394 Value = SimpleValue | simple_table | ChainValue | String; 396 Value = SimpleValue | simple_table | ChainValue | Space >> String;
395 397
396 single_string_inner = expr("\\'") | "\\\\" | not_(expr('\'')) >> Any; 398 single_string_inner = expr("\\'") | "\\\\" | not_(expr('\'')) >> Any;
397 SingleString = symx('\'') >> *single_string_inner >> symx('\''); 399 SingleString = symx('\'') >> *single_string_inner >> symx('\'');
@@ -400,7 +402,7 @@ YueParser::YueParser() {
400 double_string_inner = +(not_(interp) >> double_string_plain); 402 double_string_inner = +(not_(interp) >> double_string_plain);
401 double_string_content = double_string_inner | interp; 403 double_string_content = double_string_inner | interp;
402 DoubleString = symx('"') >> Seperator >> *double_string_content >> symx('"'); 404 DoubleString = symx('"') >> Seperator >> *double_string_content >> symx('"');
403 String = Space >> (DoubleString | SingleString | LuaString); 405 String = DoubleString | SingleString | LuaString;
404 406
405 lua_string_open = '[' >> *expr('=') >> '['; 407 lua_string_open = '[' >> *expr('=') >> '[';
406 lua_string_close = ']' >> *expr('=') >> ']'; 408 lua_string_close = ']' >> *expr('=') >> ']';
@@ -423,7 +425,7 @@ YueParser::YueParser() {
423 LuaString = LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose; 425 LuaString = LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose;
424 426
425 Parens = symx('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); 427 Parens = symx('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')');
426 Callable = Space >> (Variable | SelfName | MacroName | VarArg | Parens); 428 Callable = Variable | SelfName | MacroName | VarArg | Parens;
427 FnArgsExpList = Exp >> *((Break | sym(',')) >> White >> Exp); 429 FnArgsExpList = Exp >> *((Break | sym(',')) >> White >> Exp);
428 430
429 FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')')) | 431 FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')')) |
@@ -435,11 +437,10 @@ YueParser::YueParser() {
435 existential_op = expr('?') >> not_(expr('?')); 437 existential_op = expr('?') >> not_(expr('?'));
436 table_appending_op = expr("[]"); 438 table_appending_op = expr("[]");
437 chain_call = (Callable | String) >> -existential_op >> ChainItems; 439 chain_call = (Callable | String) >> -existential_op >> ChainItems;
438 chain_item = and_(set(".\\")) >> ChainItems; 440 chain_index_chain = Index >> -existential_op >> -ChainItems;
439 chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems; 441 chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems;
440 442
441 Chain = chain_call | chain_item | 443 Chain = chain_call | chain_dot_chain | ColonChain | chain_index_chain;
442 Space >> (chain_dot_chain | ColonChain);
443 444
444 AssignableChain = Seperator >> Chain; 445 AssignableChain = Seperator >> Chain;
445 446
@@ -631,8 +632,8 @@ YueParser::YueParser() {
631 Statement = Space >> ( 632 Statement = Space >> (
632 Import | While | Repeat | For | ForEach | 633 Import | While | Repeat | For | ForEach |
633 Return | Local | Global | Export | Macro | 634 Return | Local | Global | Export | Macro |
634 MacroInPlace | BreakLoop | Label | Goto | LocalAttrib | 635 MacroInPlace | BreakLoop | Label | Goto | ShortTabAppending |
635 Backcall | PipeBody | ExpListAssign 636 LocalAttrib | Backcall | PipeBody | ExpListAssign
636 ) >> Space >> 637 ) >> Space >>
637 -statement_appendix >> -statement_sep; 638 -statement_appendix >> -statement_sep;
638 639
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h
index 159bbca..1532adf 100755
--- a/src/yuescript/yue_parser.h
+++ b/src/yuescript/yue_parser.h
@@ -158,7 +158,7 @@ private:
158 rule FnArgs; 158 rule FnArgs;
159 rule macro_args_def; 159 rule macro_args_def;
160 rule chain_call; 160 rule chain_call;
161 rule chain_item; 161 rule chain_index_chain;
162 rule ChainItems; 162 rule ChainItems;
163 rule chain_dot_chain; 163 rule chain_dot_chain;
164 rule ColonChain; 164 rule ColonChain;
@@ -220,6 +220,7 @@ private:
220 AST_RULE(Import) 220 AST_RULE(Import)
221 AST_RULE(Label) 221 AST_RULE(Label)
222 AST_RULE(Goto) 222 AST_RULE(Goto)
223 AST_RULE(ShortTabAppending)
223 AST_RULE(fn_arrow_back) 224 AST_RULE(fn_arrow_back)
224 AST_RULE(Backcall) 225 AST_RULE(Backcall)
225 AST_RULE(PipeBody) 226 AST_RULE(PipeBody)