diff options
| author | Li Jin <dragon-fly@qq.com> | 2022-06-12 00:16:35 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2022-06-12 00:16:35 +0800 |
| commit | 1fa4049fc55986af8615ea836a60ac8cae255ad6 (patch) | |
| tree | ba2e35613b32ca3bd46f6d6ff932de2a457328ea | |
| parent | 4350d4b094c2c7202b7ad79d15187c1402bd13eb (diff) | |
| download | yuescript-1fa4049fc55986af8615ea836a60ac8cae255ad6.tar.gz yuescript-1fa4049fc55986af8615ea836a60ac8cae255ad6.tar.bz2 yuescript-1fa4049fc55986af8615ea836a60ac8cae255ad6.zip | |
fix issue #105.
Diffstat (limited to '')
| -rw-r--r-- | spec/inputs/with.yue | 14 | ||||
| -rw-r--r-- | spec/outputs/with.lua | 26 | ||||
| -rwxr-xr-x | src/yuescript/yue_ast.h | 9 | ||||
| -rwxr-xr-x | src/yuescript/yue_compiler.cpp | 31 | ||||
| -rwxr-xr-x | src/yuescript/yue_parser.cpp | 23 | ||||
| -rwxr-xr-x | src/yuescript/yue_parser.h | 3 |
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 | ||
| 125 | do | 125 | do |
| 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 | |||
| 139 | do | ||
| 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 | |||
| 165 | end | 165 | end |
| 166 | do | 166 | do |
| 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 | ||
| 191 | end | ||
| 192 | do | ||
| 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) |
| 198 | AST_END(Goto, "goto"sv) | 198 | AST_END(Goto, "goto"sv) |
| 199 | 199 | ||
| 200 | AST_NODE(ShortTabAppending) | ||
| 201 | ast_ptr<true, Assign_t> assign; | ||
| 202 | AST_MEMBER(ShortTabAppending, &assign) | ||
| 203 | AST_END(ShortTabAppending, "short_table_appending"sv) | ||
| 204 | |||
| 200 | class FnArgsDef_t; | 205 | class FnArgsDef_t; |
| 201 | 206 | ||
| 202 | AST_LEAF(fn_arrow_back) | 207 | AST_LEAF(fn_arrow_back) |
| @@ -804,8 +809,8 @@ AST_END(statement_sep, "statement_sep"sv) | |||
| 804 | AST_NODE(Statement) | 809 | AST_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 | ||
| 57 | typedef std::list<std::string> str_list; | 57 | typedef std::list<std::string> str_list; |
| 58 | 58 | ||
| 59 | const std::string_view version = "0.11.0"sv; | 59 | const std::string_view version = "0.11.1"sv; |
| 60 | const std::string_view extension = "yue"sv; | 60 | const std::string_view extension = "yue"sv; |
| 61 | 61 | ||
| 62 | class YueCompilerImpl { | 62 | class 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 | ||
| 7186 | const std::string YueCompilerImpl::Empty; | 7207 | const 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) |
