aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2023-01-16 17:28:26 +0800
committerLi Jin <dragon-fly@qq.com>2023-01-16 18:06:38 +0800
commit0dfff530f1b0be147e5cf44b9e3786a3f5b35a27 (patch)
tree119a4044c4e74be4e87e7ccde33226e85ca70739
parentc1cc934e55ca88117599121841301783d29aac32 (diff)
downloadyuescript-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.cpp95
-rw-r--r--src/yuescript/parser.hpp12
-rw-r--r--src/yuescript/yue_ast.h5
-rw-r--r--src/yuescript/yue_compiler.cpp2
-rw-r--r--src/yuescript/yue_parser.cpp396
-rw-r--r--src/yuescript/yue_parser.h2
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
609protected: 609protected:
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
637class _seq_list : public _expr {
638public:
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 }
668private:
669 std::vector<_expr*> m_list;
670};
671
635// choice 672// choice
636class _choice : public _binary { 673class _choice : public _binary {
637public: 674public:
@@ -657,6 +694,46 @@ public:
657 } 694 }
658}; 695};
659 696
697// select
698class _sel : public _expr {
699public:
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 }
733private:
734 std::vector<_expr*> m_list;
735};
736
660// reference to rule 737// reference to rule
661class _ref : public _expr { 738class _ref : public _expr {
662public: 739public:
@@ -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*/
1270expr 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*/
1288expr 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*/
304expr operator>>(const expr& left, const expr& right); 304expr 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*/
310expr 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*/
311expr operator|(const expr& left, const expr& right); 317expr 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*/
323expr 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;
521class FunLit_t; 521class FunLit_t;
522 522
523AST_NODE(SimpleValue) 523AST_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)
531AST_END(SimpleValue, "simple_value"sv) 532AST_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
74const std::string_view version = "0.15.21"sv; 74const std::string_view version = "0.15.22"sv;
75const std::string_view extension = "yue"sv; 75const std::string_view extension = "yue"sv;
76 76
77class YueCompilerImpl { 77class 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;