diff options
| author | Li Jin <dragon-fly@qq.com> | 2022-04-01 17:47:27 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2022-04-01 17:47:27 +0800 |
| commit | ca1ed557769352c0ac0ca7804dd25e18c1fdf2e1 (patch) | |
| tree | bf86d3990b90054f8d82aaf87cb9efae444a08ce | |
| parent | 7be6c300256bfe411942a7ccc66f6bc3afa7390d (diff) | |
| download | yuescript-ca1ed557769352c0ac0ca7804dd25e18c1fdf2e1.tar.gz yuescript-ca1ed557769352c0ac0ca7804dd25e18c1fdf2e1.tar.bz2 yuescript-ca1ed557769352c0ac0ca7804dd25e18c1fdf2e1.zip | |
fix some ambiguous syntax caused by arg table block.
| -rw-r--r-- | spec/inputs/ambiguous.yue | 30 | ||||
| -rw-r--r-- | spec/inputs/syntax.yue | 9 | ||||
| -rw-r--r-- | spec/outputs/ambiguous.lua | 69 | ||||
| -rwxr-xr-x | src/yuescript/yue_compiler.cpp | 14 | ||||
| -rwxr-xr-x | src/yuescript/yue_parser.cpp | 40 | ||||
| -rwxr-xr-x | 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 | |||
| 28 | global * | 28 | global * |
| 29 | $v! | 29 | $v! |
| 30 | 30 | ||
| 31 | do | ||
| 32 | f | ||
| 33 | :v | ||
| 34 | |||
| 35 | tb = while f | ||
| 36 | :v | ||
| 37 | |||
| 38 | repeat | ||
| 39 | print v | ||
| 40 | until f | ||
| 41 | :v | ||
| 42 | |||
| 43 | with f | ||
| 44 | :v = tb | ||
| 45 | .x = 1 | ||
| 46 | |||
| 47 | x = if f | ||
| 48 | :v | ||
| 49 | |||
| 50 | x = switch f | ||
| 51 | :v | ||
| 52 | when f | ||
| 53 | :v | ||
| 54 | |||
| 55 | nums = for num = 1, len | ||
| 56 | :num | ||
| 57 | |||
| 58 | objects = for item in *items | ||
| 59 | name: item | ||
| 60 | |||
| 31 | nil | 61 | 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 | |||
| 267 | z = x andb | 267 | z = x andb |
| 268 | 268 | ||
| 269 | 269 | ||
| 270 | -- undelimited tables | 270 | while 10 > something( |
| 271 | something: "world" | ||
| 272 | ) | ||
| 273 | print "yeah" | ||
| 271 | 274 | ||
| 272 | while 10 > something | 275 | -- undelimited tables |
| 273 | something: "world" | ||
| 274 | print "yeah" | ||
| 275 | 276 | ||
| 276 | x = | 277 | x = |
| 277 | okay: sure | 278 | 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 | |||
| 27 | do | 27 | do |
| 28 | print(123) | 28 | print(123) |
| 29 | end | 29 | end |
| 30 | do | ||
| 31 | f({ | ||
| 32 | v = v | ||
| 33 | }) | ||
| 34 | local tb | ||
| 35 | do | ||
| 36 | local _accum_0 = { } | ||
| 37 | local _len_0 = 1 | ||
| 38 | while f do | ||
| 39 | _accum_0[_len_0] = { | ||
| 40 | v = v | ||
| 41 | } | ||
| 42 | _len_0 = _len_0 + 1 | ||
| 43 | end | ||
| 44 | tb = _accum_0 | ||
| 45 | end | ||
| 46 | repeat | ||
| 47 | print(v) | ||
| 48 | until f({ | ||
| 49 | v = v | ||
| 50 | }) | ||
| 51 | do | ||
| 52 | local _with_0 = f | ||
| 53 | local v = tb.v | ||
| 54 | _with_0.x = 1 | ||
| 55 | end | ||
| 56 | local x | ||
| 57 | if f then | ||
| 58 | x = { | ||
| 59 | v = v | ||
| 60 | } | ||
| 61 | end | ||
| 62 | do | ||
| 63 | local _exp_0 = f({ | ||
| 64 | v = v | ||
| 65 | }) | ||
| 66 | if f == _exp_0 then | ||
| 67 | x = { | ||
| 68 | v = v | ||
| 69 | } | ||
| 70 | end | ||
| 71 | end | ||
| 72 | local nums | ||
| 73 | do | ||
| 74 | local _accum_0 = { } | ||
| 75 | local _len_0 = 1 | ||
| 76 | for num = 1, len do | ||
| 77 | _accum_0[_len_0] = { | ||
| 78 | num = num | ||
| 79 | } | ||
| 80 | _len_0 = _len_0 + 1 | ||
| 81 | end | ||
| 82 | nums = _accum_0 | ||
| 83 | end | ||
| 84 | local objects | ||
| 85 | do | ||
| 86 | local _accum_0 = { } | ||
| 87 | local _len_0 = 1 | ||
| 88 | local _list_0 = items | ||
| 89 | for _index_0 = 1, #_list_0 do | ||
| 90 | local item = _list_0[_index_0] | ||
| 91 | _accum_0[_len_0] = { | ||
| 92 | name = item | ||
| 93 | } | ||
| 94 | _len_0 = _len_0 + 1 | ||
| 95 | end | ||
| 96 | objects = _accum_0 | ||
| 97 | end | ||
| 98 | end | ||
| 30 | return nil | 99 | 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; | |||
| 60 | 60 | ||
| 61 | typedef std::list<std::string> str_list; | 61 | typedef std::list<std::string> str_list; |
| 62 | 62 | ||
| 63 | const std::string_view version = "0.10.7"sv; | 63 | const std::string_view version = "0.10.8"sv; |
| 64 | const std::string_view extension = "yue"sv; | 64 | const std::string_view extension = "yue"sv; |
| 65 | 65 | ||
| 66 | class YueCompilerImpl { | 66 | class YueCompilerImpl { |
| @@ -1876,8 +1876,16 @@ private: | |||
| 1876 | if (destructNode || (destructNode = value->item.as<simple_table_t>())) { | 1876 | if (destructNode || (destructNode = value->item.as<simple_table_t>())) { |
| 1877 | if (*j != nullNode) { | 1877 | if (*j != nullNode) { |
| 1878 | if (auto ssVal = simpleSingleValueFrom(*j)) { | 1878 | if (auto ssVal = simpleSingleValueFrom(*j)) { |
| 1879 | if (ssVal->value.is<const_value_t>()) { | 1879 | switch (ssVal->value->getId()) { |
| 1880 | throw std::logic_error(_info.errorMessage("can not destructure a const value"sv, ssVal->value)); | 1880 | case id<const_value_t>(): |
| 1881 | throw std::logic_error(_info.errorMessage("can not destructure a const value"sv, ssVal->value)); | ||
| 1882 | break; | ||
| 1883 | case id<Num_t>(): | ||
| 1884 | throw std::logic_error(_info.errorMessage("can not destructure a number"sv, ssVal->value)); | ||
| 1885 | break; | ||
| 1886 | case id<FunLit_t>(): | ||
| 1887 | throw std::logic_error(_info.errorMessage("can not destructure a function"sv, ssVal->value)); | ||
| 1888 | break; | ||
| 1881 | } | 1889 | } |
| 1882 | } | 1890 | } |
| 1883 | } else { | 1891 | } 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() { | |||
| 75 | #define key(str) (str >> not_(AlphaNum)) | 75 | #define key(str) (str >> not_(AlphaNum)) |
| 76 | #define disable_do(patt) (DisableDo >> ((patt) >> EnableDo | EnableDo >> Cut)) | 76 | #define disable_do(patt) (DisableDo >> ((patt) >> EnableDo | EnableDo >> Cut)) |
| 77 | #define disable_chain(patt) (DisableChain >> ((patt) >> EnableChain | EnableChain >> Cut)) | 77 | #define disable_chain(patt) (DisableChain >> ((patt) >> EnableChain | EnableChain >> Cut)) |
| 78 | #define disable_do_chain(patt) (DisableDoChain >> ((patt) >> EnableDoChain | EnableDoChain >> Cut)) | 78 | #define disable_do_chain_arg_table_block(patt) (DisableDoChainArgTableBlock >> ((patt) >> EnableDoChainArgTableBlock | EnableDoChainArgTableBlock >> Cut)) |
| 79 | #define disable_arg_table_block(patt) (DisableArgTableBlock >> ((patt) >> EnableArgTableBlock | EnableArgTableBlock >> Cut)) | 79 | #define disable_arg_table_block(patt) (DisableArgTableBlock >> ((patt) >> EnableArgTableBlock | EnableArgTableBlock >> Cut)) |
| 80 | #define plain_body_with(str) (-(Space >> key(str)) >> InBlock | Space >> key(str) >> Statement) | 80 | #define plain_body_with(str) (-(Space >> key(str)) >> InBlock | Space >> key(str) >> Statement) |
| 81 | #define plain_body (InBlock | Statement) | 81 | #define plain_body (InBlock | Statement) |
| @@ -223,8 +223,8 @@ YueParser::YueParser() { | |||
| 223 | 223 | ||
| 224 | WithExp = ExpList >> -Assign; | 224 | WithExp = ExpList >> -Assign; |
| 225 | 225 | ||
| 226 | With = Space >> key("with") >> -existential_op >> disable_do_chain(WithExp) >> plain_body_with("do"); | 226 | With = Space >> key("with") >> -existential_op >> disable_do_chain_arg_table_block(WithExp) >> plain_body_with("do"); |
| 227 | SwitchCase = Space >> key("when") >> disable_chain(ExpList) >> plain_body_with("then"); | 227 | SwitchCase = Space >> key("when") >> disable_chain(disable_arg_table_block(ExpList)) >> plain_body_with("then"); |
| 228 | SwitchElse = Space >> key("else") >> plain_body; | 228 | SwitchElse = Space >> key("else") >> plain_body; |
| 229 | 229 | ||
| 230 | SwitchBlock = *EmptyLine >> | 230 | SwitchBlock = *EmptyLine >> |
| @@ -238,54 +238,56 @@ YueParser::YueParser() { | |||
| 238 | >> -Space >> Break >> SwitchBlock; | 238 | >> -Space >> Break >> SwitchBlock; |
| 239 | 239 | ||
| 240 | assignment = ExpList >> Assign; | 240 | assignment = ExpList >> Assign; |
| 241 | IfCond = disable_do_chain(disable_arg_table_block(assignment | Exp)); | 241 | IfCond = disable_do_chain_arg_table_block(assignment | Exp); |
| 242 | IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("elseif") >> IfCond >> plain_body_with("then"); | 242 | IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("elseif") >> IfCond >> plain_body_with("then"); |
| 243 | IfElse = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("else") >> plain_body; | 243 | IfElse = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("else") >> plain_body; |
| 244 | IfType = (expr("if") | expr("unless")) >> not_(AlphaNum); | 244 | IfType = (expr("if") | expr("unless")) >> not_(AlphaNum); |
| 245 | If = Space >> IfType >> IfCond >> plain_body_with("then") >> *IfElseIf >> -IfElse; | 245 | If = Space >> IfType >> IfCond >> plain_body_with("then") >> *IfElseIf >> -IfElse; |
| 246 | 246 | ||
| 247 | WhileType = (expr("while") | expr("until")) >> not_(AlphaNum); | 247 | WhileType = (expr("while") | expr("until")) >> not_(AlphaNum); |
| 248 | While = WhileType >> disable_do_chain(Exp) >> plain_body_with("do"); | 248 | While = WhileType >> disable_do_chain_arg_table_block(Exp) >> plain_body_with("do"); |
| 249 | Repeat = key("repeat") >> Body >> Break >> *EmptyLine >> CheckIndent >> Space >> key("until") >> Exp; | 249 | Repeat = key("repeat") >> Body >> Break >> *EmptyLine >> CheckIndent >> Space >> key("until") >> Exp; |
| 250 | 250 | ||
| 251 | for_step_value = sym(',') >> Exp; | 251 | for_step_value = sym(',') >> Exp; |
| 252 | for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; | 252 | for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; |
| 253 | 253 | ||
| 254 | For = key("for") >> disable_do_chain(for_args) >> plain_body_with("do"); | 254 | For = key("for") >> disable_do_chain_arg_table_block(for_args) >> plain_body_with("do"); |
| 255 | 255 | ||
| 256 | for_in = star_exp | ExpList; | 256 | for_in = star_exp | ExpList; |
| 257 | 257 | ||
| 258 | ForEach = key("for") >> AssignableNameList >> Space >> key("in") >> | 258 | ForEach = key("for") >> AssignableNameList >> Space >> key("in") >> |
| 259 | disable_do_chain(for_in) >> plain_body_with("do"); | 259 | disable_do_chain_arg_table_block(for_in) >> plain_body_with("do"); |
| 260 | 260 | ||
| 261 | Do = pl::user(Space >> key("do"), [](const item_t& item) { | 261 | Do = pl::user(Space >> key("do"), [](const item_t& item) { |
| 262 | State* st = reinterpret_cast<State*>(item.user_data); | 262 | State* st = reinterpret_cast<State*>(item.user_data); |
| 263 | return st->doStack.empty() || st->doStack.top(); | 263 | return st->noDoStack.empty() || !st->noDoStack.top(); |
| 264 | }) >> Body; | 264 | }) >> Body; |
| 265 | 265 | ||
| 266 | DisableDo = pl::user(true_(), [](const item_t& item) { | 266 | DisableDo = pl::user(true_(), [](const item_t& item) { |
| 267 | State* st = reinterpret_cast<State*>(item.user_data); | 267 | State* st = reinterpret_cast<State*>(item.user_data); |
| 268 | st->doStack.push(false); | 268 | st->noDoStack.push(true); |
| 269 | return true; | 269 | return true; |
| 270 | }); | 270 | }); |
| 271 | 271 | ||
| 272 | EnableDo = pl::user(true_(), [](const item_t& item) { | 272 | EnableDo = pl::user(true_(), [](const item_t& item) { |
| 273 | State* st = reinterpret_cast<State*>(item.user_data); | 273 | State* st = reinterpret_cast<State*>(item.user_data); |
| 274 | st->doStack.pop(); | 274 | st->noDoStack.pop(); |
| 275 | return true; | 275 | return true; |
| 276 | }); | 276 | }); |
| 277 | 277 | ||
| 278 | DisableDoChain = pl::user(true_(), [](const item_t& item) { | 278 | DisableDoChainArgTableBlock = pl::user(true_(), [](const item_t& item) { |
| 279 | State* st = reinterpret_cast<State*>(item.user_data); | 279 | State* st = reinterpret_cast<State*>(item.user_data); |
| 280 | st->doStack.push(false); | 280 | st->noDoStack.push(true); |
| 281 | st->chainBlockStack.push(false); | 281 | st->noChainBlockStack.push(true); |
| 282 | st->noTableBlockStack.push(true); | ||
| 282 | return true; | 283 | return true; |
| 283 | }); | 284 | }); |
| 284 | 285 | ||
| 285 | EnableDoChain = pl::user(true_(), [](const item_t& item) { | 286 | EnableDoChainArgTableBlock = pl::user(true_(), [](const item_t& item) { |
| 286 | State* st = reinterpret_cast<State*>(item.user_data); | 287 | State* st = reinterpret_cast<State*>(item.user_data); |
| 287 | st->doStack.pop(); | 288 | st->noDoStack.pop(); |
| 288 | st->chainBlockStack.pop(); | 289 | st->noChainBlockStack.pop(); |
| 290 | st->noTableBlockStack.pop(); | ||
| 289 | return true; | 291 | return true; |
| 290 | }); | 292 | }); |
| 291 | 293 | ||
| @@ -370,20 +372,20 @@ YueParser::YueParser() { | |||
| 370 | 372 | ||
| 371 | DisableChain = pl::user(true_(), [](const item_t& item) { | 373 | DisableChain = pl::user(true_(), [](const item_t& item) { |
| 372 | State* st = reinterpret_cast<State*>(item.user_data); | 374 | State* st = reinterpret_cast<State*>(item.user_data); |
| 373 | st->chainBlockStack.push(false); | 375 | st->noChainBlockStack.push(true); |
| 374 | return true; | 376 | return true; |
| 375 | }); | 377 | }); |
| 376 | 378 | ||
| 377 | EnableChain = pl::user(true_(), [](const item_t& item) { | 379 | EnableChain = pl::user(true_(), [](const item_t& item) { |
| 378 | State* st = reinterpret_cast<State*>(item.user_data); | 380 | State* st = reinterpret_cast<State*>(item.user_data); |
| 379 | st->chainBlockStack.pop(); | 381 | st->noChainBlockStack.pop(); |
| 380 | return true; | 382 | return true; |
| 381 | }); | 383 | }); |
| 382 | 384 | ||
| 383 | chain_line = CheckIndent >> (chain_item | Space >> (chain_dot_chain | ColonChain)) >> -InvokeArgs; | 385 | chain_line = CheckIndent >> (chain_item | Space >> (chain_dot_chain | ColonChain)) >> -InvokeArgs; |
| 384 | chain_block = pl::user(true_(), [](const item_t& item) { | 386 | chain_block = pl::user(true_(), [](const item_t& item) { |
| 385 | State* st = reinterpret_cast<State*>(item.user_data); | 387 | State* st = reinterpret_cast<State*>(item.user_data); |
| 386 | return st->chainBlockStack.empty() || st->chainBlockStack.top(); | 388 | return st->noChainBlockStack.empty() || !st->noChainBlockStack.top(); |
| 387 | }) >> +SpaceBreak >> Advance >> ensure( | 389 | }) >> +SpaceBreak >> Advance >> ensure( |
| 388 | chain_line >> *(+SpaceBreak >> chain_line), PopIndent); | 390 | chain_line >> *(+SpaceBreak >> chain_line), PopIndent); |
| 389 | ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -(InvokeArgs | chain_block) >> -table_appending_op; | 391 | 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: | |||
| 77 | std::string moduleName = "_module_0"; | 77 | std::string moduleName = "_module_0"; |
| 78 | std::string buffer; | 78 | std::string buffer; |
| 79 | std::stack<int> indents; | 79 | std::stack<int> indents; |
| 80 | std::stack<bool> doStack; | 80 | std::stack<bool> noDoStack; |
| 81 | std::stack<bool> chainBlockStack; | 81 | std::stack<bool> noChainBlockStack; |
| 82 | std::stack<bool> noTableBlockStack; | 82 | std::stack<bool> noTableBlockStack; |
| 83 | }; | 83 | }; |
| 84 | 84 | ||
| @@ -135,8 +135,8 @@ private: | |||
| 135 | rule EnableDo; | 135 | rule EnableDo; |
| 136 | rule DisableChain; | 136 | rule DisableChain; |
| 137 | rule EnableChain; | 137 | rule EnableChain; |
| 138 | rule DisableDoChain; | 138 | rule DisableDoChainArgTableBlock; |
| 139 | rule EnableDoChain; | 139 | rule EnableDoChainArgTableBlock; |
| 140 | rule DisableArgTableBlock; | 140 | rule DisableArgTableBlock; |
| 141 | rule EnableArgTableBlock; | 141 | rule EnableArgTableBlock; |
| 142 | rule SwitchElse; | 142 | rule SwitchElse; |
