From ca1ed557769352c0ac0ca7804dd25e18c1fdf2e1 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Fri, 1 Apr 2022 17:47:27 +0800 Subject: fix some ambiguous syntax caused by arg table block. --- spec/inputs/ambiguous.yue | 30 ++++++++++++++++++ spec/inputs/syntax.yue | 9 +++--- spec/outputs/ambiguous.lua | 69 ++++++++++++++++++++++++++++++++++++++++++ src/yuescript/yue_compiler.cpp | 14 +++++++-- src/yuescript/yue_parser.cpp | 40 ++++++++++++------------ src/yuescript/yue_parser.h | 8 ++--- 6 files changed, 140 insertions(+), 30 deletions(-) diff --git a/spec/inputs/ambiguous.yue b/spec/inputs/ambiguous.yue index 0e09979..3ae0bfc 100644 --- a/spec/inputs/ambiguous.yue +++ b/spec/inputs/ambiguous.yue @@ -28,4 +28,34 @@ do global * $v! +do + f + :v + + tb = while f + :v + + repeat + print v + until f + :v + + with f + :v = tb + .x = 1 + + x = if f + :v + + x = switch f + :v + when f + :v + + nums = for num = 1, len + :num + + objects = for item in *items + name: item + nil diff --git a/spec/inputs/syntax.yue b/spec/inputs/syntax.yue index e7f0a8d..84c6578 100644 --- a/spec/inputs/syntax.yue +++ b/spec/inputs/syntax.yue @@ -267,11 +267,12 @@ z = x and b z = x andb --- undelimited tables +while 10 > something( + something: "world" + ) + print "yeah" -while 10 > something - something: "world" - print "yeah" +-- undelimited tables x = okay: sure diff --git a/spec/outputs/ambiguous.lua b/spec/outputs/ambiguous.lua index 6039d73..f96cee5 100644 --- a/spec/outputs/ambiguous.lua +++ b/spec/outputs/ambiguous.lua @@ -27,4 +27,73 @@ end do print(123) end +do + f({ + v = v + }) + local tb + do + local _accum_0 = { } + local _len_0 = 1 + while f do + _accum_0[_len_0] = { + v = v + } + _len_0 = _len_0 + 1 + end + tb = _accum_0 + end + repeat + print(v) + until f({ + v = v + }) + do + local _with_0 = f + local v = tb.v + _with_0.x = 1 + end + local x + if f then + x = { + v = v + } + end + do + local _exp_0 = f({ + v = v + }) + if f == _exp_0 then + x = { + v = v + } + end + end + local nums + do + local _accum_0 = { } + local _len_0 = 1 + for num = 1, len do + _accum_0[_len_0] = { + num = num + } + _len_0 = _len_0 + 1 + end + nums = _accum_0 + end + local objects + do + local _accum_0 = { } + local _len_0 = 1 + local _list_0 = items + for _index_0 = 1, #_list_0 do + local item = _list_0[_index_0] + _accum_0[_len_0] = { + name = item + } + _len_0 = _len_0 + 1 + end + objects = _accum_0 + end +end return nil diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 4e01c24..26a8c5a 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -60,7 +60,7 @@ using namespace parserlib; typedef std::list str_list; -const std::string_view version = "0.10.7"sv; +const std::string_view version = "0.10.8"sv; const std::string_view extension = "yue"sv; class YueCompilerImpl { @@ -1876,8 +1876,16 @@ private: if (destructNode || (destructNode = value->item.as())) { if (*j != nullNode) { if (auto ssVal = simpleSingleValueFrom(*j)) { - if (ssVal->value.is()) { - throw std::logic_error(_info.errorMessage("can not destructure a const value"sv, ssVal->value)); + switch (ssVal->value->getId()) { + case id(): + throw std::logic_error(_info.errorMessage("can not destructure a const value"sv, ssVal->value)); + break; + case id(): + throw std::logic_error(_info.errorMessage("can not destructure a number"sv, ssVal->value)); + break; + case id(): + throw std::logic_error(_info.errorMessage("can not destructure a function"sv, ssVal->value)); + break; } } } else { diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 258997e..ab9b657 100755 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -75,7 +75,7 @@ YueParser::YueParser() { #define key(str) (str >> not_(AlphaNum)) #define disable_do(patt) (DisableDo >> ((patt) >> EnableDo | EnableDo >> Cut)) #define disable_chain(patt) (DisableChain >> ((patt) >> EnableChain | EnableChain >> Cut)) - #define disable_do_chain(patt) (DisableDoChain >> ((patt) >> EnableDoChain | EnableDoChain >> Cut)) + #define disable_do_chain_arg_table_block(patt) (DisableDoChainArgTableBlock >> ((patt) >> EnableDoChainArgTableBlock | EnableDoChainArgTableBlock >> Cut)) #define disable_arg_table_block(patt) (DisableArgTableBlock >> ((patt) >> EnableArgTableBlock | EnableArgTableBlock >> Cut)) #define plain_body_with(str) (-(Space >> key(str)) >> InBlock | Space >> key(str) >> Statement) #define plain_body (InBlock | Statement) @@ -223,8 +223,8 @@ YueParser::YueParser() { WithExp = ExpList >> -Assign; - With = Space >> key("with") >> -existential_op >> disable_do_chain(WithExp) >> plain_body_with("do"); - SwitchCase = Space >> key("when") >> disable_chain(ExpList) >> plain_body_with("then"); + With = Space >> key("with") >> -existential_op >> disable_do_chain_arg_table_block(WithExp) >> plain_body_with("do"); + SwitchCase = Space >> key("when") >> disable_chain(disable_arg_table_block(ExpList)) >> plain_body_with("then"); SwitchElse = Space >> key("else") >> plain_body; SwitchBlock = *EmptyLine >> @@ -238,54 +238,56 @@ YueParser::YueParser() { >> -Space >> Break >> SwitchBlock; assignment = ExpList >> Assign; - IfCond = disable_do_chain(disable_arg_table_block(assignment | Exp)); + IfCond = disable_do_chain_arg_table_block(assignment | Exp); IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("elseif") >> IfCond >> plain_body_with("then"); IfElse = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("else") >> plain_body; IfType = (expr("if") | expr("unless")) >> not_(AlphaNum); If = Space >> IfType >> IfCond >> plain_body_with("then") >> *IfElseIf >> -IfElse; WhileType = (expr("while") | expr("until")) >> not_(AlphaNum); - While = WhileType >> disable_do_chain(Exp) >> plain_body_with("do"); + While = WhileType >> disable_do_chain_arg_table_block(Exp) >> plain_body_with("do"); Repeat = key("repeat") >> Body >> Break >> *EmptyLine >> CheckIndent >> Space >> key("until") >> Exp; for_step_value = sym(',') >> Exp; for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; - For = key("for") >> disable_do_chain(for_args) >> plain_body_with("do"); + For = key("for") >> disable_do_chain_arg_table_block(for_args) >> plain_body_with("do"); for_in = star_exp | ExpList; ForEach = key("for") >> AssignableNameList >> Space >> key("in") >> - disable_do_chain(for_in) >> plain_body_with("do"); + disable_do_chain_arg_table_block(for_in) >> plain_body_with("do"); Do = pl::user(Space >> key("do"), [](const item_t& item) { State* st = reinterpret_cast(item.user_data); - return st->doStack.empty() || st->doStack.top(); + return st->noDoStack.empty() || !st->noDoStack.top(); }) >> Body; DisableDo = pl::user(true_(), [](const item_t& item) { State* st = reinterpret_cast(item.user_data); - st->doStack.push(false); + st->noDoStack.push(true); return true; }); EnableDo = pl::user(true_(), [](const item_t& item) { State* st = reinterpret_cast(item.user_data); - st->doStack.pop(); + st->noDoStack.pop(); return true; }); - DisableDoChain = pl::user(true_(), [](const item_t& item) { + DisableDoChainArgTableBlock = pl::user(true_(), [](const item_t& item) { State* st = reinterpret_cast(item.user_data); - st->doStack.push(false); - st->chainBlockStack.push(false); + st->noDoStack.push(true); + st->noChainBlockStack.push(true); + st->noTableBlockStack.push(true); return true; }); - EnableDoChain = pl::user(true_(), [](const item_t& item) { + EnableDoChainArgTableBlock = pl::user(true_(), [](const item_t& item) { State* st = reinterpret_cast(item.user_data); - st->doStack.pop(); - st->chainBlockStack.pop(); + st->noDoStack.pop(); + st->noChainBlockStack.pop(); + st->noTableBlockStack.pop(); return true; }); @@ -370,20 +372,20 @@ YueParser::YueParser() { DisableChain = pl::user(true_(), [](const item_t& item) { State* st = reinterpret_cast(item.user_data); - st->chainBlockStack.push(false); + st->noChainBlockStack.push(true); return true; }); EnableChain = pl::user(true_(), [](const item_t& item) { State* st = reinterpret_cast(item.user_data); - st->chainBlockStack.pop(); + st->noChainBlockStack.pop(); return true; }); chain_line = CheckIndent >> (chain_item | Space >> (chain_dot_chain | ColonChain)) >> -InvokeArgs; chain_block = pl::user(true_(), [](const item_t& item) { State* st = reinterpret_cast(item.user_data); - return st->chainBlockStack.empty() || st->chainBlockStack.top(); + 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; diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 51e6977..6be8451 100755 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h @@ -77,8 +77,8 @@ protected: std::string moduleName = "_module_0"; std::string buffer; std::stack indents; - std::stack doStack; - std::stack chainBlockStack; + std::stack noDoStack; + std::stack noChainBlockStack; std::stack noTableBlockStack; }; @@ -135,8 +135,8 @@ private: rule EnableDo; rule DisableChain; rule EnableChain; - rule DisableDoChain; - rule EnableDoChain; + rule DisableDoChainArgTableBlock; + rule EnableDoChainArgTableBlock; rule DisableArgTableBlock; rule EnableArgTableBlock; rule SwitchElse; -- cgit v1.2.3-55-g6feb