From 1fa4049fc55986af8615ea836a60ac8cae255ad6 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Sun, 12 Jun 2022 00:16:35 +0800 Subject: fix issue #105. --- src/yuescript/yue_ast.h | 9 +++++++-- src/yuescript/yue_compiler.cpp | 31 ++++++++++++++++++++++++++----- src/yuescript/yue_parser.cpp | 23 ++++++++++++----------- src/yuescript/yue_parser.h | 3 ++- 4 files changed, 47 insertions(+), 19 deletions(-) (limited to 'src') 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) AST_MEMBER(Goto, &label) AST_END(Goto, "goto"sv) +AST_NODE(ShortTabAppending) + ast_ptr assign; + AST_MEMBER(ShortTabAppending, &assign) +AST_END(ShortTabAppending, "short_table_appending"sv) + class FnArgsDef_t; AST_LEAF(fn_arrow_back) @@ -804,8 +809,8 @@ AST_END(statement_sep, "statement_sep"sv) AST_NODE(Statement) ast_sel content; + BreakLoop_t, Label_t, Goto_t, ShortTabAppending_t, + Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t> content; ast_ptr appendix; ast_ptr needSep; 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; typedef std::list str_list; -const std::string_view version = "0.11.0"sv; +const std::string_view version = "0.11.1"sv; const std::string_view extension = "yue"sv; class YueCompilerImpl { @@ -806,8 +806,10 @@ private: case id(): return true; } - } else if (firstItem->getId() == id()) { - return true; + } else switch (firstItem->getId()) { + case id(): + case id(): + return true; } } else { if (std::find_if(chainItems.begin(), chainItems.end(), [](ast_node* node) { @@ -1055,6 +1057,7 @@ private: case id(): transformBreakLoop(static_cast(content), out); break; case id(): transformLabel(static_cast(content), out); break; case id(): transformGoto(static_cast(content), out); break; + case id(): transformShortTabAppending(static_cast(content), out); break; case id(): transformLocalAttrib(static_cast(content), out); break; case id(): throw std::logic_error(_info.errorMessage("pipe chain must be following a value"sv, x)); break; case id(): { @@ -1278,6 +1281,13 @@ private: temp.push_back(clearBuf()); } else if (ast_is(chainValue->items.back())) { chainValue->items.pop_back(); + if (chainValue->items.empty()) { + if (_withVars.empty()) { + throw std::logic_error(_info.errorMessage("short table appending must be called within a with block"sv, x)); + } else { + chainValue->items.push_back(toAst(_withVars.top(), chainValue)); + } + } auto varName = singleVariableFrom(chainValue); bool isScoped = false; if (varName.empty() || !isLocal(varName)) { @@ -3797,6 +3807,7 @@ private: switch (chainList.front()->getId()) { case id(): case id(): + case id(): if (_withVars.empty()) { throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, chainList.front())); } else { @@ -3943,8 +3954,9 @@ private: switch (x->getId()) { case id(): case id(): + case id(): if (_withVars.empty()) { - throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x)); + throw std::logic_error(_info.errorMessage("short dot/colon and indexing syntax must be called within a with block"sv, x)); } else { temp.push_back(_withVars.top()); } @@ -4440,7 +4452,7 @@ private: void transformChainValue(ChainValue_t* chainValue, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr, bool allowBlockMacroReturn = false) { if (isMacroChain(chainValue)) { #ifndef YUE_NO_MACRO - ast_ptr node; + ast_ptr node; std::unique_ptr codes; std::string luaCodes; str_list localVars; @@ -7181,6 +7193,15 @@ private: void transformGoto(Goto_t* gotoNode, str_list& out) { out.push_back(indent() + "goto "s + _parser.toString(gotoNode->label) + nll(gotoNode)); } + + void transformShortTabAppending(ShortTabAppending_t* tab, str_list& out) { + if (_withVars.empty()) { + throw std::logic_error(_info.errorMessage("short table appending syntax must be called within a with block"sv, tab)); + } + auto assignment = toAst(_withVars.top() + "[]=nil"s, tab); + assignment->action.set(tab->assign); + transformAssignment(assignment, out); + } }; 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() { Goto = key("goto") >> Space >> LabelName; + ShortTabAppending = expr("[]") >> Assign; + BreakLoop = (expr("break") | expr("continue")) >> not_(AlphaNum); Return = key("return") >> -(TableBlock | ExpListLow); @@ -335,7 +337,7 @@ YueParser::YueParser() { Update = Space >> update_op >> expr("=") >> Exp; - Assignable = AssignableChain | Space >> Variable | Space >> SelfName; + Assignable = Space >> (AssignableChain | Variable | SelfName); unary_value = unary_operator >> *(Space >> unary_operator) >> Value; @@ -382,16 +384,16 @@ YueParser::YueParser() { return true; }); - chain_line = CheckIndent >> (chain_item | Space >> (chain_dot_chain | ColonChain)) >> -InvokeArgs; + chain_line = CheckIndent >> Space >> (chain_dot_chain | ColonChain) >> -InvokeArgs; chain_block = pl::user(true_(), [](const item_t& item) { State* st = reinterpret_cast(item.user_data); return st->noChainBlockStack.empty() || !st->noChainBlockStack.top(); }) >> +SpaceBreak >> Advance >> ensure( chain_line >> *(+SpaceBreak >> chain_line), PopIndent); - ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -(InvokeArgs | chain_block) >> -table_appending_op; + ChainValue = Space >> Seperator >> (Chain | Callable) >> -existential_op >> -(InvokeArgs | chain_block) >> -table_appending_op; simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue); - Value = SimpleValue | simple_table | ChainValue | String; + Value = SimpleValue | simple_table | ChainValue | Space >> String; single_string_inner = expr("\\'") | "\\\\" | not_(expr('\'')) >> Any; SingleString = symx('\'') >> *single_string_inner >> symx('\''); @@ -400,7 +402,7 @@ YueParser::YueParser() { double_string_inner = +(not_(interp) >> double_string_plain); double_string_content = double_string_inner | interp; DoubleString = symx('"') >> Seperator >> *double_string_content >> symx('"'); - String = Space >> (DoubleString | SingleString | LuaString); + String = DoubleString | SingleString | LuaString; lua_string_open = '[' >> *expr('=') >> '['; lua_string_close = ']' >> *expr('=') >> ']'; @@ -423,7 +425,7 @@ YueParser::YueParser() { LuaString = LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose; Parens = symx('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); - Callable = Space >> (Variable | SelfName | MacroName | VarArg | Parens); + Callable = Variable | SelfName | MacroName | VarArg | Parens; FnArgsExpList = Exp >> *((Break | sym(',')) >> White >> Exp); FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')')) | @@ -435,11 +437,10 @@ YueParser::YueParser() { existential_op = expr('?') >> not_(expr('?')); table_appending_op = expr("[]"); chain_call = (Callable | String) >> -existential_op >> ChainItems; - chain_item = and_(set(".\\")) >> ChainItems; + chain_index_chain = Index >> -existential_op >> -ChainItems; chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems; - Chain = chain_call | chain_item | - Space >> (chain_dot_chain | ColonChain); + Chain = chain_call | chain_dot_chain | ColonChain | chain_index_chain; AssignableChain = Seperator >> Chain; @@ -631,8 +632,8 @@ YueParser::YueParser() { Statement = Space >> ( Import | While | Repeat | For | ForEach | Return | Local | Global | Export | Macro | - MacroInPlace | BreakLoop | Label | Goto | LocalAttrib | - Backcall | PipeBody | ExpListAssign + MacroInPlace | BreakLoop | Label | Goto | ShortTabAppending | + LocalAttrib | Backcall | PipeBody | ExpListAssign ) >> Space >> -statement_appendix >> -statement_sep; 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: rule FnArgs; rule macro_args_def; rule chain_call; - rule chain_item; + rule chain_index_chain; rule ChainItems; rule chain_dot_chain; rule ColonChain; @@ -220,6 +220,7 @@ private: AST_RULE(Import) AST_RULE(Label) AST_RULE(Goto) + AST_RULE(ShortTabAppending) AST_RULE(fn_arrow_back) AST_RULE(Backcall) AST_RULE(PipeBody) -- cgit v1.2.3-55-g6feb