diff options
author | Li Jin <dragon-fly@qq.com> | 2023-01-16 17:28:26 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2023-01-16 18:06:38 +0800 |
commit | 0dfff530f1b0be147e5cf44b9e3786a3f5b35a27 (patch) | |
tree | 119a4044c4e74be4e87e7ccde33226e85ca70739 | |
parent | c1cc934e55ca88117599121841301783d29aac32 (diff) | |
download | yuescript-0dfff530f1b0be147e5cf44b9e3786a3f5b35a27.tar.gz yuescript-0dfff530f1b0be147e5cf44b9e3786a3f5b35a27.tar.bz2 yuescript-0dfff530f1b0be147e5cf44b9e3786a3f5b35a27.zip |
fix more cases from issue #120 and reduce some parsing call stacks.
-rw-r--r-- | src/yuescript/parser.cpp | 95 | ||||
-rw-r--r-- | src/yuescript/parser.hpp | 12 | ||||
-rw-r--r-- | src/yuescript/yue_ast.h | 5 | ||||
-rw-r--r-- | src/yuescript/yue_compiler.cpp | 2 | ||||
-rw-r--r-- | src/yuescript/yue_parser.cpp | 396 | ||||
-rw-r--r-- | src/yuescript/yue_parser.h | 2 |
6 files changed, 352 insertions, 160 deletions
diff --git a/src/yuescript/parser.cpp b/src/yuescript/parser.cpp index 5939793..be38e83 100644 --- a/src/yuescript/parser.cpp +++ b/src/yuescript/parser.cpp | |||
@@ -608,7 +608,8 @@ public: | |||
608 | 608 | ||
609 | protected: | 609 | protected: |
610 | // left and right expressions | 610 | // left and right expressions |
611 | _expr *m_left, *m_right; | 611 | _expr* m_left; |
612 | _expr* m_right; | ||
612 | }; | 613 | }; |
613 | 614 | ||
614 | // sequence | 615 | // sequence |
@@ -632,6 +633,42 @@ public: | |||
632 | } | 633 | } |
633 | }; | 634 | }; |
634 | 635 | ||
636 | // sequence list | ||
637 | class _seq_list : public _expr { | ||
638 | public: | ||
639 | // constructor. | ||
640 | _seq_list(std::initializer_list<expr> list) { | ||
641 | m_list.reserve(list.size()); | ||
642 | for (const expr& expr : list) { | ||
643 | m_list.push_back(_private::get_expr(expr)); | ||
644 | } | ||
645 | } | ||
646 | |||
647 | virtual ~_seq_list() { | ||
648 | for (_expr* expr : m_list) { | ||
649 | delete expr; | ||
650 | } | ||
651 | } | ||
652 | |||
653 | // parse with whitespace | ||
654 | virtual bool parse_non_term(_context& con) const { | ||
655 | for (_expr* expr : m_list) { | ||
656 | if (!expr->parse_non_term(con)) return false; | ||
657 | } | ||
658 | return true; | ||
659 | } | ||
660 | |||
661 | // parse terminal | ||
662 | virtual bool parse_term(_context& con) const { | ||
663 | for (_expr* expr : m_list) { | ||
664 | if (!expr->parse_term(con)) return false; | ||
665 | } | ||
666 | return true; | ||
667 | } | ||
668 | private: | ||
669 | std::vector<_expr*> m_list; | ||
670 | }; | ||
671 | |||
635 | // choice | 672 | // choice |
636 | class _choice : public _binary { | 673 | class _choice : public _binary { |
637 | public: | 674 | public: |
@@ -657,6 +694,46 @@ public: | |||
657 | } | 694 | } |
658 | }; | 695 | }; |
659 | 696 | ||
697 | // select | ||
698 | class _sel : public _expr { | ||
699 | public: | ||
700 | // constructor. | ||
701 | _sel(std::initializer_list<expr> list) { | ||
702 | m_list.reserve(list.size()); | ||
703 | for (const expr& expr : list) { | ||
704 | m_list.push_back(_private::get_expr(expr)); | ||
705 | } | ||
706 | } | ||
707 | |||
708 | virtual ~_sel() { | ||
709 | for (_expr* expr : m_list) { | ||
710 | delete expr; | ||
711 | } | ||
712 | } | ||
713 | |||
714 | // parse with whitespace | ||
715 | virtual bool parse_non_term(_context& con) const { | ||
716 | _state st(con); | ||
717 | for (_expr* expr : m_list) { | ||
718 | if (expr->parse_non_term(con)) return true; | ||
719 | if (expr != m_list.back()) con.restore(st); | ||
720 | } | ||
721 | return false; | ||
722 | } | ||
723 | |||
724 | // parse terminal | ||
725 | virtual bool parse_term(_context& con) const { | ||
726 | _state st(con); | ||
727 | for (_expr* expr : m_list) { | ||
728 | if (expr->parse_term(con)) return true; | ||
729 | if (expr != m_list.back()) con.restore(st); | ||
730 | } | ||
731 | return false; | ||
732 | } | ||
733 | private: | ||
734 | std::vector<_expr*> m_list; | ||
735 | }; | ||
736 | |||
660 | // reference to rule | 737 | // reference to rule |
661 | class _ref : public _expr { | 738 | class _ref : public _expr { |
662 | public: | 739 | public: |
@@ -1186,6 +1263,14 @@ expr operator>>(const expr& left, const expr& right) { | |||
1186 | new _seq(_private::get_expr(left), _private::get_expr(right))); | 1263 | new _seq(_private::get_expr(left), _private::get_expr(right))); |
1187 | } | 1264 | } |
1188 | 1265 | ||
1266 | /** creates a sequence of expressions. | ||
1267 | @param list list of expressions. | ||
1268 | @return an expression which parses a sequence. | ||
1269 | */ | ||
1270 | expr seq(std::initializer_list<expr> list) { | ||
1271 | return _private::construct_expr(new _seq_list(list)); | ||
1272 | } | ||
1273 | |||
1189 | /** creates a choice of expressions. | 1274 | /** creates a choice of expressions. |
1190 | @param left left operand. | 1275 | @param left left operand. |
1191 | @param right right operand. | 1276 | @param right right operand. |
@@ -1196,6 +1281,14 @@ expr operator|(const expr& left, const expr& right) { | |||
1196 | new _choice(_private::get_expr(left), _private::get_expr(right))); | 1281 | new _choice(_private::get_expr(left), _private::get_expr(right))); |
1197 | } | 1282 | } |
1198 | 1283 | ||
1284 | /** creates multiple choices of expressions. | ||
1285 | @param list list of expressions. | ||
1286 | @return an expression which parses multiple choices. | ||
1287 | */ | ||
1288 | expr sel(std::initializer_list<expr> list) { | ||
1289 | return _private::construct_expr(new _sel(list)); | ||
1290 | } | ||
1291 | |||
1199 | /** converts a parser expression into a terminal. | 1292 | /** converts a parser expression into a terminal. |
1200 | @param e expression. | 1293 | @param e expression. |
1201 | @return an expression which parses a terminal. | 1294 | @return an expression which parses a terminal. |
diff --git a/src/yuescript/parser.hpp b/src/yuescript/parser.hpp index 7bec5d5..b504866 100644 --- a/src/yuescript/parser.hpp +++ b/src/yuescript/parser.hpp | |||
@@ -303,6 +303,12 @@ private: | |||
303 | */ | 303 | */ |
304 | expr operator>>(const expr& left, const expr& right); | 304 | expr operator>>(const expr& left, const expr& right); |
305 | 305 | ||
306 | /** creates a sequence of expressions. | ||
307 | @param list list of expressions. | ||
308 | @return an expression which parses a sequence. | ||
309 | */ | ||
310 | expr seq(std::initializer_list<expr> list); | ||
311 | |||
306 | /** creates a choice of expressions. | 312 | /** creates a choice of expressions. |
307 | @param left left operand. | 313 | @param left left operand. |
308 | @param right right operand. | 314 | @param right right operand. |
@@ -310,6 +316,12 @@ expr operator>>(const expr& left, const expr& right); | |||
310 | */ | 316 | */ |
311 | expr operator|(const expr& left, const expr& right); | 317 | expr operator|(const expr& left, const expr& right); |
312 | 318 | ||
319 | /** creates multiple choices of expressions. | ||
320 | @param list list of expressions. | ||
321 | @return an expression which parses multiple choices. | ||
322 | */ | ||
323 | expr sel(std::initializer_list<expr> list); | ||
324 | |||
313 | /** converts a parser expression into a terminal. | 325 | /** converts a parser expression into a terminal. |
314 | @param e expression. | 326 | @param e expression. |
315 | @return an expression which parses a terminal. | 327 | @return an expression which parses a terminal. |
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 86f1904..6a1a940 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
@@ -521,11 +521,12 @@ class unary_value_t; | |||
521 | class FunLit_t; | 521 | class FunLit_t; |
522 | 522 | ||
523 | AST_NODE(SimpleValue) | 523 | AST_NODE(SimpleValue) |
524 | ast_sel<true, const_value_t, | 524 | ast_sel<true, |
525 | TableLit_t, const_value_t, | ||
525 | If_t, Switch_t, With_t, ClassDecl_t, | 526 | If_t, Switch_t, With_t, ClassDecl_t, |
526 | ForEach_t, For_t, While_t, Do_t, Try_t, | 527 | ForEach_t, For_t, While_t, Do_t, Try_t, |
527 | unary_value_t, | 528 | unary_value_t, |
528 | TblComprehension_t, TableLit_t, Comprehension_t, | 529 | TblComprehension_t, Comprehension_t, |
529 | FunLit_t, Num_t> value; | 530 | FunLit_t, Num_t> value; |
530 | AST_MEMBER(SimpleValue, &value) | 531 | AST_MEMBER(SimpleValue, &value) |
531 | AST_END(SimpleValue, "simple_value"sv) | 532 | AST_END(SimpleValue, "simple_value"sv) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 6d33a7e..5a54a05 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -71,7 +71,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
71 | "close"s // Lua 5.4 | 71 | "close"s // Lua 5.4 |
72 | }; | 72 | }; |
73 | 73 | ||
74 | const std::string_view version = "0.15.21"sv; | 74 | const std::string_view version = "0.15.22"sv; |
75 | const std::string_view extension = "yue"sv; | 75 | const std::string_view extension = "yue"sv; |
76 | 76 | ||
77 | class YueCompilerImpl { | 77 | class YueCompilerImpl { |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index d23ff4b..e8b47b7 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
@@ -56,27 +56,25 @@ YueParser::YueParser() { | |||
56 | num_char = range('0', '9') >> *(range('0', '9') | expr('_') >> and_(range('0', '9'))); | 56 | num_char = range('0', '9') >> *(range('0', '9') | expr('_') >> and_(range('0', '9'))); |
57 | num_char_hex = range('0', '9') | range('a', 'f') | range('A', 'F'); | 57 | num_char_hex = range('0', '9') | range('a', 'f') | range('A', 'F'); |
58 | num_lit = num_char_hex >> *(num_char_hex | expr('_') >> and_(num_char_hex)); | 58 | num_lit = num_char_hex >> *(num_char_hex | expr('_') >> and_(num_char_hex)); |
59 | Num = ( | 59 | Num = sel({ |
60 | "0x" >> ( | 60 | expr("0x") >> ( |
61 | +num_lit >> ( | 61 | +num_lit >> sel({ |
62 | '.' >> +num_lit >> -num_expo_hex | | 62 | seq({expr('.'), +num_lit, -num_expo_hex}), |
63 | num_expo_hex | | 63 | num_expo_hex, |
64 | lj_num | | 64 | lj_num, |
65 | true_() | 65 | true_() |
66 | ) | ( | 66 | }) | seq({ |
67 | '.' >> +num_lit >> -num_expo_hex | 67 | expr('.'), +num_lit, -num_expo_hex |
68 | ) | 68 | }) |
69 | ) | 69 | ), |
70 | ) | ( | 70 | +num_char >> sel({ |
71 | +num_char >> ( | 71 | seq({expr('.'), +num_char, -num_expo}), |
72 | '.' >> +num_char >> -num_expo | | 72 | num_expo, |
73 | num_expo | | 73 | lj_num, |
74 | lj_num | | ||
75 | true_() | 74 | true_() |
76 | ) | 75 | }), |
77 | ) | ( | 76 | seq({expr('.'), +num_char, -num_expo}) |
78 | '.' >> +num_char >> -num_expo | 77 | }); |
79 | ); | ||
80 | 78 | ||
81 | Cut = false_(); | 79 | Cut = false_(); |
82 | Seperator = true_(); | 80 | Seperator = true_(); |
@@ -87,7 +85,6 @@ YueParser::YueParser() { | |||
87 | }); | 85 | }); |
88 | 86 | ||
89 | #define sym(str) (Space >> str) | 87 | #define sym(str) (Space >> str) |
90 | #define symx(str) expr(str) | ||
91 | #define ensure(patt, finally) ((patt) >> (finally) | (finally) >> Cut) | 88 | #define ensure(patt, finally) ((patt) >> (finally) | (finally) >> Cut) |
92 | #define key(str) (str >> not_(AlphaNum)) | 89 | #define key(str) (str >> not_(AlphaNum)) |
93 | #define disable_do(patt) (DisableDo >> ((patt) >> EnableDo | EnableDo >> Cut)) | 90 | #define disable_do(patt) (DisableDo >> ((patt) >> EnableDo | EnableDo >> Cut)) |
@@ -133,8 +130,8 @@ YueParser::YueParser() { | |||
133 | self_class = expr("@@"); | 130 | self_class = expr("@@"); |
134 | self_class_name = "@@" >> Name; | 131 | self_class_name = "@@" >> Name; |
135 | 132 | ||
136 | SelfName = self_class_name | self_class | self_name | self; | 133 | SelfName = sel({self_class_name, self_class, self_name, self}); |
137 | KeyName = Space >> (SelfName | Name); | 134 | KeyName = SelfName | Name; |
138 | VarArg = expr("..."); | 135 | VarArg = expr("..."); |
139 | 136 | ||
140 | check_indent = pl::user(Indent, [](const item_t& item) { | 137 | check_indent = pl::user(Indent, [](const item_t& item) { |
@@ -215,22 +212,36 @@ YueParser::YueParser() { | |||
215 | 212 | ||
216 | import_literal_inner = (range('a', 'z') | range('A', 'Z') | set("_-")) >> *(AlphaNum | '-'); | 213 | import_literal_inner = (range('a', 'z') | range('A', 'Z') | set("_-")) >> *(AlphaNum | '-'); |
217 | import_literal_chain = Seperator >> import_literal_inner >> *(expr('.') >> import_literal_inner); | 214 | import_literal_chain = Seperator >> import_literal_inner >> *(expr('.') >> import_literal_inner); |
218 | ImportLiteral = sym('\'') >> import_literal_chain >> symx('\'') | sym('"') >> import_literal_chain >> symx('"'); | 215 | ImportLiteral = sym('\'') >> import_literal_chain >> expr('\'') | sym('"') >> import_literal_chain >> expr('"'); |
219 | 216 | ||
220 | macro_name_pair = Space >> MacroName >> Space >> symx(':') >> Space >> MacroName; | 217 | macro_name_pair = Space >> MacroName >> Space >> expr(':') >> Space >> MacroName; |
221 | import_all_macro = expr('$'); | 218 | import_all_macro = expr('$'); |
222 | ImportTabItem = variable_pair | normal_pair | sym(':') >> MacroName | macro_name_pair | Space >> import_all_macro | meta_variable_pair | meta_normal_pair | Exp; | 219 | ImportTabItem = sel({ |
220 | variable_pair, | ||
221 | normal_pair, | ||
222 | sym(':') >> MacroName, | ||
223 | macro_name_pair, | ||
224 | Space >> import_all_macro, | ||
225 | meta_variable_pair, | ||
226 | meta_normal_pair, | ||
227 | Exp | ||
228 | }); | ||
223 | ImportTabList = ImportTabItem >> *(sym(',') >> ImportTabItem); | 229 | ImportTabList = ImportTabItem >> *(sym(',') >> ImportTabItem); |
224 | ImportTabLine = ( | 230 | ImportTabLine = ( |
225 | PushIndent >> (ImportTabList >> PopIndent | PopIndent) | 231 | PushIndent >> (ImportTabList >> PopIndent | PopIndent) |
226 | ) | Space; | 232 | ) | Space; |
227 | import_tab_lines = SpaceBreak >> ImportTabLine >> *(-sym(',') >> SpaceBreak >> ImportTabLine) >> -sym(','); | 233 | import_tab_lines = SpaceBreak >> ImportTabLine >> *(-sym(',') >> SpaceBreak >> ImportTabLine) >> -sym(','); |
228 | ImportTabLit = | 234 | ImportTabLit = seq({ |
229 | Seperator >> (sym('{') >> | 235 | Seperator, |
230 | -ImportTabList >> | 236 | sym('{'), |
231 | -sym(',') >> | 237 | -ImportTabList, |
232 | -import_tab_lines >> | 238 | -sym(','), |
233 | White >> sym('}') | KeyValue >> *(sym(',') >> KeyValue)); | 239 | -import_tab_lines, |
240 | White, | ||
241 | sym('}') | ||
242 | }) | seq({ | ||
243 | Seperator, KeyValue, *(sym(',') >> KeyValue) | ||
244 | }); | ||
234 | 245 | ||
235 | ImportAs = ImportLiteral >> -(Space >> key("as") >> Space >> (ImportTabLit | Variable | import_all_macro)); | 246 | ImportAs = ImportLiteral >> -(Space >> key("as") >> Space >> (ImportTabLit | Variable | import_all_macro)); |
236 | 247 | ||
@@ -273,11 +284,11 @@ YueParser::YueParser() { | |||
273 | IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("elseif") >> IfCond >> body_with("then"); | 284 | IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("elseif") >> IfCond >> body_with("then"); |
274 | IfElse = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("else") >> body; | 285 | IfElse = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("else") >> body; |
275 | IfType = (expr("if") | expr("unless")) >> not_(AlphaNum); | 286 | IfType = (expr("if") | expr("unless")) >> not_(AlphaNum); |
276 | If = Space >> IfType >> IfCond >> opt_body_with("then") >> *IfElseIf >> -IfElse; | 287 | If = seq({Space, IfType, IfCond, opt_body_with("then"), *IfElseIf, -IfElse}); |
277 | 288 | ||
278 | WhileType = (expr("while") | expr("until")) >> not_(AlphaNum); | 289 | WhileType = (expr("while") | expr("until")) >> not_(AlphaNum); |
279 | While = WhileType >> disable_do_chain_arg_table_block(Exp) >> opt_body_with("do"); | 290 | While = WhileType >> disable_do_chain_arg_table_block(Exp) >> opt_body_with("do"); |
280 | Repeat = key("repeat") >> Body >> Break >> *EmptyLine >> CheckIndent >> Space >> key("until") >> Exp; | 291 | Repeat = seq({key("repeat"), Body, Break, *EmptyLine, CheckIndent, Space, key("until"), Exp}); |
281 | 292 | ||
282 | for_step_value = sym(',') >> Exp; | 293 | for_step_value = sym(',') >> Exp; |
283 | for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; | 294 | for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; |
@@ -347,17 +358,21 @@ YueParser::YueParser() { | |||
347 | CompFor = key("for") >> Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; | 358 | CompFor = key("for") >> Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; |
348 | CompClause = Space >> (CompFor | CompForEach | key("when") >> Exp); | 359 | CompClause = Space >> (CompFor | CompForEach | key("when") >> Exp); |
349 | 360 | ||
350 | Assign = sym('=') >> Seperator >> (With | If | Switch | TableBlock | Exp >> *(Space >> set(",;") >> Exp)); | 361 | Assign = sym('=') >> Seperator >> sel({ |
362 | With, If, Switch, TableBlock, | ||
363 | Exp >> *(Space >> set(",;") >> Exp) | ||
364 | }); | ||
351 | 365 | ||
352 | update_op = | 366 | update_op = sel({ |
353 | expr("..") | | 367 | expr(".."), |
354 | expr("//") | | 368 | expr("//"), |
355 | expr("or") | | 369 | expr("or"), |
356 | expr("and") | | 370 | expr("and"), |
357 | expr(">>") | | 371 | expr(">>"), |
358 | expr("<<") | | 372 | expr("<<"), |
359 | expr("??") | | 373 | expr("??"), |
360 | set("+-*/%&|"); | 374 | set("+-*/%&|") |
375 | }); | ||
361 | 376 | ||
362 | Update = Space >> update_op >> expr("=") >> Exp; | 377 | Update = Space >> update_op >> expr("=") >> Exp; |
363 | 378 | ||
@@ -366,35 +381,37 @@ YueParser::YueParser() { | |||
366 | unary_value = +(unary_operator >> Space) >> Value; | 381 | unary_value = +(unary_operator >> Space) >> Value; |
367 | 382 | ||
368 | ExponentialOperator = expr('^'); | 383 | ExponentialOperator = expr('^'); |
369 | expo_value = Space >> ExponentialOperator >> *SpaceBreak >> Space >> Value; | 384 | expo_value = seq({Space, ExponentialOperator, *SpaceBreak, Space, Value}); |
370 | expo_exp = Value >> *expo_value; | 385 | expo_exp = Value >> *expo_value; |
371 | 386 | ||
372 | unary_operator = | 387 | unary_operator = sel({ |
373 | expr('-') >> not_(set(">=") | space_one) | | 388 | expr('-') >> not_(set(">=") | space_one), |
374 | expr('#') | | 389 | expr('#'), |
375 | expr('~') >> not_(expr('=') | space_one) | | 390 | expr('~') >> not_(expr('=') | space_one), |
376 | expr("not") >> not_(AlphaNum); | 391 | expr("not") >> not_(AlphaNum) |
392 | }); | ||
377 | unary_exp = Space >> *(unary_operator >> Space) >> expo_exp; | 393 | unary_exp = Space >> *(unary_operator >> Space) >> expo_exp; |
378 | 394 | ||
379 | PipeOperator = expr("|>"); | 395 | PipeOperator = expr("|>"); |
380 | pipe_value = Space >> PipeOperator >> *SpaceBreak >> unary_exp; | 396 | pipe_value = seq({Space, PipeOperator, *SpaceBreak, unary_exp}); |
381 | pipe_exp = unary_exp >> *pipe_value; | 397 | pipe_exp = unary_exp >> *pipe_value; |
382 | 398 | ||
383 | BinaryOperator = | 399 | BinaryOperator = sel({ |
384 | (expr("or") >> not_(AlphaNum)) | | 400 | (expr("or") >> not_(AlphaNum)), |
385 | (expr("and") >> not_(AlphaNum)) | | 401 | (expr("and") >> not_(AlphaNum)), |
386 | expr("<=") | | 402 | expr("<="), |
387 | expr(">=") | | 403 | expr(">="), |
388 | expr("~=") | | 404 | expr("~="), |
389 | expr("!=") | | 405 | expr("!="), |
390 | expr("==") | | 406 | expr("=="), |
391 | expr("..") | | 407 | expr(".."), |
392 | expr("<<") | | 408 | expr("<<"), |
393 | expr(">>") | | 409 | expr(">>"), |
394 | expr("//") | | 410 | expr("//"), |
395 | set("+-*/%><|&~"); | 411 | set("+-*/%><|&~") |
396 | exp_op_value = Space >> BinaryOperator >> *SpaceBreak >> pipe_exp; | 412 | }); |
397 | Exp = Seperator >> pipe_exp >> *exp_op_value >> -(Space >> expr("??") >> Exp); | 413 | exp_op_value = seq({Space, BinaryOperator, *SpaceBreak, pipe_exp}); |
414 | Exp = seq({Seperator, pipe_exp, *exp_op_value, -(Space >> expr("??") >> Exp)}); | ||
398 | 415 | ||
399 | DisableChain = pl::user(true_(), [](const item_t& item) { | 416 | DisableChain = pl::user(true_(), [](const item_t& item) { |
400 | State* st = reinterpret_cast<State*>(item.user_data); | 417 | State* st = reinterpret_cast<State*>(item.user_data); |
@@ -408,24 +425,30 @@ YueParser::YueParser() { | |||
408 | return true; | 425 | return true; |
409 | }); | 426 | }); |
410 | 427 | ||
411 | chain_line = CheckIndent >> Space >> (chain_dot_chain | ColonChain) >> -InvokeArgs; | 428 | chain_line = seq({CheckIndent, Space, chain_dot_chain | ColonChain, -InvokeArgs}); |
412 | chain_block = pl::user(true_(), [](const item_t& item) { | 429 | chain_block = pl::user(true_(), [](const item_t& item) { |
413 | State* st = reinterpret_cast<State*>(item.user_data); | 430 | State* st = reinterpret_cast<State*>(item.user_data); |
414 | return st->noChainBlockStack.empty() || !st->noChainBlockStack.top(); | 431 | return st->noChainBlockStack.empty() || !st->noChainBlockStack.top(); |
415 | }) >> +SpaceBreak >> Advance >> ensure( | 432 | }) >> +SpaceBreak >> Advance >> ensure( |
416 | chain_line >> *(+SpaceBreak >> chain_line), PopIndent); | 433 | chain_line >> *(+SpaceBreak >> chain_line), PopIndent); |
417 | ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -(InvokeArgs | chain_block) >> -table_appending_op; | 434 | ChainValue = seq({ |
435 | Seperator, | ||
436 | Chain, | ||
437 | -existential_op, | ||
438 | -(InvokeArgs | chain_block), | ||
439 | -table_appending_op | ||
440 | }); | ||
418 | 441 | ||
419 | simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue); | 442 | simple_table = seq({Seperator, KeyValue, *(sym(',') >> KeyValue)}); |
420 | Value = SimpleValue | simple_table | ChainValue | String; | 443 | Value = sel({SimpleValue, simple_table, ChainValue, String}); |
421 | 444 | ||
422 | single_string_inner = expr('\\') >> set("'\\") | not_(expr('\'')) >> Any; | 445 | single_string_inner = expr('\\') >> set("'\\") | not_(expr('\'')) >> Any; |
423 | SingleString = symx('\'') >> *single_string_inner >> symx('\''); | 446 | SingleString = expr('\'') >> *single_string_inner >> expr('\''); |
424 | interp = symx("#{") >> Exp >> sym('}'); | 447 | interp = expr("#{") >> Exp >> sym('}'); |
425 | double_string_plain = expr('\\') >> set("\"\\") | not_(expr('"')) >> Any; | 448 | double_string_plain = expr('\\') >> set("\"\\") | not_(expr('"')) >> Any; |
426 | double_string_inner = +(not_(interp) >> double_string_plain); | 449 | double_string_inner = +(not_(interp) >> double_string_plain); |
427 | double_string_content = double_string_inner | interp; | 450 | double_string_content = double_string_inner | interp; |
428 | DoubleString = symx('"') >> Seperator >> *double_string_content >> symx('"'); | 451 | DoubleString = expr('"') >> Seperator >> *double_string_content >> expr('"'); |
429 | String = DoubleString | SingleString | LuaString; | 452 | String = DoubleString | SingleString | LuaString; |
430 | 453 | ||
431 | lua_string_open = '[' >> *expr('=') >> '['; | 454 | lua_string_open = '[' >> *expr('=') >> '['; |
@@ -448,71 +471,99 @@ YueParser::YueParser() { | |||
448 | 471 | ||
449 | LuaString = LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose; | 472 | LuaString = LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose; |
450 | 473 | ||
451 | Parens = symx('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); | 474 | Parens = pl::user(seq({expr('('), *SpaceBreak, Exp, *SpaceBreak, Space >> expr(')')}), [](const item_t&) { |
452 | Callable = Variable | SelfName | MacroName | VarArg | Parens; | 475 | return true; |
453 | FnArgsExpList = Exp >> *((Break | sym(',')) >> White >> Exp); | 476 | }); |
477 | Callable = sel({Variable, SelfName, MacroName, VarArg, Parens}); | ||
478 | FnArgsExpList = Exp >> *seq({Break | Space >> expr(','), White, Exp}); | ||
454 | 479 | ||
455 | FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')')) | | 480 | FnArgs = seq({expr('('), *SpaceBreak, -FnArgsExpList, *SpaceBreak, Space, expr(')')}) | |
456 | (sym('!') >> not_(expr('='))); | 481 | seq({Space, expr('!'), not_(expr('='))}); |
457 | 482 | ||
458 | meta_index = Name | Index | String; | 483 | meta_index = sel({Name, Index, String}); |
459 | Metatable = expr('<') >> sym('>'); | 484 | Metatable = expr('<') >> Space >> expr('>'); |
460 | Metamethod = expr('<') >> Space >> meta_index >> sym('>'); | 485 | Metamethod = expr('<') >> Space >> meta_index >> Space >> expr('>'); |
461 | 486 | ||
462 | existential_op = expr('?') >> not_(expr('?')); | 487 | existential_op = expr('?') >> not_(expr('?')); |
463 | table_appending_op = expr("[]"); | 488 | table_appending_op = expr("[]"); |
464 | chain_call = (Callable | String) >> -existential_op >> ChainItems; | 489 | chain_call = seq({ |
465 | chain_index_chain = Index >> -existential_op >> -ChainItems; | 490 | Callable, |
466 | chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems; | 491 | -existential_op, |
467 | 492 | -ChainItems | |
468 | Chain = chain_call | chain_dot_chain | ColonChain | chain_index_chain; | 493 | }) | seq({ |
494 | String, | ||
495 | ChainItems | ||
496 | }); | ||
497 | chain_index_chain = seq({Index, -existential_op, -ChainItems}); | ||
498 | chain_dot_chain = seq({DotChainItem, -existential_op, -ChainItems}); | ||
499 | |||
500 | Chain = sel({chain_call, chain_dot_chain, ColonChain, chain_index_chain}); | ||
501 | |||
502 | chain_call_list = seq({ | ||
503 | Callable, | ||
504 | -existential_op, | ||
505 | ChainItems | ||
506 | }) | seq({ | ||
507 | String, | ||
508 | ChainItems | ||
509 | }); | ||
510 | ChainList = sel({chain_call_list, chain_dot_chain, ColonChain, chain_index_chain}); | ||
469 | 511 | ||
470 | AssignableChain = Seperator >> Chain; | 512 | AssignableChain = Seperator >> ChainList; |
471 | 513 | ||
472 | chain_with_colon = +ChainItem >> -ColonChain; | 514 | chain_with_colon = +ChainItem >> -ColonChain; |
473 | ChainItems = chain_with_colon | ColonChain; | 515 | ChainItems = chain_with_colon | ColonChain; |
474 | 516 | ||
475 | Index = symx('[') >> not_('[') >> Exp >> sym(']'); | 517 | Index = seq({expr('['), not_('['), Exp, Space, expr(']')}); |
476 | ChainItem = Invoke >> -existential_op | DotChainItem >> -existential_op | Slice | Index >> -existential_op; | 518 | ChainItem = sel({ |
477 | DotChainItem = symx('.') >> (Name | Metatable | Metamethod); | 519 | Invoke >> -existential_op, |
520 | DotChainItem >> -existential_op, | ||
521 | Slice, | ||
522 | Index >> -existential_op | ||
523 | }); | ||
524 | DotChainItem = expr('.') >> (Name | Metatable | Metamethod); | ||
478 | ColonChainItem = (expr('\\') | expr("::")) >> (LuaKeyword | Name | Metamethod); | 525 | ColonChainItem = (expr('\\') | expr("::")) >> (LuaKeyword | Name | Metamethod); |
479 | invoke_chain = Invoke >> -existential_op >> -ChainItems; | 526 | invoke_chain = Invoke >> -existential_op >> -ChainItems; |
480 | ColonChain = ColonChainItem >> -existential_op >> -invoke_chain; | 527 | ColonChain = ColonChainItem >> -existential_op >> -invoke_chain; |
481 | 528 | ||
482 | default_value = true_(); | 529 | default_value = true_(); |
483 | Slice = | 530 | Slice = seq({ |
484 | symx('[') >> not_('[') >> | 531 | expr('['), not_('['), |
485 | (Exp | default_value) >> | 532 | Exp | default_value, |
486 | sym(',') >> | 533 | Space, expr(','), |
487 | (Exp | default_value) >> | 534 | Exp | default_value, |
488 | (sym(',') >> Exp | default_value) >> | 535 | Space >> expr(',') >> Exp | default_value, |
489 | sym(']'); | 536 | Space, expr(']') |
490 | 537 | }); | |
491 | Invoke = Seperator >> ( | 538 | |
492 | FnArgs | | 539 | Invoke = Seperator >> sel({ |
493 | SingleString | | 540 | FnArgs, |
494 | DoubleString | | 541 | SingleString, |
495 | and_(expr('[')) >> LuaString | | 542 | DoubleString, |
496 | and_(expr('{')) >> TableLit); | 543 | and_(expr('[')) >> LuaString, |
544 | and_(expr('{')) >> TableLit | ||
545 | }); | ||
497 | 546 | ||
498 | SpreadExp = sym("...") >> Exp; | 547 | SpreadExp = sym("...") >> Exp; |
499 | 548 | ||
500 | TableValue = | 549 | TableValue = sel({ |
501 | variable_pair_def | | 550 | variable_pair_def, |
502 | normal_pair_def | | 551 | normal_pair_def, |
503 | meta_variable_pair_def | | 552 | meta_variable_pair_def, |
504 | meta_normal_pair_def | | 553 | meta_normal_pair_def, |
505 | SpreadExp | | 554 | SpreadExp, |
506 | normal_def; | 555 | normal_def |
556 | }); | ||
507 | 557 | ||
508 | table_lit_lines = SpaceBreak >> TableLitLine >> *(-sym(',') >> SpaceBreak >> TableLitLine) >> -sym(','); | 558 | table_lit_lines = SpaceBreak >> TableLitLine >> *(-sym(',') >> SpaceBreak >> TableLitLine) >> -sym(','); |
509 | 559 | ||
510 | TableLit = | 560 | TableLit = seq({ |
511 | sym('{') >> Seperator >> | 561 | sym('{'), Seperator, |
512 | -TableValueList >> | 562 | -TableValueList, |
513 | -sym(',') >> | 563 | -sym(','), |
514 | -table_lit_lines >> | 564 | -table_lit_lines, |
515 | White >> sym('}'); | 565 | White, sym('}') |
566 | }); | ||
516 | 567 | ||
517 | TableValueList = TableValue >> *(sym(',') >> TableValue); | 568 | TableValueList = TableValue >> *(sym(',') >> TableValue); |
518 | 569 | ||
@@ -575,13 +626,16 @@ YueParser::YueParser() { | |||
575 | 626 | ||
576 | variable_pair = sym(':') >> Variable; | 627 | variable_pair = sym(':') >> Variable; |
577 | 628 | ||
578 | normal_pair = ( | 629 | normal_pair = seq({ |
579 | KeyName | | 630 | Space, |
580 | sym('[') >> not_('[') >> Exp >> sym(']') | | 631 | sel({ |
581 | Space >> String | 632 | KeyName, |
582 | ) >> | 633 | seq({expr('['), not_('['), Exp, sym(']')}), |
583 | symx(':') >> not_(':') >> | 634 | String |
584 | (Exp | TableBlock | +SpaceBreak >> Exp); | 635 | }), |
636 | expr(':'), not_(':'), | ||
637 | sel({Exp, TableBlock, +SpaceBreak >> Exp}) | ||
638 | }); | ||
585 | 639 | ||
586 | meta_variable_pair = sym(":<") >> Space >> Variable >> sym('>'); | 640 | meta_variable_pair = sym(":<") >> Space >> Variable >> sym('>'); |
587 | 641 | ||
@@ -594,27 +648,31 @@ YueParser::YueParser() { | |||
594 | meta_normal_pair_def = meta_normal_pair >> -(sym('=') >> Exp); | 648 | meta_normal_pair_def = meta_normal_pair >> -(sym('=') >> Exp); |
595 | normal_def = Exp >> Seperator >> -(sym('=') >> Exp); | 649 | normal_def = Exp >> Seperator >> -(sym('=') >> Exp); |
596 | 650 | ||
597 | KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair; | 651 | KeyValue = sel({ |
652 | variable_pair, | ||
653 | normal_pair, | ||
654 | meta_variable_pair, | ||
655 | meta_normal_pair | ||
656 | }); | ||
598 | KeyValueList = KeyValue >> *(sym(',') >> KeyValue); | 657 | KeyValueList = KeyValue >> *(sym(',') >> KeyValue); |
599 | KeyValueLine = CheckIndent >> (KeyValueList >> -sym(',') | TableBlockIndent | Space >> expr('*') >> (SpreadExp | Exp | TableBlock)); | 658 | KeyValueLine = CheckIndent >> (KeyValueList >> -sym(',') | TableBlockIndent | Space >> expr('*') >> (SpreadExp | Exp | TableBlock)); |
600 | 659 | ||
601 | FnArgDef = (Variable | SelfName >> -existential_op) >> -(sym('=') >> Space >> Exp); | 660 | FnArgDef = (Variable | SelfName >> -existential_op) >> -(sym('=') >> Space >> Exp); |
602 | 661 | ||
603 | FnArgDefList = Space >> Seperator >> ( | 662 | FnArgDefList = Space >> Seperator >> ( |
604 | ( | 663 | seq({ |
605 | FnArgDef >> | 664 | FnArgDef, |
606 | *((sym(',') | Break) >> White >> FnArgDef) >> | 665 | *seq({(sym(',') | Break), White, FnArgDef}), |
607 | -((sym(',') | Break) >> White >> VarArg) | 666 | -seq({(sym(',') | Break), White, VarArg}) |
608 | ) | ( | 667 | }) | |
609 | VarArg | 668 | VarArg |
610 | ) | ||
611 | ); | 669 | ); |
612 | 670 | ||
613 | outer_var_shadow = Space >> key("using") >> (NameList | Space >> expr("nil")); | 671 | outer_var_shadow = Space >> key("using") >> (NameList | Space >> expr("nil")); |
614 | 672 | ||
615 | FnArgsDef = sym('(') >> White >> -FnArgDefList >> -outer_var_shadow >> White >> sym(')'); | 673 | FnArgsDef = seq({Space, expr('('), White, -FnArgDefList, -outer_var_shadow, White, Space, expr(')')}); |
616 | fn_arrow = expr("->") | expr("=>"); | 674 | fn_arrow = expr("->") | expr("=>"); |
617 | FunLit = -FnArgsDef >> Space >> fn_arrow >> -Body; | 675 | FunLit = seq({-FnArgsDef, Space, fn_arrow, -Body}); |
618 | 676 | ||
619 | MacroName = expr('$') >> Name; | 677 | MacroName = expr('$') >> Name; |
620 | macro_args_def = sym('(') >> White >> -FnArgDefList >> White >> sym(')'); | 678 | macro_args_def = sym('(') >> White >> -FnArgDefList >> White >> sym(')'); |
@@ -627,9 +685,14 @@ YueParser::YueParser() { | |||
627 | AssignableNameList = Seperator >> NameOrDestructure >> *(sym(',') >> NameOrDestructure); | 685 | AssignableNameList = Seperator >> NameOrDestructure >> *(sym(',') >> NameOrDestructure); |
628 | 686 | ||
629 | fn_arrow_back = expr('<') >> set("-="); | 687 | fn_arrow_back = expr('<') >> set("-="); |
630 | Backcall = -FnArgsDef >> Space >> fn_arrow_back >> Space >> ChainValue; | 688 | Backcall = seq({-FnArgsDef, Space, fn_arrow_back, Space, ChainValue}); |
631 | 689 | ||
632 | PipeBody = Seperator >> PipeOperator >> unary_exp >> *(+SpaceBreak >> CheckIndent >> Space >> PipeOperator >> unary_exp); | 690 | PipeBody = seq({ |
691 | Seperator, | ||
692 | PipeOperator, | ||
693 | unary_exp, | ||
694 | *seq({+SpaceBreak, CheckIndent, Space, PipeOperator, unary_exp}) | ||
695 | }); | ||
633 | 696 | ||
634 | ExpList = Seperator >> Exp >> *(sym(',') >> Exp); | 697 | ExpList = Seperator >> Exp >> *(sym(',') >> Exp); |
635 | ExpListLow = Seperator >> Exp >> *(Space >> set(",;") >> Exp); | 698 | ExpListLow = Seperator >> Exp >> *(Space >> set(",;") >> Exp); |
@@ -661,13 +724,14 @@ YueParser::YueParser() { | |||
661 | leading_spaces_error | 724 | leading_spaces_error |
662 | ); | 725 | ); |
663 | 726 | ||
664 | const_value = (expr("nil") | expr("true") | expr("false")) >> not_(AlphaNum); | 727 | const_value = sel({expr("nil"), expr("true"), expr("false")}) >> not_(AlphaNum); |
665 | 728 | ||
666 | SimpleValue = | 729 | SimpleValue = sel({ |
667 | TableLit | const_value | If | Switch | Try | With | | 730 | TableLit, const_value, If, Switch, Try, With, |
668 | ClassDecl | ForEach | For | While | Do | | 731 | ClassDecl, ForEach, For, While, Do, |
669 | unary_value | TblComprehension | Comprehension | | 732 | unary_value, TblComprehension, Comprehension, |
670 | FunLit | Num; | 733 | FunLit, Num |
734 | }); | ||
671 | 735 | ||
672 | ExpListAssign = ExpList >> -(Update | Assign) >> not_(Space >> expr('=')); | 736 | ExpListAssign = ExpList >> -(Update | Assign) >> not_(Space >> expr('=')); |
673 | 737 | ||
@@ -683,15 +747,34 @@ YueParser::YueParser() { | |||
683 | ChainAssign = Seperator >> Exp >> +(sym('=') >> Exp >> Space >> and_('=')) >> Assign; | 747 | ChainAssign = Seperator >> Exp >> +(sym('=') >> Exp >> Space >> and_('=')) >> Assign; |
684 | 748 | ||
685 | statement_appendix = (if_line | while_line | CompInner) >> Space; | 749 | statement_appendix = (if_line | while_line | CompInner) >> Space; |
686 | statement_sep = and_(*SpaceBreak >> CheckIndent >> Space >> (set("($'\"") | expr("[[") | expr("[="))); | 750 | statement_sep = and_(seq({ |
687 | Statement = Seperator >> -(yue_comment >> *(Break >> yue_comment) >> Break >> CheckIndent) >> Space >> ( | 751 | *SpaceBreak, CheckIndent, Space, |
688 | Import | While | Repeat | For | ForEach | | 752 | sel({ |
689 | Return | Local | Global | Export | Macro | | 753 | set("($'\""), |
690 | MacroInPlace | BreakLoop | Label | Goto | ShortTabAppending | | 754 | expr("[["), |
691 | LocalAttrib | Backcall | PipeBody | ExpListAssign | ChainAssign | | 755 | expr("[=") |
692 | statement_appendix >> empty_block_error | 756 | }) |
693 | ) >> Space >> | 757 | })); |
694 | -statement_appendix >> -statement_sep; | 758 | Statement = seq({ |
759 | Seperator, | ||
760 | -seq({ | ||
761 | yue_comment, | ||
762 | *(Break >> yue_comment), | ||
763 | Break, | ||
764 | CheckIndent | ||
765 | }), | ||
766 | Space, | ||
767 | sel({ | ||
768 | Import, While, Repeat, For, ForEach, | ||
769 | Return, Local, Global, Export, Macro, | ||
770 | MacroInPlace, BreakLoop, Label, Goto, ShortTabAppending, | ||
771 | LocalAttrib, Backcall, PipeBody, ExpListAssign, ChainAssign, | ||
772 | statement_appendix >> empty_block_error | ||
773 | }), | ||
774 | Space, | ||
775 | -statement_appendix, | ||
776 | -statement_sep | ||
777 | }); | ||
695 | 778 | ||
696 | Body = InBlock | Space >> Statement; | 779 | Body = InBlock | Space >> Statement; |
697 | 780 | ||
@@ -705,15 +788,16 @@ YueParser::YueParser() { | |||
705 | return false; | 788 | return false; |
706 | }); | 789 | }); |
707 | 790 | ||
708 | Line = | 791 | Line = sel({ |
709 | CheckIndent >> Statement | | 792 | CheckIndent >> Statement, |
710 | empty_line_break | | 793 | empty_line_break, |
711 | Advance >> ensure(Space >> (indentation_error | Statement), PopIndent); | 794 | Advance >> ensure(Space >> (indentation_error | Statement), PopIndent) |
712 | Block = Seperator >> Line >> *(+Break >> Line); | 795 | }); |
796 | Block = seq({Seperator, Line, *(+Break >> Line)}); | ||
713 | 797 | ||
714 | Shebang = expr("#!") >> *(not_(Stop) >> Any); | 798 | Shebang = expr("#!") >> *(not_(Stop) >> Any); |
715 | BlockEnd = Block >> White >> Stop; | 799 | BlockEnd = seq({Block, White, Stop}); |
716 | File = -Shebang >> -Block >> White >> Stop; | 800 | File = seq({-Shebang, -Block, White, Stop}); |
717 | } | 801 | } |
718 | // clang-format on | 802 | // clang-format on |
719 | 803 | ||
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index c37894c..1068468 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
@@ -176,6 +176,7 @@ private: | |||
176 | rule for_in; | 176 | rule for_in; |
177 | rule CompClause; | 177 | rule CompClause; |
178 | rule Chain; | 178 | rule Chain; |
179 | rule ChainList; | ||
179 | rule KeyValue; | 180 | rule KeyValue; |
180 | rule single_string_inner; | 181 | rule single_string_inner; |
181 | rule interp; | 182 | rule interp; |
@@ -186,6 +187,7 @@ private: | |||
186 | rule FnArgs; | 187 | rule FnArgs; |
187 | rule macro_args_def; | 188 | rule macro_args_def; |
188 | rule chain_call; | 189 | rule chain_call; |
190 | rule chain_call_list; | ||
189 | rule chain_index_chain; | 191 | rule chain_index_chain; |
190 | rule ChainItems; | 192 | rule ChainItems; |
191 | rule chain_dot_chain; | 193 | rule chain_dot_chain; |