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.cpp190
1 files changed, 130 insertions, 60 deletions
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index ceb1f7c..1942e23 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -67,24 +67,28 @@ YueParser::YueParser() {
67 num_char = range('0', '9') >> *(range('0', '9') | '_' >> and_(range('0', '9'))); 67 num_char = range('0', '9') >> *(range('0', '9') | '_' >> and_(range('0', '9')));
68 num_char_hex = range('0', '9') | range('a', 'f') | range('A', 'F'); 68 num_char_hex = range('0', '9') | range('a', 'f') | range('A', 'F');
69 num_lit = num_char_hex >> *(num_char_hex | '_' >> and_(num_char_hex)); 69 num_lit = num_char_hex >> *(num_char_hex | '_' >> and_(num_char_hex));
70 num_bin_lit = set("01") >> *(set("01") | '_' >> and_(set("01")));
70 Num = 71 Num =
71 "0x" >> ( 72 '0' >> (
72 +num_lit >> ( 73 set("xX") >> (
73 '.' >> +num_lit >> -num_expo_hex | 74 num_lit >> (
74 num_expo_hex | 75 '.' >> num_lit >> -num_expo_hex |
75 lj_num | 76 num_expo_hex |
76 true_() 77 lj_num |
77 ) | ( 78 true_()
78 '.' >> +num_lit >> -num_expo_hex 79 ) | (
79 ) 80 '.' >> num_lit >> -num_expo_hex
81 )
82 ) |
83 set("bB") >> num_bin_lit
80 ) | 84 ) |
81 +num_char >> ( 85 num_char >> (
82 '.' >> +num_char >> -num_expo | 86 '.' >> num_char >> -num_expo |
83 num_expo | 87 num_expo |
84 lj_num | 88 lj_num |
85 true_() 89 true_()
86 ) | 90 ) |
87 '.' >> +num_char >> -num_expo; 91 '.' >> num_char >> -num_expo;
88 92
89 cut = false_(); 93 cut = false_();
90 Seperator = true_(); 94 Seperator = true_();
@@ -114,8 +118,8 @@ YueParser::YueParser() {
114 return false; 118 return false;
115 }); 119 });
116 120
117 if_assignment_syntax_error = pl::user(true_(), [](const item_t& item) { 121 assignment_expression_syntax_error = pl::user(true_(), [](const item_t& item) {
118 throw ParserError("use := for if-assignment expression"sv, item.begin); 122 throw ParserError("use := for assignment expression"sv, item.begin);
119 return false; 123 return false;
120 }); 124 });
121 125
@@ -158,6 +162,13 @@ YueParser::YueParser() {
158 ) \ 162 ) \
159 ) 163 )
160 164
165 #define disable_until_rule(patt) ( \
166 disable_until >> ( \
167 (patt) >> enable_until | \
168 enable_until >> cut \
169 ) \
170 )
171
161 #define body_with(str) ( \ 172 #define body_with(str) ( \
162 key(str) >> space >> (in_block | Statement) | \ 173 key(str) >> space >> (in_block | Statement) | \
163 in_block | \ 174 in_block | \
@@ -321,7 +332,7 @@ YueParser::YueParser() {
321 Exp; 332 Exp;
322 import_tab_list = import_tab_item >> *(space >> ',' >> space >> import_tab_item); 333 import_tab_list = import_tab_item >> *(space >> ',' >> space >> import_tab_item);
323 import_tab_line = ( 334 import_tab_line = (
324 push_indent_match >> (space >> import_tab_list >> pop_indent | pop_indent) 335 push_indent_match >> ensure(space >> import_tab_list, pop_indent)
325 ) | space; 336 ) | space;
326 import_tab_lines = space_break >> import_tab_line >> *(-(space >> ',') >> space_break >> import_tab_line) >> -(space >> ','); 337 import_tab_lines = space_break >> import_tab_line >> *(-(space >> ',') >> space_break >> import_tab_line) >> -(space >> ',');
327 import_tab_key_value = key_value | ':' >> MacroName | MacroNamePair | ImportAllMacro; 338 import_tab_key_value = key_value | ':' >> MacroName | MacroNamePair | ImportAllMacro;
@@ -338,7 +349,9 @@ YueParser::YueParser() {
338 349
339 ImportAs = ImportLiteral >> -(space >> key("as") >> space >> (ImportTabLit | Variable | ImportAllMacro)); 350 ImportAs = ImportLiteral >> -(space >> key("as") >> space >> (ImportTabLit | Variable | ImportAllMacro));
340 351
341 Import = key("import") >> space >> (ImportAs | ImportFrom) | FromImport; 352 ImportGlobal = Seperator >> UnicodeName >> *('.' >> UnicodeName) >> -(space >> key("as") >> space >> Variable);
353
354 Import = key("import") >> space >> (ImportAs | ImportFrom | ImportGlobal) | FromImport;
342 355
343 Label = "::" >> LabelName >> "::"; 356 Label = "::" >> LabelName >> "::";
344 357
@@ -346,11 +359,13 @@ YueParser::YueParser() {
346 359
347 ShortTabAppending = "[]" >> space >> Assign; 360 ShortTabAppending = "[]" >> space >> Assign;
348 361
349 BreakLoop = (expr("break") | "continue") >> not_alpha_num; 362 Break = key("break");
363 Continue = key("continue");
364 BreakLoop = (Break >> -(space >> Exp) | Continue) >> not_alpha_num;
350 365
351 Return = key("return") >> -(space >> (TableBlock | ExpListLow)); 366 Return = key("return") >> -(space >> (TableBlock | ExpListLow));
352 367
353 with_exp = ExpList >> -(space >> Assign); 368 with_exp = ExpList >> -(space >> (':' >> Assign | and_('=') >> assignment_expression_syntax_error));
354 369
355 With = key("with") >> -ExistentialOp >> space >> disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do"); 370 With = key("with") >> -ExistentialOp >> space >> disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do");
356 SwitchCase = key("when") >> space >> disable_chain_rule(disable_arg_table_block_rule(SwitchList)) >> space >> body_with("then"); 371 SwitchCase = key("when") >> space >> disable_chain_rule(disable_arg_table_block_rule(SwitchList)) >> space >> body_with("then");
@@ -366,7 +381,8 @@ YueParser::YueParser() {
366 and_(SimpleTable | TableLit) >> Exp | 381 and_(SimpleTable | TableLit) >> Exp |
367 exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) 382 exp_not_tab >> *(space >> ',' >> space >> exp_not_tab)
368 ); 383 );
369 Switch = key("switch") >> space >> Exp >> 384 Switch = key("switch") >> space >>
385 Exp >> -(space >> Assignment) >>
370 space >> Seperator >> ( 386 space >> Seperator >> (
371 SwitchCase >> space >> ( 387 SwitchCase >> space >> (
372 switch_block | 388 switch_block |
@@ -375,20 +391,26 @@ YueParser::YueParser() {
375 +space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent 391 +space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent
376 ); 392 );
377 393
378 Assignment = -(',' >> space >> ExpList >> space) >> (':' >> Assign | and_('=') >> if_assignment_syntax_error); 394 Assignment = -(',' >> space >> ExpList >> space) >> (':' >> Assign | and_('=') >> assignment_expression_syntax_error);
379 IfCond = disable_chain_rule(disable_arg_table_block_rule(Exp >> -(space >> Assignment))); 395 IfCond = disable_chain_rule(disable_arg_table_block_rule(Exp >> -(space >> Assignment)));
380 if_else_if = -(line_break >> *space_break >> check_indent_match) >> space >> key("elseif") >> space >> IfCond >> space >> body_with("then"); 396 if_else_if = -(line_break >> *space_break >> check_indent_match) >> space >> key("elseif") >> space >> IfCond >> space >> body_with("then");
381 if_else = -(line_break >> *space_break >> check_indent_match) >> space >> key("else") >> space >> body; 397 if_else = -(line_break >> *space_break >> check_indent_match) >> space >> key("else") >> space >> body;
382 IfType = (expr("if") | "unless") >> not_alpha_num; 398 IfType = (expr("if") | "unless") >> not_alpha_num;
383 If = IfType >> space >> IfCond >> space >> opt_body_with("then") >> *if_else_if >> -if_else; 399 If = IfType >> space >> IfCond >> space >> opt_body_with("then") >> *if_else_if >> -if_else;
384 400
385 WhileType = (expr("while") | "until") >> not_alpha_num; 401 WhileType = (expr("while") | pl::user("until", [](const item_t& item) {
386 While = WhileType >> space >> disable_do_chain_arg_table_block_rule(Exp >> -(space >> Assignment)) >> space >> opt_body_with("do"); 402 State* st = reinterpret_cast<State*>(item.user_data);
387 Repeat = key("repeat") >> space >> Body >> line_break >> *space_break >> check_indent_match >> space >> key("until") >> space >> Exp; 403 return st->noUntilStack.empty() || !st->noUntilStack.back();
404 })) >> not_alpha_num;
405 While = key(WhileType) >> space >> disable_do_chain_arg_table_block_rule(Exp >> -(space >> Assignment)) >> space >> opt_body_with("do");
406 Repeat = key("repeat") >> space >> (
407 in_block >> line_break >> *space_break >> check_indent_match |
408 disable_until_rule(Statement)
409 ) >> space >> key("until") >> space >> Exp;
388 410
389 for_key = pl::user(key("for"), [](const item_t& item) { 411 for_key = pl::user(key("for"), [](const item_t& item) {
390 State* st = reinterpret_cast<State*>(item.user_data); 412 State* st = reinterpret_cast<State*>(item.user_data);
391 return st->noForStack.empty() || !st->noForStack.top(); 413 return st->noForStack.empty() || !st->noForStack.back();
392 }); 414 });
393 ForStepValue = ',' >> space >> Exp; 415 ForStepValue = ',' >> space >> Exp;
394 for_args = Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> space >> -ForStepValue; 416 for_args = Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> space >> -ForStepValue;
@@ -402,18 +424,18 @@ YueParser::YueParser() {
402 424
403 Do = pl::user(key("do"), [](const item_t& item) { 425 Do = pl::user(key("do"), [](const item_t& item) {
404 State* st = reinterpret_cast<State*>(item.user_data); 426 State* st = reinterpret_cast<State*>(item.user_data);
405 return st->noDoStack.empty() || !st->noDoStack.top(); 427 return st->noDoStack.empty() || !st->noDoStack.back();
406 }) >> space >> Body; 428 }) >> space >> Body;
407 429
408 disable_do = pl::user(true_(), [](const item_t& item) { 430 disable_do = pl::user(true_(), [](const item_t& item) {
409 State* st = reinterpret_cast<State*>(item.user_data); 431 State* st = reinterpret_cast<State*>(item.user_data);
410 st->noDoStack.push(true); 432 st->noDoStack.push_back(true);
411 return true; 433 return true;
412 }); 434 });
413 435
414 enable_do = pl::user(true_(), [](const item_t& item) { 436 enable_do = pl::user(true_(), [](const item_t& item) {
415 State* st = reinterpret_cast<State*>(item.user_data); 437 State* st = reinterpret_cast<State*>(item.user_data);
416 st->noDoStack.pop(); 438 st->noDoStack.pop_back();
417 return true; 439 return true;
418 }); 440 });
419 441
@@ -431,46 +453,58 @@ YueParser::YueParser() {
431 453
432 disable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { 454 disable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) {
433 State* st = reinterpret_cast<State*>(item.user_data); 455 State* st = reinterpret_cast<State*>(item.user_data);
434 st->noDoStack.push(true); 456 st->noDoStack.push_back(true);
435 st->noChainBlockStack.push(true); 457 st->noChainBlockStack.push_back(true);
436 st->noTableBlockStack.push(true); 458 st->noTableBlockStack.push_back(true);
437 return true; 459 return true;
438 }); 460 });
439 461
440 enable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { 462 enable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) {
441 State* st = reinterpret_cast<State*>(item.user_data); 463 State* st = reinterpret_cast<State*>(item.user_data);
442 st->noDoStack.pop(); 464 st->noDoStack.pop_back();
443 st->noChainBlockStack.pop(); 465 st->noChainBlockStack.pop_back();
444 st->noTableBlockStack.pop(); 466 st->noTableBlockStack.pop_back();
445 return true; 467 return true;
446 }); 468 });
447 469
448 disable_arg_table_block = pl::user(true_(), [](const item_t& item) { 470 disable_arg_table_block = pl::user(true_(), [](const item_t& item) {
449 State* st = reinterpret_cast<State*>(item.user_data); 471 State* st = reinterpret_cast<State*>(item.user_data);
450 st->noTableBlockStack.push(true); 472 st->noTableBlockStack.push_back(true);
451 return true; 473 return true;
452 }); 474 });
453 475
454 enable_arg_table_block = pl::user(true_(), [](const item_t& item) { 476 enable_arg_table_block = pl::user(true_(), [](const item_t& item) {
455 State* st = reinterpret_cast<State*>(item.user_data); 477 State* st = reinterpret_cast<State*>(item.user_data);
456 st->noTableBlockStack.pop(); 478 st->noTableBlockStack.pop_back();
457 return true; 479 return true;
458 }); 480 });
459 481
460 disable_for = pl::user(true_(), [](const item_t& item) { 482 disable_for = pl::user(true_(), [](const item_t& item) {
461 State* st = reinterpret_cast<State*>(item.user_data); 483 State* st = reinterpret_cast<State*>(item.user_data);
462 st->noForStack.push(true); 484 st->noForStack.push_back(true);
463 return true; 485 return true;
464 }); 486 });
465 487
466 enable_for = pl::user(true_(), [](const item_t& item) { 488 enable_for = pl::user(true_(), [](const item_t& item) {
467 State* st = reinterpret_cast<State*>(item.user_data); 489 State* st = reinterpret_cast<State*>(item.user_data);
468 st->noForStack.pop(); 490 st->noForStack.pop_back();
491 return true;
492 });
493
494 disable_until = pl::user(true_(), [](const item_t& item) {
495 State* st = reinterpret_cast<State*>(item.user_data);
496 st->noUntilStack.push_back(true);
497 return true;
498 });
499
500 enable_until = pl::user(true_(), [](const item_t& item) {
501 State* st = reinterpret_cast<State*>(item.user_data);
502 st->noUntilStack.pop_back();
469 return true; 503 return true;
470 }); 504 });
471 505
472 CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> Variable >> space >> in_block; 506 CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> Variable >> space >> in_block;
473 Try = key("try") >> space >> (in_block | Exp) >> -CatchBlock; 507 Try = key("try") >> -ExistentialOp >> space >> (in_block | Exp) >> -CatchBlock;
474 508
475 list_value = 509 list_value =
476 and_( 510 and_(
@@ -557,20 +591,20 @@ YueParser::YueParser() {
557 591
558 disable_chain = pl::user(true_(), [](const item_t& item) { 592 disable_chain = pl::user(true_(), [](const item_t& item) {
559 State* st = reinterpret_cast<State*>(item.user_data); 593 State* st = reinterpret_cast<State*>(item.user_data);
560 st->noChainBlockStack.push(true); 594 st->noChainBlockStack.push_back(true);
561 return true; 595 return true;
562 }); 596 });
563 597
564 enable_chain = pl::user(true_(), [](const item_t& item) { 598 enable_chain = pl::user(true_(), [](const item_t& item) {
565 State* st = reinterpret_cast<State*>(item.user_data); 599 State* st = reinterpret_cast<State*>(item.user_data);
566 st->noChainBlockStack.pop(); 600 st->noChainBlockStack.pop_back();
567 return true; 601 return true;
568 }); 602 });
569 603
570 chain_line = check_indent_match >> space >> (chain_dot_chain | colon_chain) >> -InvokeArgs; 604 chain_line = check_indent_match >> space >> (chain_dot_chain | colon_chain) >> -InvokeArgs;
571 chain_block = pl::user(true_(), [](const item_t& item) { 605 chain_block = pl::user(true_(), [](const item_t& item) {
572 State* st = reinterpret_cast<State*>(item.user_data); 606 State* st = reinterpret_cast<State*>(item.user_data);
573 return st->noChainBlockStack.empty() || !st->noChainBlockStack.top(); 607 return st->noChainBlockStack.empty() || !st->noChainBlockStack.back();
574 }) >> +space_break >> advance_match >> ensure( 608 }) >> +space_break >> advance_match >> ensure(
575 chain_line >> *(+space_break >> chain_line), pop_indent); 609 chain_line >> *(+space_break >> chain_line), pop_indent);
576 ChainValue = 610 ChainValue =
@@ -607,7 +641,15 @@ YueParser::YueParser() {
607 DoubleStringInner = +(not_("#{") >> double_string_plain); 641 DoubleStringInner = +(not_("#{") >> double_string_plain);
608 DoubleStringContent = DoubleStringInner | interp; 642 DoubleStringContent = DoubleStringInner | interp;
609 DoubleString = '"' >> Seperator >> *DoubleStringContent >> '"'; 643 DoubleString = '"' >> Seperator >> *DoubleStringContent >> '"';
610 String = DoubleString | SingleString | LuaString; 644
645 YAMLIndent = +set(" \t");
646 YAMLLineInner = +('\\' >> set("\"\\#") | not_("#{" | stop) >> any_char);
647 YAMLLineContent = YAMLLineInner | interp;
648 YAMLLine = check_indent_match >> YAMLIndent >> +(YAMLLineContent) |
649 advance_match >> YAMLIndent >> ensure(+YAMLLineContent, pop_indent);
650 YAMLMultiline = '|' >> space >> Seperator >> +(*set(" \t") >> line_break) >> advance_match >> ensure(YAMLLine >> *(+(*set(" \t") >> line_break) >> YAMLLine), pop_indent);
651
652 String = DoubleString | SingleString | LuaString | YAMLMultiline;
611 653
612 lua_string_open = '[' >> *expr('=') >> '['; 654 lua_string_open = '[' >> *expr('=') >> '[';
613 lua_string_close = ']' >> *expr('=') >> ']'; 655 lua_string_close = ']' >> *expr('=') >> ']';
@@ -635,7 +677,7 @@ YueParser::YueParser() {
635 fn_args_value_list = Exp >> *(space >> ',' >> space >> Exp); 677 fn_args_value_list = Exp >> *(space >> ',' >> space >> Exp);
636 678
637 fn_args_lit_line = ( 679 fn_args_lit_line = (
638 push_indent_match >> (space >> fn_args_value_list >> pop_indent | pop_indent) 680 push_indent_match >> ensure(space >> fn_args_value_list, pop_indent)
639 ) | ( 681 ) | (
640 space 682 space
641 ); 683 );
@@ -677,7 +719,8 @@ YueParser::YueParser() {
677 chain_with_colon = +chain_item >> -colon_chain; 719 chain_with_colon = +chain_item >> -colon_chain;
678 chain_items = chain_with_colon | colon_chain; 720 chain_items = chain_with_colon | colon_chain;
679 721
680 index = '[' >> not_('[') >> space >> Exp >> space >> ']'; 722 index = '[' >> not_('[') >> space >> (ReversedIndex >> and_(space >> ']') | Exp) >> space >> ']';
723 ReversedIndex = '#' >> space >> -('-' >> space >> Exp);
681 chain_item = 724 chain_item =
682 Invoke >> -ExistentialOp | 725 Invoke >> -ExistentialOp |
683 DotChainItem >> -ExistentialOp | 726 DotChainItem >> -ExistentialOp |
@@ -734,7 +777,7 @@ YueParser::YueParser() {
734 777
735 table_block_inner = Seperator >> key_value_line >> *(+space_break >> key_value_line); 778 table_block_inner = Seperator >> key_value_line >> *(+space_break >> key_value_line);
736 TableBlock = +space_break >> advance_match >> ensure(table_block_inner, pop_indent); 779 TableBlock = +space_break >> advance_match >> ensure(table_block_inner, pop_indent);
737 TableBlockIndent = '*' >> Seperator >> disable_arg_table_block_rule( 780 TableBlockIndent = ('*' | '-' >> space_one) >> Seperator >> disable_arg_table_block_rule(
738 space >> key_value_list >> -(space >> ',') >> 781 space >> key_value_list >> -(space >> ',') >>
739 -(+space_break >> advance_match >> space >> ensure(key_value_list >> -(space >> ',') >> *(+space_break >> key_value_line), pop_indent))); 782 -(+space_break >> advance_match >> space >> ensure(key_value_list >> -(space >> ',') >> *(+space_break >> key_value_line), pop_indent)));
740 783
@@ -755,7 +798,7 @@ YueParser::YueParser() {
755 798
756 GlobalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow)); 799 GlobalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow));
757 GlobalOp = expr('*') | '^'; 800 GlobalOp = expr('*') | '^';
758 Global = key("global") >> space >> (ClassDecl | GlobalOp | GlobalValues); 801 Global = key("global") >> space >> (-(ConstAttrib >> space) >> ClassDecl | GlobalOp | -(ConstAttrib >> space) >> GlobalValues);
759 802
760 ExportDefault = key("default"); 803 ExportDefault = key("default");
761 804
@@ -837,24 +880,24 @@ YueParser::YueParser() {
837 key_value_line = check_indent_match >> space >> ( 880 key_value_line = check_indent_match >> space >> (
838 key_value_list >> -(space >> ',') | 881 key_value_list >> -(space >> ',') |
839 TableBlockIndent | 882 TableBlockIndent |
840 '*' >> space >> (SpreadExp | Exp | TableBlock) 883 ('*' | '-' >> space_one) >> space >> (SpreadExp | Exp | TableBlock)
841 ); 884 );
842 885
843 fn_arg_def_list = FnArgDef >> *(space >> ',' >> space >> FnArgDef); 886 fn_arg_def_list = FnArgDef >> *(space >> ',' >> space >> FnArgDef);
844 887
845 fn_arg_def_lit_line = ( 888 fn_arg_def_lit_line = (
846 push_indent_match >> (space >> fn_arg_def_list >> pop_indent | pop_indent) 889 push_indent_match >> ensure(space >> fn_arg_def_list, pop_indent)
847 ) | ( 890 ) | (
848 space 891 space
849 ); 892 );
850 893
851 fn_arg_def_lit_lines = fn_arg_def_lit_line >> *(-(space >> ',') >> space_break >> fn_arg_def_lit_line); 894 fn_arg_def_lit_lines = fn_arg_def_lit_line >> *(-(space >> ',') >> space_break >> fn_arg_def_lit_line);
852 895
853 FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '=' >> space >> Exp); 896 FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '`' >> space >> Name) >> -(space >> '=' >> space >> Exp);
854 897
855 FnArgDefList = Seperator >> ( 898 FnArgDefList = Seperator >> (
856 fn_arg_def_lit_lines >> -(-(space >> ',') >> white >> VarArg) | 899 fn_arg_def_lit_lines >> -(-(space >> ',') >> white >> VarArg >> -(space >> '`' >> space >> Name)) |
857 white >> VarArg 900 white >> VarArg >> -(space >> '`' >> space >> Name)
858 ); 901 );
859 902
860 OuterVarShadow = key("using") >> space >> (NameList | key("nil")); 903 OuterVarShadow = key("using") >> space >> (NameList | key("nil"));
@@ -883,6 +926,7 @@ YueParser::YueParser() {
883 926
884 FnArrowBack = '<' >> set("-="); 927 FnArrowBack = '<' >> set("-=");
885 Backcall = -(FnArgsDef >> space) >> FnArrowBack >> space >> ChainValue; 928 Backcall = -(FnArgsDef >> space) >> FnArrowBack >> space >> ChainValue;
929 SubBackcall = FnArrowBack >> space >> ChainValue;
886 930
887 PipeBody = Seperator >> 931 PipeBody = Seperator >>
888 pipe_operator >> space >> UnaryExp >> 932 pipe_operator >> space >> UnaryExp >>
@@ -896,7 +940,7 @@ YueParser::YueParser() {
896 940
897 arg_table_block = pl::user(true_(), [](const item_t& item) { 941 arg_table_block = pl::user(true_(), [](const item_t& item) {
898 State* st = reinterpret_cast<State*>(item.user_data); 942 State* st = reinterpret_cast<State*>(item.user_data);
899 return st->noTableBlockStack.empty() || !st->noTableBlockStack.top(); 943 return st->noTableBlockStack.empty() || !st->noTableBlockStack.back();
900 }) >> TableBlock; 944 }) >> TableBlock;
901 945
902 invoke_args_with_table = 946 invoke_args_with_table =
@@ -936,11 +980,11 @@ YueParser::YueParser() {
936 980
937 SimpleValue = 981 SimpleValue =
938 TableLit | ConstValue | If | Switch | Try | With | 982 TableLit | ConstValue | If | Switch | Try | With |
939 ClassDecl | ForEach | For | While | Do | 983 ClassDecl | ForEach | For | While | Repeat | Do |
940 UnaryValue | TblComprehension | Comprehension | 984 UnaryValue | TblComprehension | Comprehension |
941 FunLit | Num | VarArg; 985 FunLit | Num | VarArg;
942 986
943 ExpListAssign = ExpList >> -(space >> (Update | Assign)) >> not_(space >> '='); 987 ExpListAssign = ExpList >> -(space >> (Update | Assign | SubBackcall)) >> not_(space >> '=');
944 988
945 IfLine = IfType >> space >> IfCond; 989 IfLine = IfType >> space >> IfCond;
946 WhileLine = WhileType >> space >> Exp; 990 WhileLine = WhileType >> space >> Exp;
@@ -997,11 +1041,16 @@ YueParser::YueParser() {
997 empty_line_break | 1041 empty_line_break |
998 advance_match >> ensure(space >> (indentation_error | Statement), pop_indent) 1042 advance_match >> ensure(space >> (indentation_error | Statement), pop_indent)
999 ); 1043 );
1000 Block = Seperator >> line >> *(+line_break >> line); 1044 Block = Seperator >> (pl::user(true_(), [](const item_t& item) {
1045 State* st = reinterpret_cast<State*>(item.user_data);
1046 return st->lax;
1047 }) >> lax_line >> *(+line_break >> lax_line) | line >> *(+line_break >> line));
1001 1048
1002 shebang = "#!" >> *(not_(stop) >> any_char); 1049 shebang = "#!" >> *(not_(stop) >> any_char);
1003 BlockEnd = Block >> white >> stop; 1050 BlockEnd = Block >> white >> stop;
1004 File = -shebang >> -Block >> white >> stop; 1051 File = -shebang >> -Block >> white >> stop;
1052
1053 lax_line = advance_match >> ensure(*(not_(stop) >> any()), pop_indent) | line >> and_(stop) | check_indent_match >> *(not_(stop) >> any());
1005} 1054}
1006// clang-format on 1055// clang-format on
1007 1056
@@ -1031,7 +1080,7 @@ bool YueParser::startWith(std::string_view codes, rule& r) {
1031 return true; 1080 return true;
1032} 1081}
1033 1082
1034ParseInfo YueParser::parse(std::string_view codes, rule& r) { 1083ParseInfo YueParser::parse(std::string_view codes, rule& r, bool lax) {
1035 ParseInfo res; 1084 ParseInfo res;
1036 if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) { 1085 if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) {
1037 codes = codes.substr(3); 1086 codes = codes.substr(3);
@@ -1049,6 +1098,7 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) {
1049 error_list errors; 1098 error_list errors;
1050 try { 1099 try {
1051 State state; 1100 State state;
1101 state.lax = lax;
1052 res.node.set(::yue::parse(*(res.codes), r, errors, &state)); 1102 res.node.set(::yue::parse(*(res.codes), r, errors, &state));
1053 if (state.exportCount > 0) { 1103 if (state.exportCount > 0) {
1054 int index = 0; 1104 int index = 0;
@@ -1086,19 +1136,21 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) {
1086 return res; 1136 return res;
1087} 1137}
1088 1138
1089ParseInfo YueParser::parse(std::string_view astName, std::string_view codes) { 1139ParseInfo YueParser::parse(std::string_view astName, std::string_view codes, bool lax) {
1090 auto it = _rules.find(astName); 1140 auto it = _rules.find(astName);
1091 if (it != _rules.end()) { 1141 if (it != _rules.end()) {
1092 return parse(codes, *it->second); 1142 return parse(codes, *it->second, lax);
1093 } 1143 }
1094 return {}; 1144 ParseInfo info{};
1145 info.error = ParseInfo::Error{"invalid rule: "s + std::string{astName}, 1, 1};
1146 return info;
1095} 1147}
1096 1148
1097bool YueParser::match(std::string_view astName, std::string_view codes) { 1149bool YueParser::match(std::string_view astName, std::string_view codes) {
1098 auto it = _rules.find(astName); 1150 auto it = _rules.find(astName);
1099 if (it != _rules.end()) { 1151 if (it != _rules.end()) {
1100 auto rEnd = rule(*it->second >> eof()); 1152 auto rEnd = rule(*it->second >> eof());
1101 return parse(codes, rEnd).node; 1153 return parse(codes, rEnd, false).node;
1102 } 1154 }
1103 return false; 1155 return false;
1104} 1156}
@@ -1134,6 +1186,24 @@ void trim(std::string& str) {
1134 str.erase(0, str.find_first_not_of(" \t\r\n")); 1186 str.erase(0, str.find_first_not_of(" \t\r\n"));
1135 str.erase(str.find_last_not_of(" \t\r\n") + 1); 1187 str.erase(str.find_last_not_of(" \t\r\n") + 1);
1136} 1188}
1189
1190std::string toLuaDoubleString(const std::string& input) {
1191 std::string luaStr = "\"";
1192 for (char c : input) {
1193 switch (c) {
1194 case '\"': luaStr += "\\\""; break;
1195 case '\\': luaStr += "\\\\"; break;
1196 case '\n': luaStr += "\\n"; break;
1197 case '\r': luaStr += "\\r"; break;
1198 case '\t': luaStr += "\\t"; break;
1199 default:
1200 luaStr += c;
1201 break;
1202 }
1203 }
1204 luaStr += "\"";
1205 return luaStr;
1206}
1137} // namespace Utils 1207} // namespace Utils
1138 1208
1139std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { 1209std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const {