aboutsummaryrefslogtreecommitdiff
path: root/src/yuescript/yue_parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuescript/yue_parser.cpp')
-rw-r--r--src/yuescript/yue_parser.cpp64
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