diff options
Diffstat (limited to 'src/yuescript/yue_parser.cpp')
-rw-r--r-- | src/yuescript/yue_parser.cpp | 162 |
1 files changed, 114 insertions, 48 deletions
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 77c5901..1942e23 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
@@ -118,8 +118,8 @@ YueParser::YueParser() { | |||
118 | return false; | 118 | return false; |
119 | }); | 119 | }); |
120 | 120 | ||
121 | if_assignment_syntax_error = pl::user(true_(), [](const item_t& item) { | 121 | assignment_expression_syntax_error = pl::user(true_(), [](const item_t& item) { |
122 | throw ParserError("use := for if-assignment expression"sv, item.begin); | 122 | throw ParserError("use := for assignment expression"sv, item.begin); |
123 | return false; | 123 | return false; |
124 | }); | 124 | }); |
125 | 125 | ||
@@ -162,6 +162,13 @@ YueParser::YueParser() { | |||
162 | ) \ | 162 | ) \ |
163 | ) | 163 | ) |
164 | 164 | ||
165 | #define disable_until_rule(patt) ( \ | ||
166 | disable_until >> ( \ | ||
167 | (patt) >> enable_until | \ | ||
168 | enable_until >> cut \ | ||
169 | ) \ | ||
170 | ) | ||
171 | |||
165 | #define body_with(str) ( \ | 172 | #define body_with(str) ( \ |
166 | key(str) >> space >> (in_block | Statement) | \ | 173 | key(str) >> space >> (in_block | Statement) | \ |
167 | in_block | \ | 174 | in_block | \ |
@@ -325,7 +332,7 @@ YueParser::YueParser() { | |||
325 | Exp; | 332 | Exp; |
326 | import_tab_list = import_tab_item >> *(space >> ',' >> space >> import_tab_item); | 333 | import_tab_list = import_tab_item >> *(space >> ',' >> space >> import_tab_item); |
327 | import_tab_line = ( | 334 | import_tab_line = ( |
328 | push_indent_match >> (space >> import_tab_list >> pop_indent | pop_indent) | 335 | push_indent_match >> ensure(space >> import_tab_list, pop_indent) |
329 | ) | space; | 336 | ) | space; |
330 | 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 >> ','); |
331 | import_tab_key_value = key_value | ':' >> MacroName | MacroNamePair | ImportAllMacro; | 338 | import_tab_key_value = key_value | ':' >> MacroName | MacroNamePair | ImportAllMacro; |
@@ -342,7 +349,9 @@ YueParser::YueParser() { | |||
342 | 349 | ||
343 | ImportAs = ImportLiteral >> -(space >> key("as") >> space >> (ImportTabLit | Variable | ImportAllMacro)); | 350 | ImportAs = ImportLiteral >> -(space >> key("as") >> space >> (ImportTabLit | Variable | ImportAllMacro)); |
344 | 351 | ||
345 | 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; | ||
346 | 355 | ||
347 | Label = "::" >> LabelName >> "::"; | 356 | Label = "::" >> LabelName >> "::"; |
348 | 357 | ||
@@ -350,11 +359,13 @@ YueParser::YueParser() { | |||
350 | 359 | ||
351 | ShortTabAppending = "[]" >> space >> Assign; | 360 | ShortTabAppending = "[]" >> space >> Assign; |
352 | 361 | ||
353 | BreakLoop = (expr("break") | "continue") >> not_alpha_num; | 362 | Break = key("break"); |
363 | Continue = key("continue"); | ||
364 | BreakLoop = (Break >> -(space >> Exp) | Continue) >> not_alpha_num; | ||
354 | 365 | ||
355 | Return = key("return") >> -(space >> (TableBlock | ExpListLow)); | 366 | Return = key("return") >> -(space >> (TableBlock | ExpListLow)); |
356 | 367 | ||
357 | with_exp = ExpList >> -(space >> Assign); | 368 | with_exp = ExpList >> -(space >> (':' >> Assign | and_('=') >> assignment_expression_syntax_error)); |
358 | 369 | ||
359 | 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"); |
360 | 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"); |
@@ -370,7 +381,8 @@ YueParser::YueParser() { | |||
370 | and_(SimpleTable | TableLit) >> Exp | | 381 | and_(SimpleTable | TableLit) >> Exp | |
371 | exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) | 382 | exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) |
372 | ); | 383 | ); |
373 | Switch = key("switch") >> space >> Exp >> | 384 | Switch = key("switch") >> space >> |
385 | Exp >> -(space >> Assignment) >> | ||
374 | space >> Seperator >> ( | 386 | space >> Seperator >> ( |
375 | SwitchCase >> space >> ( | 387 | SwitchCase >> space >> ( |
376 | switch_block | | 388 | switch_block | |
@@ -379,20 +391,26 @@ YueParser::YueParser() { | |||
379 | +space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent | 391 | +space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent |
380 | ); | 392 | ); |
381 | 393 | ||
382 | Assignment = -(',' >> space >> ExpList >> space) >> (':' >> Assign | and_('=') >> if_assignment_syntax_error); | 394 | Assignment = -(',' >> space >> ExpList >> space) >> (':' >> Assign | and_('=') >> assignment_expression_syntax_error); |
383 | 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))); |
384 | 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"); |
385 | 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; |
386 | IfType = (expr("if") | "unless") >> not_alpha_num; | 398 | IfType = (expr("if") | "unless") >> not_alpha_num; |
387 | 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; |
388 | 400 | ||
389 | WhileType = (expr("while") | "until") >> not_alpha_num; | 401 | WhileType = (expr("while") | pl::user("until", [](const item_t& item) { |
390 | 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); |
391 | 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; | ||
392 | 410 | ||
393 | for_key = pl::user(key("for"), [](const item_t& item) { | 411 | for_key = pl::user(key("for"), [](const item_t& item) { |
394 | State* st = reinterpret_cast<State*>(item.user_data); | 412 | State* st = reinterpret_cast<State*>(item.user_data); |
395 | return st->noForStack.empty() || !st->noForStack.top(); | 413 | return st->noForStack.empty() || !st->noForStack.back(); |
396 | }); | 414 | }); |
397 | ForStepValue = ',' >> space >> Exp; | 415 | ForStepValue = ',' >> space >> Exp; |
398 | for_args = Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> space >> -ForStepValue; | 416 | for_args = Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> space >> -ForStepValue; |
@@ -406,18 +424,18 @@ YueParser::YueParser() { | |||
406 | 424 | ||
407 | Do = pl::user(key("do"), [](const item_t& item) { | 425 | Do = pl::user(key("do"), [](const item_t& item) { |
408 | State* st = reinterpret_cast<State*>(item.user_data); | 426 | State* st = reinterpret_cast<State*>(item.user_data); |
409 | return st->noDoStack.empty() || !st->noDoStack.top(); | 427 | return st->noDoStack.empty() || !st->noDoStack.back(); |
410 | }) >> space >> Body; | 428 | }) >> space >> Body; |
411 | 429 | ||
412 | disable_do = pl::user(true_(), [](const item_t& item) { | 430 | disable_do = pl::user(true_(), [](const item_t& item) { |
413 | State* st = reinterpret_cast<State*>(item.user_data); | 431 | State* st = reinterpret_cast<State*>(item.user_data); |
414 | st->noDoStack.push(true); | 432 | st->noDoStack.push_back(true); |
415 | return true; | 433 | return true; |
416 | }); | 434 | }); |
417 | 435 | ||
418 | enable_do = pl::user(true_(), [](const item_t& item) { | 436 | enable_do = pl::user(true_(), [](const item_t& item) { |
419 | State* st = reinterpret_cast<State*>(item.user_data); | 437 | State* st = reinterpret_cast<State*>(item.user_data); |
420 | st->noDoStack.pop(); | 438 | st->noDoStack.pop_back(); |
421 | return true; | 439 | return true; |
422 | }); | 440 | }); |
423 | 441 | ||
@@ -435,46 +453,58 @@ YueParser::YueParser() { | |||
435 | 453 | ||
436 | 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) { |
437 | State* st = reinterpret_cast<State*>(item.user_data); | 455 | State* st = reinterpret_cast<State*>(item.user_data); |
438 | st->noDoStack.push(true); | 456 | st->noDoStack.push_back(true); |
439 | st->noChainBlockStack.push(true); | 457 | st->noChainBlockStack.push_back(true); |
440 | st->noTableBlockStack.push(true); | 458 | st->noTableBlockStack.push_back(true); |
441 | return true; | 459 | return true; |
442 | }); | 460 | }); |
443 | 461 | ||
444 | 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) { |
445 | State* st = reinterpret_cast<State*>(item.user_data); | 463 | State* st = reinterpret_cast<State*>(item.user_data); |
446 | st->noDoStack.pop(); | 464 | st->noDoStack.pop_back(); |
447 | st->noChainBlockStack.pop(); | 465 | st->noChainBlockStack.pop_back(); |
448 | st->noTableBlockStack.pop(); | 466 | st->noTableBlockStack.pop_back(); |
449 | return true; | 467 | return true; |
450 | }); | 468 | }); |
451 | 469 | ||
452 | disable_arg_table_block = pl::user(true_(), [](const item_t& item) { | 470 | disable_arg_table_block = pl::user(true_(), [](const item_t& item) { |
453 | State* st = reinterpret_cast<State*>(item.user_data); | 471 | State* st = reinterpret_cast<State*>(item.user_data); |
454 | st->noTableBlockStack.push(true); | 472 | st->noTableBlockStack.push_back(true); |
455 | return true; | 473 | return true; |
456 | }); | 474 | }); |
457 | 475 | ||
458 | enable_arg_table_block = pl::user(true_(), [](const item_t& item) { | 476 | enable_arg_table_block = pl::user(true_(), [](const item_t& item) { |
459 | State* st = reinterpret_cast<State*>(item.user_data); | 477 | State* st = reinterpret_cast<State*>(item.user_data); |
460 | st->noTableBlockStack.pop(); | 478 | st->noTableBlockStack.pop_back(); |
461 | return true; | 479 | return true; |
462 | }); | 480 | }); |
463 | 481 | ||
464 | disable_for = pl::user(true_(), [](const item_t& item) { | 482 | disable_for = pl::user(true_(), [](const item_t& item) { |
465 | State* st = reinterpret_cast<State*>(item.user_data); | 483 | State* st = reinterpret_cast<State*>(item.user_data); |
466 | st->noForStack.push(true); | 484 | st->noForStack.push_back(true); |
467 | return true; | 485 | return true; |
468 | }); | 486 | }); |
469 | 487 | ||
470 | enable_for = pl::user(true_(), [](const item_t& item) { | 488 | enable_for = pl::user(true_(), [](const item_t& item) { |
471 | State* st = reinterpret_cast<State*>(item.user_data); | 489 | State* st = reinterpret_cast<State*>(item.user_data); |
472 | 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(); | ||
473 | return true; | 503 | return true; |
474 | }); | 504 | }); |
475 | 505 | ||
476 | 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; |
477 | Try = key("try") >> space >> (in_block | Exp) >> -CatchBlock; | 507 | Try = key("try") >> -ExistentialOp >> space >> (in_block | Exp) >> -CatchBlock; |
478 | 508 | ||
479 | list_value = | 509 | list_value = |
480 | and_( | 510 | and_( |
@@ -561,20 +591,20 @@ YueParser::YueParser() { | |||
561 | 591 | ||
562 | disable_chain = pl::user(true_(), [](const item_t& item) { | 592 | disable_chain = pl::user(true_(), [](const item_t& item) { |
563 | State* st = reinterpret_cast<State*>(item.user_data); | 593 | State* st = reinterpret_cast<State*>(item.user_data); |
564 | st->noChainBlockStack.push(true); | 594 | st->noChainBlockStack.push_back(true); |
565 | return true; | 595 | return true; |
566 | }); | 596 | }); |
567 | 597 | ||
568 | enable_chain = pl::user(true_(), [](const item_t& item) { | 598 | enable_chain = pl::user(true_(), [](const item_t& item) { |
569 | State* st = reinterpret_cast<State*>(item.user_data); | 599 | State* st = reinterpret_cast<State*>(item.user_data); |
570 | st->noChainBlockStack.pop(); | 600 | st->noChainBlockStack.pop_back(); |
571 | return true; | 601 | return true; |
572 | }); | 602 | }); |
573 | 603 | ||
574 | 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; |
575 | chain_block = pl::user(true_(), [](const item_t& item) { | 605 | chain_block = pl::user(true_(), [](const item_t& item) { |
576 | State* st = reinterpret_cast<State*>(item.user_data); | 606 | State* st = reinterpret_cast<State*>(item.user_data); |
577 | return st->noChainBlockStack.empty() || !st->noChainBlockStack.top(); | 607 | return st->noChainBlockStack.empty() || !st->noChainBlockStack.back(); |
578 | }) >> +space_break >> advance_match >> ensure( | 608 | }) >> +space_break >> advance_match >> ensure( |
579 | chain_line >> *(+space_break >> chain_line), pop_indent); | 609 | chain_line >> *(+space_break >> chain_line), pop_indent); |
580 | ChainValue = | 610 | ChainValue = |
@@ -611,7 +641,15 @@ YueParser::YueParser() { | |||
611 | DoubleStringInner = +(not_("#{") >> double_string_plain); | 641 | DoubleStringInner = +(not_("#{") >> double_string_plain); |
612 | DoubleStringContent = DoubleStringInner | interp; | 642 | DoubleStringContent = DoubleStringInner | interp; |
613 | DoubleString = '"' >> Seperator >> *DoubleStringContent >> '"'; | 643 | DoubleString = '"' >> Seperator >> *DoubleStringContent >> '"'; |
614 | 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; | ||
615 | 653 | ||
616 | lua_string_open = '[' >> *expr('=') >> '['; | 654 | lua_string_open = '[' >> *expr('=') >> '['; |
617 | lua_string_close = ']' >> *expr('=') >> ']'; | 655 | lua_string_close = ']' >> *expr('=') >> ']'; |
@@ -639,7 +677,7 @@ YueParser::YueParser() { | |||
639 | fn_args_value_list = Exp >> *(space >> ',' >> space >> Exp); | 677 | fn_args_value_list = Exp >> *(space >> ',' >> space >> Exp); |
640 | 678 | ||
641 | fn_args_lit_line = ( | 679 | fn_args_lit_line = ( |
642 | push_indent_match >> (space >> fn_args_value_list >> pop_indent | pop_indent) | 680 | push_indent_match >> ensure(space >> fn_args_value_list, pop_indent) |
643 | ) | ( | 681 | ) | ( |
644 | space | 682 | space |
645 | ); | 683 | ); |
@@ -681,7 +719,8 @@ YueParser::YueParser() { | |||
681 | chain_with_colon = +chain_item >> -colon_chain; | 719 | chain_with_colon = +chain_item >> -colon_chain; |
682 | chain_items = chain_with_colon | colon_chain; | 720 | chain_items = chain_with_colon | colon_chain; |
683 | 721 | ||
684 | index = '[' >> not_('[') >> space >> Exp >> space >> ']'; | 722 | index = '[' >> not_('[') >> space >> (ReversedIndex >> and_(space >> ']') | Exp) >> space >> ']'; |
723 | ReversedIndex = '#' >> space >> -('-' >> space >> Exp); | ||
685 | chain_item = | 724 | chain_item = |
686 | Invoke >> -ExistentialOp | | 725 | Invoke >> -ExistentialOp | |
687 | DotChainItem >> -ExistentialOp | | 726 | DotChainItem >> -ExistentialOp | |
@@ -738,7 +777,7 @@ YueParser::YueParser() { | |||
738 | 777 | ||
739 | 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); |
740 | TableBlock = +space_break >> advance_match >> ensure(table_block_inner, pop_indent); | 779 | TableBlock = +space_break >> advance_match >> ensure(table_block_inner, pop_indent); |
741 | TableBlockIndent = '*' >> Seperator >> disable_arg_table_block_rule( | 780 | TableBlockIndent = ('*' | '-' >> space_one) >> Seperator >> disable_arg_table_block_rule( |
742 | space >> key_value_list >> -(space >> ',') >> | 781 | space >> key_value_list >> -(space >> ',') >> |
743 | -(+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))); |
744 | 783 | ||
@@ -759,7 +798,7 @@ YueParser::YueParser() { | |||
759 | 798 | ||
760 | GlobalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow)); | 799 | GlobalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow)); |
761 | GlobalOp = expr('*') | '^'; | 800 | GlobalOp = expr('*') | '^'; |
762 | Global = key("global") >> space >> (ClassDecl | GlobalOp | GlobalValues); | 801 | Global = key("global") >> space >> (-(ConstAttrib >> space) >> ClassDecl | GlobalOp | -(ConstAttrib >> space) >> GlobalValues); |
763 | 802 | ||
764 | ExportDefault = key("default"); | 803 | ExportDefault = key("default"); |
765 | 804 | ||
@@ -841,24 +880,24 @@ YueParser::YueParser() { | |||
841 | key_value_line = check_indent_match >> space >> ( | 880 | key_value_line = check_indent_match >> space >> ( |
842 | key_value_list >> -(space >> ',') | | 881 | key_value_list >> -(space >> ',') | |
843 | TableBlockIndent | | 882 | TableBlockIndent | |
844 | '*' >> space >> (SpreadExp | Exp | TableBlock) | 883 | ('*' | '-' >> space_one) >> space >> (SpreadExp | Exp | TableBlock) |
845 | ); | 884 | ); |
846 | 885 | ||
847 | fn_arg_def_list = FnArgDef >> *(space >> ',' >> space >> FnArgDef); | 886 | fn_arg_def_list = FnArgDef >> *(space >> ',' >> space >> FnArgDef); |
848 | 887 | ||
849 | fn_arg_def_lit_line = ( | 888 | fn_arg_def_lit_line = ( |
850 | push_indent_match >> (space >> fn_arg_def_list >> pop_indent | pop_indent) | 889 | push_indent_match >> ensure(space >> fn_arg_def_list, pop_indent) |
851 | ) | ( | 890 | ) | ( |
852 | space | 891 | space |
853 | ); | 892 | ); |
854 | 893 | ||
855 | 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); |
856 | 895 | ||
857 | FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '=' >> space >> Exp); | 896 | FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '`' >> space >> Name) >> -(space >> '=' >> space >> Exp); |
858 | 897 | ||
859 | FnArgDefList = Seperator >> ( | 898 | FnArgDefList = Seperator >> ( |
860 | fn_arg_def_lit_lines >> -(-(space >> ',') >> white >> VarArg) | | 899 | fn_arg_def_lit_lines >> -(-(space >> ',') >> white >> VarArg >> -(space >> '`' >> space >> Name)) | |
861 | white >> VarArg | 900 | white >> VarArg >> -(space >> '`' >> space >> Name) |
862 | ); | 901 | ); |
863 | 902 | ||
864 | OuterVarShadow = key("using") >> space >> (NameList | key("nil")); | 903 | OuterVarShadow = key("using") >> space >> (NameList | key("nil")); |
@@ -887,6 +926,7 @@ YueParser::YueParser() { | |||
887 | 926 | ||
888 | FnArrowBack = '<' >> set("-="); | 927 | FnArrowBack = '<' >> set("-="); |
889 | Backcall = -(FnArgsDef >> space) >> FnArrowBack >> space >> ChainValue; | 928 | Backcall = -(FnArgsDef >> space) >> FnArrowBack >> space >> ChainValue; |
929 | SubBackcall = FnArrowBack >> space >> ChainValue; | ||
890 | 930 | ||
891 | PipeBody = Seperator >> | 931 | PipeBody = Seperator >> |
892 | pipe_operator >> space >> UnaryExp >> | 932 | pipe_operator >> space >> UnaryExp >> |
@@ -900,7 +940,7 @@ YueParser::YueParser() { | |||
900 | 940 | ||
901 | arg_table_block = pl::user(true_(), [](const item_t& item) { | 941 | arg_table_block = pl::user(true_(), [](const item_t& item) { |
902 | State* st = reinterpret_cast<State*>(item.user_data); | 942 | State* st = reinterpret_cast<State*>(item.user_data); |
903 | return st->noTableBlockStack.empty() || !st->noTableBlockStack.top(); | 943 | return st->noTableBlockStack.empty() || !st->noTableBlockStack.back(); |
904 | }) >> TableBlock; | 944 | }) >> TableBlock; |
905 | 945 | ||
906 | invoke_args_with_table = | 946 | invoke_args_with_table = |
@@ -940,11 +980,11 @@ YueParser::YueParser() { | |||
940 | 980 | ||
941 | SimpleValue = | 981 | SimpleValue = |
942 | TableLit | ConstValue | If | Switch | Try | With | | 982 | TableLit | ConstValue | If | Switch | Try | With | |
943 | ClassDecl | ForEach | For | While | Do | | 983 | ClassDecl | ForEach | For | While | Repeat | Do | |
944 | UnaryValue | TblComprehension | Comprehension | | 984 | UnaryValue | TblComprehension | Comprehension | |
945 | FunLit | Num | VarArg; | 985 | FunLit | Num | VarArg; |
946 | 986 | ||
947 | ExpListAssign = ExpList >> -(space >> (Update | Assign)) >> not_(space >> '='); | 987 | ExpListAssign = ExpList >> -(space >> (Update | Assign | SubBackcall)) >> not_(space >> '='); |
948 | 988 | ||
949 | IfLine = IfType >> space >> IfCond; | 989 | IfLine = IfType >> space >> IfCond; |
950 | WhileLine = WhileType >> space >> Exp; | 990 | WhileLine = WhileType >> space >> Exp; |
@@ -1001,11 +1041,16 @@ YueParser::YueParser() { | |||
1001 | empty_line_break | | 1041 | empty_line_break | |
1002 | advance_match >> ensure(space >> (indentation_error | Statement), pop_indent) | 1042 | advance_match >> ensure(space >> (indentation_error | Statement), pop_indent) |
1003 | ); | 1043 | ); |
1004 | 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)); | ||
1005 | 1048 | ||
1006 | shebang = "#!" >> *(not_(stop) >> any_char); | 1049 | shebang = "#!" >> *(not_(stop) >> any_char); |
1007 | BlockEnd = Block >> white >> stop; | 1050 | BlockEnd = Block >> white >> stop; |
1008 | 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()); | ||
1009 | } | 1054 | } |
1010 | // clang-format on | 1055 | // clang-format on |
1011 | 1056 | ||
@@ -1035,7 +1080,7 @@ bool YueParser::startWith(std::string_view codes, rule& r) { | |||
1035 | return true; | 1080 | return true; |
1036 | } | 1081 | } |
1037 | 1082 | ||
1038 | ParseInfo YueParser::parse(std::string_view codes, rule& r) { | 1083 | ParseInfo YueParser::parse(std::string_view codes, rule& r, bool lax) { |
1039 | ParseInfo res; | 1084 | ParseInfo res; |
1040 | if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) { | 1085 | if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) { |
1041 | codes = codes.substr(3); | 1086 | codes = codes.substr(3); |
@@ -1053,6 +1098,7 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) { | |||
1053 | error_list errors; | 1098 | error_list errors; |
1054 | try { | 1099 | try { |
1055 | State state; | 1100 | State state; |
1101 | state.lax = lax; | ||
1056 | res.node.set(::yue::parse(*(res.codes), r, errors, &state)); | 1102 | res.node.set(::yue::parse(*(res.codes), r, errors, &state)); |
1057 | if (state.exportCount > 0) { | 1103 | if (state.exportCount > 0) { |
1058 | int index = 0; | 1104 | int index = 0; |
@@ -1090,19 +1136,21 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) { | |||
1090 | return res; | 1136 | return res; |
1091 | } | 1137 | } |
1092 | 1138 | ||
1093 | ParseInfo YueParser::parse(std::string_view astName, std::string_view codes) { | 1139 | ParseInfo YueParser::parse(std::string_view astName, std::string_view codes, bool lax) { |
1094 | auto it = _rules.find(astName); | 1140 | auto it = _rules.find(astName); |
1095 | if (it != _rules.end()) { | 1141 | if (it != _rules.end()) { |
1096 | return parse(codes, *it->second); | 1142 | return parse(codes, *it->second, lax); |
1097 | } | 1143 | } |
1098 | return {}; | 1144 | ParseInfo info{}; |
1145 | info.error = ParseInfo::Error{"invalid rule: "s + std::string{astName}, 1, 1}; | ||
1146 | return info; | ||
1099 | } | 1147 | } |
1100 | 1148 | ||
1101 | bool YueParser::match(std::string_view astName, std::string_view codes) { | 1149 | bool YueParser::match(std::string_view astName, std::string_view codes) { |
1102 | auto it = _rules.find(astName); | 1150 | auto it = _rules.find(astName); |
1103 | if (it != _rules.end()) { | 1151 | if (it != _rules.end()) { |
1104 | auto rEnd = rule(*it->second >> eof()); | 1152 | auto rEnd = rule(*it->second >> eof()); |
1105 | return parse(codes, rEnd).node; | 1153 | return parse(codes, rEnd, false).node; |
1106 | } | 1154 | } |
1107 | return false; | 1155 | return false; |
1108 | } | 1156 | } |
@@ -1138,6 +1186,24 @@ void trim(std::string& str) { | |||
1138 | str.erase(0, str.find_first_not_of(" \t\r\n")); | 1186 | str.erase(0, str.find_first_not_of(" \t\r\n")); |
1139 | str.erase(str.find_last_not_of(" \t\r\n") + 1); | 1187 | str.erase(str.find_last_not_of(" \t\r\n") + 1); |
1140 | } | 1188 | } |
1189 | |||
1190 | std::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 | } | ||
1141 | } // namespace Utils | 1207 | } // namespace Utils |
1142 | 1208 | ||
1143 | std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { | 1209 | std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { |