diff options
Diffstat (limited to 'src/yuescript/yue_parser.cpp')
-rw-r--r-- | src/yuescript/yue_parser.cpp | 64 |
1 files changed, 54 insertions, 10 deletions
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 2fc1333..5bb4817 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
@@ -114,6 +114,13 @@ YueParser::YueParser() { | |||
114 | ) \ | 114 | ) \ |
115 | ) | 115 | ) |
116 | 116 | ||
117 | #define disable_for_rule(patt) ( \ | ||
118 | disable_for >> ( \ | ||
119 | (patt) >> enable_for | \ | ||
120 | enable_for >> cut \ | ||
121 | ) \ | ||
122 | ) | ||
123 | |||
117 | #define body_with(str) ( \ | 124 | #define body_with(str) ( \ |
118 | key(str) >> space >> (in_block | Statement) | \ | 125 | key(str) >> space >> (in_block | Statement) | \ |
119 | in_block | \ | 126 | in_block | \ |
@@ -327,14 +334,18 @@ YueParser::YueParser() { | |||
327 | While = WhileType >> space >> disable_do_chain_arg_table_block_rule(Exp) >> space >> opt_body_with("do"); | 334 | While = WhileType >> space >> disable_do_chain_arg_table_block_rule(Exp) >> space >> opt_body_with("do"); |
328 | Repeat = key("repeat") >> space >> Body >> line_break >> *space_break >> check_indent_match >> space >> key("until") >> space >> Exp; | 335 | Repeat = key("repeat") >> space >> Body >> line_break >> *space_break >> check_indent_match >> space >> key("until") >> space >> Exp; |
329 | 336 | ||
337 | for_key = pl::user(key("for"), [](const item_t& item) { | ||
338 | State* st = reinterpret_cast<State*>(item.user_data); | ||
339 | return st->noForStack.empty() || !st->noForStack.top(); | ||
340 | }); | ||
330 | ForStepValue = ',' >> space >> Exp; | 341 | ForStepValue = ',' >> space >> Exp; |
331 | for_args = Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> space >> -ForStepValue; | 342 | for_args = Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> space >> -ForStepValue; |
332 | 343 | ||
333 | For = key("for") >> space >> disable_do_chain_arg_table_block_rule(for_args) >> space >> opt_body_with("do"); | 344 | For = for_key >> space >> disable_do_chain_arg_table_block_rule(for_args) >> space >> opt_body_with("do"); |
334 | 345 | ||
335 | for_in = StarExp | ExpList; | 346 | for_in = StarExp | ExpList; |
336 | 347 | ||
337 | ForEach = key("for") >> space >> AssignableNameList >> space >> key("in") >> space >> | 348 | ForEach = for_key >> space >> AssignableNameList >> space >> key("in") >> space >> |
338 | disable_do_chain_arg_table_block_rule(for_in) >> space >> opt_body_with("do"); | 349 | disable_do_chain_arg_table_block_rule(for_in) >> space >> opt_body_with("do"); |
339 | 350 | ||
340 | Do = pl::user(key("do"), [](const item_t& item) { | 351 | Do = pl::user(key("do"), [](const item_t& item) { |
@@ -382,12 +393,24 @@ YueParser::YueParser() { | |||
382 | return true; | 393 | return true; |
383 | }); | 394 | }); |
384 | 395 | ||
396 | disable_for = pl::user(true_(), [](const item_t& item) { | ||
397 | State* st = reinterpret_cast<State*>(item.user_data); | ||
398 | st->noForStack.push(true); | ||
399 | return true; | ||
400 | }); | ||
401 | |||
402 | enable_for = pl::user(true_(), [](const item_t& item) { | ||
403 | State* st = reinterpret_cast<State*>(item.user_data); | ||
404 | st->noForStack.pop(); | ||
405 | return true; | ||
406 | }); | ||
407 | |||
385 | CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> Variable >> space >> in_block; | 408 | CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> Variable >> space >> in_block; |
386 | Try = key("try") >> space >> (in_block | Exp) >> -CatchBlock; | 409 | Try = key("try") >> space >> (in_block | Exp) >> -CatchBlock; |
387 | 410 | ||
388 | Comprehension = '[' >> not_('[') >> space >> Exp >> space >> CompInner >> space >> ']'; | 411 | Comprehension = '[' >> not_('[') >> space >> disable_for_rule(Exp) >> space >> CompInner >> space >> ']'; |
389 | CompValue = ',' >> space >> Exp; | 412 | CompValue = ',' >> space >> Exp; |
390 | TblComprehension = '{' >> (space >> Exp >> space >> -(CompValue >> space) >> CompInner >> space >> '}' | braces_expression_error); | 413 | TblComprehension = and_('{') >> ('{' >> space >> disable_for_rule(Exp >> space >> -(CompValue >> space)) >> CompInner >> space >> '}' | braces_expression_error); |
391 | 414 | ||
392 | CompInner = Seperator >> (CompForEach | CompFor) >> *(space >> comp_clause); | 415 | CompInner = Seperator >> (CompForEach | CompFor) >> *(space >> comp_clause); |
393 | StarExp = '*' >> space >> Exp; | 416 | StarExp = '*' >> space >> Exp; |
@@ -461,8 +484,24 @@ YueParser::YueParser() { | |||
461 | -(InvokeArgs | chain_block) >> | 484 | -(InvokeArgs | chain_block) >> |
462 | -TableAppendingOp; | 485 | -TableAppendingOp; |
463 | 486 | ||
487 | inc_exp_level = pl::user(true_(), [](const item_t& item) { | ||
488 | State* st = reinterpret_cast<State*>(item.user_data); | ||
489 | st->expLevel++; | ||
490 | const int max_exp_level = 100; | ||
491 | if (st->expLevel > max_exp_level) { | ||
492 | throw ParserError("nesting expressions exceeds 100 levels", *item.begin, *item.end); | ||
493 | } | ||
494 | return true; | ||
495 | }); | ||
496 | |||
497 | dec_exp_level = pl::user(true_(), [](const item_t& item) { | ||
498 | State* st = reinterpret_cast<State*>(item.user_data); | ||
499 | st->expLevel--; | ||
500 | return true; | ||
501 | }); | ||
502 | |||
464 | SimpleTable = Seperator >> key_value >> *(space >> ',' >> space >> key_value); | 503 | SimpleTable = Seperator >> key_value >> *(space >> ',' >> space >> key_value); |
465 | Value = SimpleValue | SimpleTable | ChainValue | String; | 504 | Value = inc_exp_level >> ensure(SimpleValue | SimpleTable | ChainValue | String, dec_exp_level); |
466 | 505 | ||
467 | single_string_inner = '\\' >> set("'\\") | not_('\'') >> any_char; | 506 | single_string_inner = '\\' >> set("'\\") | not_('\'') >> any_char; |
468 | SingleString = '\'' >> *single_string_inner >> '\''; | 507 | SingleString = '\'' >> *single_string_inner >> '\''; |
@@ -495,7 +534,7 @@ YueParser::YueParser() { | |||
495 | LuaString = LuaStringOpen >> -line_break >> LuaStringContent >> LuaStringClose; | 534 | LuaString = LuaStringOpen >> -line_break >> LuaStringContent >> LuaStringClose; |
496 | 535 | ||
497 | Parens = '(' >> *space_break >> space >> Exp >> *space_break >> space >> ')'; | 536 | Parens = '(' >> *space_break >> space >> Exp >> *space_break >> space >> ')'; |
498 | Callable = Variable | SelfItem | MacroName | VarArg | Parens; | 537 | Callable = Variable | SelfItem | MacroName | Parens; |
499 | fn_args_exp_list = space >> Exp >> space >> *((line_break | ',') >> white >> Exp); | 538 | fn_args_exp_list = space >> Exp >> space >> *((line_break | ',') >> white >> Exp); |
500 | 539 | ||
501 | fn_args = | 540 | fn_args = |
@@ -507,7 +546,7 @@ YueParser::YueParser() { | |||
507 | Metamethod = '<' >> space >> meta_index >> space >> '>'; | 546 | Metamethod = '<' >> space >> meta_index >> space >> '>'; |
508 | 547 | ||
509 | ExistentialOp = '?' >> not_('?'); | 548 | ExistentialOp = '?' >> not_('?'); |
510 | TableAppendingOp = "[]"; | 549 | TableAppendingOp = and_('[') >> ("[]" | brackets_expression_error); |
511 | chain_call = ( | 550 | chain_call = ( |
512 | Callable >> -ExistentialOp >> -chain_items | 551 | Callable >> -ExistentialOp >> -chain_items |
513 | ) | ( | 552 | ) | ( |
@@ -736,8 +775,13 @@ YueParser::YueParser() { | |||
736 | 775 | ||
737 | ConstValue = (expr("nil") | "true" | "false") >> not_alpha_num; | 776 | ConstValue = (expr("nil") | "true" | "false") >> not_alpha_num; |
738 | 777 | ||
739 | braces_expression_error = pl::user("{", [](const item_t& item) { | 778 | braces_expression_error = pl::user(true_(), [](const item_t& item) { |
740 | throw ParserError("invalid brace expression", *item.begin, *item.end); | 779 | throw ParserError("syntax error in brace expression", *item.begin, *item.end); |
780 | return false; | ||
781 | }); | ||
782 | |||
783 | brackets_expression_error = pl::user(true_(), [](const item_t& item) { | ||
784 | throw ParserError("syntax error in bracket expression", *item.begin, *item.end); | ||
741 | return false; | 785 | return false; |
742 | }); | 786 | }); |
743 | 787 | ||
@@ -745,7 +789,7 @@ YueParser::YueParser() { | |||
745 | TableLit | ConstValue | If | Switch | Try | With | | 789 | TableLit | ConstValue | If | Switch | Try | With | |
746 | ClassDecl | ForEach | For | While | Do | | 790 | ClassDecl | ForEach | For | While | Do | |
747 | UnaryValue | TblComprehension | Comprehension | | 791 | UnaryValue | TblComprehension | Comprehension | |
748 | FunLit | Num; | 792 | FunLit | Num | VarArg; |
749 | 793 | ||
750 | ExpListAssign = ExpList >> -(space >> (Update | Assign)) >> not_(space >> '='); | 794 | ExpListAssign = ExpList >> -(space >> (Update | Assign)) >> not_(space >> '='); |
751 | 795 | ||