aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2023-01-29 10:29:19 +0800
committerLi Jin <dragon-fly@qq.com>2023-01-29 10:29:19 +0800
commite10b1b163a9a173f32b956bf1fb9be00194352b5 (patch)
tree4692fe729bbb588c0565ce78426c932e8b360f22
parent32f2a579ec15e6204e44d67ab2b8b4a1796e9a84 (diff)
downloadyuescript-e10b1b163a9a173f32b956bf1fb9be00194352b5.tar.gz
yuescript-e10b1b163a9a173f32b956bf1fb9be00194352b5.tar.bz2
yuescript-e10b1b163a9a173f32b956bf1fb9be00194352b5.zip
fix cases from issue #120.
-rw-r--r--spec/inputs/loops.yue6
-rw-r--r--spec/inputs/return.yue2
-rw-r--r--spec/outputs/5.1/loops.lua3
-rw-r--r--spec/outputs/loops.lua3
-rw-r--r--src/yuescript/parser.cpp12
-rw-r--r--src/yuescript/parser.hpp14
-rw-r--r--src/yuescript/yue_ast.h4
-rw-r--r--src/yuescript/yue_compiler.cpp54
-rw-r--r--src/yuescript/yue_parser.cpp64
-rw-r--r--src/yuescript/yue_parser.h250
10 files changed, 261 insertions, 151 deletions
diff --git a/spec/inputs/loops.yue b/spec/inputs/loops.yue
index d997c65..51eb10b 100644
--- a/spec/inputs/loops.yue
+++ b/spec/inputs/loops.yue
@@ -75,15 +75,17 @@ while also do
75i = 0 75i = 0
76x = while i < 10 76x = while i < 10
77 i += 1 77 i += 1
78 i
78 79
79-- values that can'e be coerced 80-- values that can't be coerced
80 81
81x = for thing in *3 82x = for thing in *3
82 y = "hello" 83 y = "hello"
84 break
83 85
84x = for x=1,2 86x = for x=1,2
85 y = "hello" 87 y = "hello"
86 88 y
87 89
88-- continue 90-- continue
89 91
diff --git a/spec/inputs/return.yue b/spec/inputs/return.yue
index 96fa0cd..fda8d62 100644
--- a/spec/inputs/return.yue
+++ b/spec/inputs/return.yue
@@ -6,7 +6,7 @@ _ = -> [x for x in *things]
6 6
7-- doesn't make sense on purpose 7-- doesn't make sense on purpose
8do 8do
9 return x for x in *things 9 for x in *things do return x
10 10
11do 11do
12 return [x for x in *things] 12 return [x for x in *things]
diff --git a/spec/outputs/5.1/loops.lua b/spec/outputs/5.1/loops.lua
index a3b9548..85e9de8 100644
--- a/spec/outputs/5.1/loops.lua
+++ b/spec/outputs/5.1/loops.lua
@@ -125,6 +125,7 @@ do
125 local _len_0 = 1 125 local _len_0 = 1
126 while i < 10 do 126 while i < 10 do
127 i = i + 1 127 i = i + 1
128 _accum_0[_len_0] = i
128 _len_0 = _len_0 + 1 129 _len_0 = _len_0 + 1
129 end 130 end
130 x = _accum_0 131 x = _accum_0
@@ -136,6 +137,7 @@ do
136 for _index_0 = 1, #_list_2 do 137 for _index_0 = 1, #_list_2 do
137 local thing = _list_2[_index_0] 138 local thing = _list_2[_index_0]
138 y = "hello" 139 y = "hello"
140 break
139 _len_0 = _len_0 + 1 141 _len_0 = _len_0 + 1
140 end 142 end
141 x = _accum_0 143 x = _accum_0
@@ -145,6 +147,7 @@ do
145 local _len_0 = 1 147 local _len_0 = 1
146 for x = 1, 2 do 148 for x = 1, 2 do
147 y = "hello" 149 y = "hello"
150 _accum_0[_len_0] = y
148 _len_0 = _len_0 + 1 151 _len_0 = _len_0 + 1
149 end 152 end
150 x = _accum_0 153 x = _accum_0
diff --git a/spec/outputs/loops.lua b/spec/outputs/loops.lua
index 9c16ee4..eeea15f 100644
--- a/spec/outputs/loops.lua
+++ b/spec/outputs/loops.lua
@@ -125,6 +125,7 @@ do
125 local _len_0 = 1 125 local _len_0 = 1
126 while i < 10 do 126 while i < 10 do
127 i = i + 1 127 i = i + 1
128 _accum_0[_len_0] = i
128 _len_0 = _len_0 + 1 129 _len_0 = _len_0 + 1
129 end 130 end
130 x = _accum_0 131 x = _accum_0
@@ -136,6 +137,7 @@ do
136 for _index_0 = 1, #_list_2 do 137 for _index_0 = 1, #_list_2 do
137 local thing = _list_2[_index_0] 138 local thing = _list_2[_index_0]
138 y = "hello" 139 y = "hello"
140 break
139 _len_0 = _len_0 + 1 141 _len_0 = _len_0 + 1
140 end 142 end
141 x = _accum_0 143 x = _accum_0
@@ -145,6 +147,7 @@ do
145 local _len_0 = 1 147 local _len_0 = 1
146 for x = 1, 2 do 148 for x = 1, 2 do
147 y = "hello" 149 y = "hello"
150 _accum_0[_len_0] = y
148 _len_0 = _len_0 + 1 151 _len_0 = _len_0 + 1
149 end 152 end
150 x = _accum_0 153 x = _accum_0
diff --git a/src/yuescript/parser.cpp b/src/yuescript/parser.cpp
index 078e23f..0fc1c1e 100644
--- a/src/yuescript/parser.cpp
+++ b/src/yuescript/parser.cpp
@@ -1217,6 +1217,18 @@ rule::rule(const expr& e)
1217 : m_expr(_private::get_expr(e)) 1217 : m_expr(_private::get_expr(e))
1218 , m_parse_proc(nullptr) { } 1218 , m_parse_proc(nullptr) { }
1219 1219
1220#ifndef NDEBUG
1221
1222/** constructor from a expression name.
1223 @param name name of expression.
1224*/
1225rule::rule(const char* name, rule::initTag)
1226 : m_expr(nullptr)
1227 , m_parse_proc(nullptr)
1228 , m_name(name) { }
1229
1230#endif // NDEBUG
1231
1220/** constructor from rule. 1232/** constructor from rule.
1221 @param r rule. 1233 @param r rule.
1222*/ 1234*/
diff --git a/src/yuescript/parser.hpp b/src/yuescript/parser.hpp
index 1973315..5a0afa8 100644
--- a/src/yuescript/parser.hpp
+++ b/src/yuescript/parser.hpp
@@ -207,6 +207,16 @@ public:
207 */ 207 */
208 rule(const expr& e); 208 rule(const expr& e);
209 209
210#ifndef NDEBUG
211
212 /** constructor from a expression name.
213 @param name name of expression.
214 */
215 struct initTag { };
216 rule(const char* name, initTag);
217
218#endif // NDEBUG
219
210 /** constructor from rule. 220 /** constructor from rule.
211 @param r rule. 221 @param r rule.
212 */ 222 */
@@ -286,6 +296,10 @@ private:
286 // internal expression 296 // internal expression
287 _expr* m_expr; 297 _expr* m_expr;
288 298
299#ifndef NDEBUG
300 const char* m_name = nullptr;
301#endif
302
289 // associated parse procedure. 303 // associated parse procedure.
290 parse_proc m_parse_proc; 304 parse_proc m_parse_proc;
291 305
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index 9101b2f..b265ebc 100644
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -450,7 +450,7 @@ class Parens_t;
450class MacroName_t; 450class MacroName_t;
451 451
452AST_NODE(Callable) 452AST_NODE(Callable)
453 ast_sel<true, Variable_t, SelfItem_t, VarArg_t, Parens_t, MacroName_t> item; 453 ast_sel<true, Variable_t, SelfItem_t, Parens_t, MacroName_t> item;
454 AST_MEMBER(Callable, &item) 454 AST_MEMBER(Callable, &item)
455AST_END(Callable, "callable"sv) 455AST_END(Callable, "callable"sv)
456 456
@@ -527,7 +527,7 @@ AST_NODE(SimpleValue)
527 ForEach_t, For_t, While_t, Do_t, Try_t, 527 ForEach_t, For_t, While_t, Do_t, Try_t,
528 UnaryValue_t, 528 UnaryValue_t,
529 TblComprehension_t, Comprehension_t, 529 TblComprehension_t, Comprehension_t,
530 FunLit_t, Num_t> value; 530 FunLit_t, Num_t, VarArg_t> value;
531 AST_MEMBER(SimpleValue, &value) 531 AST_MEMBER(SimpleValue, &value)
532AST_END(SimpleValue, "simple_value"sv) 532AST_END(SimpleValue, "simple_value"sv)
533 533
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 5443c61..c7f0f27 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.23"sv; 74const std::string_view version = "0.15.24"sv;
75const std::string_view extension = "yue"sv; 75const std::string_view extension = "yue"sv;
76 76
77class YueCompilerImpl { 77class YueCompilerImpl {
@@ -1224,6 +1224,8 @@ private:
1224 } 1224 }
1225 default: YUEE("AST node mismatch", appendix->item.get()); break; 1225 default: YUEE("AST node mismatch", appendix->item.get()); break;
1226 } 1226 }
1227 } else if (statement->content.is<Return_t>() && !statement->appendix->item.is<IfLine_t>()) {
1228 throw std::logic_error(_info.errorMessage("loop line decorator can not be used in a return statement"sv, statement->appendix->item));
1227 } 1229 }
1228 auto appendix = statement->appendix.get(); 1230 auto appendix = statement->appendix.get();
1229 switch (appendix->item->getId()) { 1231 switch (appendix->item->getId()) {
@@ -1357,7 +1359,7 @@ private:
1357 break; 1359 break;
1358 } 1360 }
1359 } 1361 }
1360 throw std::logic_error(_info.errorMessage("expression list is not supported here"sv, expList)); 1362 throw std::logic_error(_info.errorMessage("unexpected expression"sv, expList));
1361 } 1363 }
1362 break; 1364 break;
1363 } 1365 }
@@ -3029,7 +3031,7 @@ private:
3029 auto unary = static_cast<UnaryExp_t*>(*it); 3031 auto unary = static_cast<UnaryExp_t*>(*it);
3030 auto value = static_cast<Value_t*>(singleUnaryExpFrom(unary) ? unary->expos.back() : nullptr); 3032 auto value = static_cast<Value_t*>(singleUnaryExpFrom(unary) ? unary->expos.back() : nullptr);
3031 if (values.back() == *it && !unary->ops.empty() && usage == ExpUsage::Common) { 3033 if (values.back() == *it && !unary->ops.empty() && usage == ExpUsage::Common) {
3032 throw std::logic_error(_info.errorMessage("expression list is not supported here"sv, x)); 3034 throw std::logic_error(_info.errorMessage("unexpected expression"sv, x));
3033 } 3035 }
3034 if (!value) throw std::logic_error(_info.errorMessage("pipe operator must be followed by chain value"sv, *it)); 3036 if (!value) throw std::logic_error(_info.errorMessage("pipe operator must be followed by chain value"sv, *it));
3035 if (auto chainValue = value->item.as<ChainValue_t>()) { 3037 if (auto chainValue = value->item.as<ChainValue_t>()) {
@@ -3275,13 +3277,6 @@ private:
3275 globalVar("self"sv, item); 3277 globalVar("self"sv, item);
3276 break; 3278 break;
3277 } 3279 }
3278 case id<VarArg_t>():
3279 if (_varArgs.empty() || !_varArgs.top().hasVar) {
3280 throw std::logic_error(_info.errorMessage("cannot use '...' outside a vararg function near '...'"sv, item));
3281 }
3282 _varArgs.top().usedVar = true;
3283 out.push_back("..."s);
3284 break;
3285 case id<Parens_t>(): transformParens(static_cast<Parens_t*>(item), out); break; 3280 case id<Parens_t>(): transformParens(static_cast<Parens_t*>(item), out); break;
3286 default: YUEE("AST node mismatch", item); break; 3281 default: YUEE("AST node mismatch", item); break;
3287 } 3282 }
@@ -3312,6 +3307,7 @@ private:
3312 case id<Comprehension_t>(): transformComprehension(static_cast<Comprehension_t*>(value), out, ExpUsage::Closure); break; 3307 case id<Comprehension_t>(): transformComprehension(static_cast<Comprehension_t*>(value), out, ExpUsage::Closure); break;
3313 case id<FunLit_t>(): transformFunLit(static_cast<FunLit_t*>(value), out); break; 3308 case id<FunLit_t>(): transformFunLit(static_cast<FunLit_t*>(value), out); break;
3314 case id<Num_t>(): transformNum(static_cast<Num_t*>(value), out); break; 3309 case id<Num_t>(): transformNum(static_cast<Num_t*>(value), out); break;
3310 case id<VarArg_t>(): transformVarArg(static_cast<VarArg_t*>(value), out); break;
3315 default: YUEE("AST node mismatch", value); break; 3311 default: YUEE("AST node mismatch", value); break;
3316 } 3312 }
3317 } 3313 }
@@ -3638,8 +3634,19 @@ private:
3638 } 3634 }
3639 case ExpUsage::Assignment: { 3635 case ExpUsage::Assignment: {
3640 auto last = lastStatementFrom(block); 3636 auto last = lastStatementFrom(block);
3641 if (!last) return; 3637 if (!last) throw std::logic_error(_info.errorMessage("block is not assignable"sv, block));
3642 bool lastAssignable = expListFrom(last) || ast_is<For_t, ForEach_t, While_t>(last->content); 3638 if (last->appendix) {
3639 auto appendix = last->appendix->item.get();
3640 switch (appendix->getId()) {
3641 case id<WhileLine_t>():
3642 throw std::logic_error(_info.errorMessage("while-loop line decorator is not supported here"sv, appendix));
3643 break;
3644 case id<CompFor_t>():
3645 throw std::logic_error(_info.errorMessage("for-loop line decorator is not supported here"sv, appendix));
3646 break;
3647 }
3648 }
3649 bool lastAssignable = (expListFrom(last) || ast_is<For_t, ForEach_t, While_t>(last->content));
3643 if (lastAssignable) { 3650 if (lastAssignable) {
3644 auto x = last; 3651 auto x = last;
3645 auto newAssignment = x->new_ptr<ExpListAssign_t>(); 3652 auto newAssignment = x->new_ptr<ExpListAssign_t>();
@@ -3660,6 +3667,8 @@ private:
3660 if (bLast != nodes.rend()) { 3667 if (bLast != nodes.rend()) {
3661 static_cast<Statement_t*>(*bLast)->needSep.set(nullptr); 3668 static_cast<Statement_t*>(*bLast)->needSep.set(nullptr);
3662 } 3669 }
3670 } else if (!last->content.is<BreakLoop_t>()) {
3671 throw std::logic_error(_info.errorMessage("expecting assignable statement or break loop"sv, last));
3663 } 3672 }
3664 break; 3673 break;
3665 } 3674 }
@@ -4627,12 +4636,6 @@ private:
4627 4636
4628 void transformChainList(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 4637 void transformChainList(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
4629 auto x = chainList.front(); 4638 auto x = chainList.front();
4630 if (chainList.size() > 1) {
4631 auto callable = ast_cast<Callable_t>(x);
4632 if (callable && callable->item.is<VarArg_t>()) {
4633 throw std::logic_error(_info.errorMessage("can not access variadic arguments directly"sv, x));
4634 }
4635 }
4636 str_list temp; 4639 str_list temp;
4637 switch (x->getId()) { 4640 switch (x->getId()) {
4638 case id<DotChainItem_t>(): 4641 case id<DotChainItem_t>():
@@ -5277,6 +5280,14 @@ private:
5277 out.push_back(numStr); 5280 out.push_back(numStr);
5278 } 5281 }
5279 5282
5283 void transformVarArg(VarArg_t* varArg, str_list& out) {
5284 if (_varArgs.empty() || !_varArgs.top().hasVar) {
5285 throw std::logic_error(_info.errorMessage("cannot use '...' outside a vararg function near '...'"sv, varArg));
5286 }
5287 _varArgs.top().usedVar = true;
5288 out.push_back("..."s);
5289 }
5290
5280 bool hasSpreadExp(const node_container& items) { 5291 bool hasSpreadExp(const node_container& items) {
5281 for (auto item : items) { 5292 for (auto item : items) {
5282 if (ast_is<SpreadExp_t>(item)) return true; 5293 if (ast_is<SpreadExp_t>(item)) return true;
@@ -5420,10 +5431,9 @@ private:
5420 BREAK_IF(current != values.back()); 5431 BREAK_IF(current != values.back());
5421 auto value = singleValueFrom(item); 5432 auto value = singleValueFrom(item);
5422 BREAK_IF(!value); 5433 BREAK_IF(!value);
5423 auto chainValue = value->item.as<ChainValue_t>(); 5434 auto simpleValue = value->item.as<SimpleValue_t>();
5424 BREAK_IF(!chainValue); 5435 BREAK_IF(!simpleValue);
5425 BREAK_IF(chainValue->items.size() != 1); 5436 BREAK_IF(!simpleValue->value.is<VarArg_t>());
5426 BREAK_IF((!chainValue->getByPath<Callable_t, VarArg_t>()));
5427 auto indexVar = getUnusedName("_index_"); 5437 auto indexVar = getUnusedName("_index_");
5428 _buf << "for "sv << indexVar << "=1,select '#',...\n\t"sv << tableVar << "[]= select "sv << indexVar << ",..."sv; 5438 _buf << "for "sv << indexVar << "=1,select '#',...\n\t"sv << tableVar << "[]= select "sv << indexVar << ",..."sv;
5429 transformFor(toAst<For_t>(clearBuf(), item), temp); 5439 transformFor(toAst<For_t>(clearBuf(), item), temp);
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index 2fc1333..5bb4817 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -114,6 +114,13 @@ YueParser::YueParser() {
114 ) \ 114 ) \
115 ) 115 )
116 116
117 #define disable_for_rule(patt) ( \
118 disable_for >> ( \
119 (patt) >> enable_for | \
120 enable_for >> cut \
121 ) \
122 )
123
117 #define body_with(str) ( \ 124 #define body_with(str) ( \
118 key(str) >> space >> (in_block | Statement) | \ 125 key(str) >> space >> (in_block | Statement) | \
119 in_block | \ 126 in_block | \
@@ -327,14 +334,18 @@ YueParser::YueParser() {
327 While = WhileType >> space >> disable_do_chain_arg_table_block_rule(Exp) >> space >> opt_body_with("do"); 334 While = WhileType >> space >> disable_do_chain_arg_table_block_rule(Exp) >> space >> opt_body_with("do");
328 Repeat = key("repeat") >> space >> Body >> line_break >> *space_break >> check_indent_match >> space >> key("until") >> space >> Exp; 335 Repeat = key("repeat") >> space >> Body >> line_break >> *space_break >> check_indent_match >> space >> key("until") >> space >> Exp;
329 336
337 for_key = pl::user(key("for"), [](const item_t& item) {
338 State* st = reinterpret_cast<State*>(item.user_data);
339 return st->noForStack.empty() || !st->noForStack.top();
340 });
330 ForStepValue = ',' >> space >> Exp; 341 ForStepValue = ',' >> space >> Exp;
331 for_args = Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> space >> -ForStepValue; 342 for_args = Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> space >> -ForStepValue;
332 343
333 For = key("for") >> space >> disable_do_chain_arg_table_block_rule(for_args) >> space >> opt_body_with("do"); 344 For = for_key >> space >> disable_do_chain_arg_table_block_rule(for_args) >> space >> opt_body_with("do");
334 345
335 for_in = StarExp | ExpList; 346 for_in = StarExp | ExpList;
336 347
337 ForEach = key("for") >> space >> AssignableNameList >> space >> key("in") >> space >> 348 ForEach = for_key >> space >> AssignableNameList >> space >> key("in") >> space >>
338 disable_do_chain_arg_table_block_rule(for_in) >> space >> opt_body_with("do"); 349 disable_do_chain_arg_table_block_rule(for_in) >> space >> opt_body_with("do");
339 350
340 Do = pl::user(key("do"), [](const item_t& item) { 351 Do = pl::user(key("do"), [](const item_t& item) {
@@ -382,12 +393,24 @@ YueParser::YueParser() {
382 return true; 393 return true;
383 }); 394 });
384 395
396 disable_for = pl::user(true_(), [](const item_t& item) {
397 State* st = reinterpret_cast<State*>(item.user_data);
398 st->noForStack.push(true);
399 return true;
400 });
401
402 enable_for = pl::user(true_(), [](const item_t& item) {
403 State* st = reinterpret_cast<State*>(item.user_data);
404 st->noForStack.pop();
405 return true;
406 });
407
385 CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> Variable >> space >> in_block; 408 CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> Variable >> space >> in_block;
386 Try = key("try") >> space >> (in_block | Exp) >> -CatchBlock; 409 Try = key("try") >> space >> (in_block | Exp) >> -CatchBlock;
387 410
388 Comprehension = '[' >> not_('[') >> space >> Exp >> space >> CompInner >> space >> ']'; 411 Comprehension = '[' >> not_('[') >> space >> disable_for_rule(Exp) >> space >> CompInner >> space >> ']';
389 CompValue = ',' >> space >> Exp; 412 CompValue = ',' >> space >> Exp;
390 TblComprehension = '{' >> (space >> Exp >> space >> -(CompValue >> space) >> CompInner >> space >> '}' | braces_expression_error); 413 TblComprehension = and_('{') >> ('{' >> space >> disable_for_rule(Exp >> space >> -(CompValue >> space)) >> CompInner >> space >> '}' | braces_expression_error);
391 414
392 CompInner = Seperator >> (CompForEach | CompFor) >> *(space >> comp_clause); 415 CompInner = Seperator >> (CompForEach | CompFor) >> *(space >> comp_clause);
393 StarExp = '*' >> space >> Exp; 416 StarExp = '*' >> space >> Exp;
@@ -461,8 +484,24 @@ YueParser::YueParser() {
461 -(InvokeArgs | chain_block) >> 484 -(InvokeArgs | chain_block) >>
462 -TableAppendingOp; 485 -TableAppendingOp;
463 486
487 inc_exp_level = pl::user(true_(), [](const item_t& item) {
488 State* st = reinterpret_cast<State*>(item.user_data);
489 st->expLevel++;
490 const int max_exp_level = 100;
491 if (st->expLevel > max_exp_level) {
492 throw ParserError("nesting expressions exceeds 100 levels", *item.begin, *item.end);
493 }
494 return true;
495 });
496
497 dec_exp_level = pl::user(true_(), [](const item_t& item) {
498 State* st = reinterpret_cast<State*>(item.user_data);
499 st->expLevel--;
500 return true;
501 });
502
464 SimpleTable = Seperator >> key_value >> *(space >> ',' >> space >> key_value); 503 SimpleTable = Seperator >> key_value >> *(space >> ',' >> space >> key_value);
465 Value = SimpleValue | SimpleTable | ChainValue | String; 504 Value = inc_exp_level >> ensure(SimpleValue | SimpleTable | ChainValue | String, dec_exp_level);
466 505
467 single_string_inner = '\\' >> set("'\\") | not_('\'') >> any_char; 506 single_string_inner = '\\' >> set("'\\") | not_('\'') >> any_char;
468 SingleString = '\'' >> *single_string_inner >> '\''; 507 SingleString = '\'' >> *single_string_inner >> '\'';
@@ -495,7 +534,7 @@ YueParser::YueParser() {
495 LuaString = LuaStringOpen >> -line_break >> LuaStringContent >> LuaStringClose; 534 LuaString = LuaStringOpen >> -line_break >> LuaStringContent >> LuaStringClose;
496 535
497 Parens = '(' >> *space_break >> space >> Exp >> *space_break >> space >> ')'; 536 Parens = '(' >> *space_break >> space >> Exp >> *space_break >> space >> ')';
498 Callable = Variable | SelfItem | MacroName | VarArg | Parens; 537 Callable = Variable | SelfItem | MacroName | Parens;
499 fn_args_exp_list = space >> Exp >> space >> *((line_break | ',') >> white >> Exp); 538 fn_args_exp_list = space >> Exp >> space >> *((line_break | ',') >> white >> Exp);
500 539
501 fn_args = 540 fn_args =
@@ -507,7 +546,7 @@ YueParser::YueParser() {
507 Metamethod = '<' >> space >> meta_index >> space >> '>'; 546 Metamethod = '<' >> space >> meta_index >> space >> '>';
508 547
509 ExistentialOp = '?' >> not_('?'); 548 ExistentialOp = '?' >> not_('?');
510 TableAppendingOp = "[]"; 549 TableAppendingOp = and_('[') >> ("[]" | brackets_expression_error);
511 chain_call = ( 550 chain_call = (
512 Callable >> -ExistentialOp >> -chain_items 551 Callable >> -ExistentialOp >> -chain_items
513 ) | ( 552 ) | (
@@ -736,8 +775,13 @@ YueParser::YueParser() {
736 775
737 ConstValue = (expr("nil") | "true" | "false") >> not_alpha_num; 776 ConstValue = (expr("nil") | "true" | "false") >> not_alpha_num;
738 777
739 braces_expression_error = pl::user("{", [](const item_t& item) { 778 braces_expression_error = pl::user(true_(), [](const item_t& item) {
740 throw ParserError("invalid brace expression", *item.begin, *item.end); 779 throw ParserError("syntax error in brace expression", *item.begin, *item.end);
780 return false;
781 });
782
783 brackets_expression_error = pl::user(true_(), [](const item_t& item) {
784 throw ParserError("syntax error in bracket expression", *item.begin, *item.end);
741 return false; 785 return false;
742 }); 786 });
743 787
@@ -745,7 +789,7 @@ YueParser::YueParser() {
745 TableLit | ConstValue | If | Switch | Try | With | 789 TableLit | ConstValue | If | Switch | Try | With |
746 ClassDecl | ForEach | For | While | Do | 790 ClassDecl | ForEach | For | While | Do |
747 UnaryValue | TblComprehension | Comprehension | 791 UnaryValue | TblComprehension | Comprehension |
748 FunLit | Num; 792 FunLit | Num | VarArg;
749 793
750 ExpListAssign = ExpList >> -(space >> (Update | Assign)) >> not_(space >> '='); 794 ExpListAssign = ExpList >> -(space >> (Update | Assign)) >> not_(space >> '=');
751 795
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h
index c8fc17e..8e7f555 100644
--- a/src/yuescript/yue_parser.h
+++ b/src/yuescript/yue_parser.h
@@ -52,10 +52,23 @@ struct identity {
52 typedef T type; 52 typedef T type;
53}; 53};
54 54
55#define AST_RULE(type) \ 55#ifdef NDEBUG
56 rule type; \ 56 #define NONE_AST_RULE(type) \
57 ast<type##_t> type##_impl = type; \ 57 rule type;
58 inline rule& getRule(identity<type##_t>) { return type; } 58
59 #define AST_RULE(type) \
60 rule type; \
61 ast<type##_t> type##_impl = type; \
62 inline rule& getRule(identity<type##_t>) { return type; }
63#else // NDEBUG
64 #define NONE_AST_RULE(type) \
65 rule type{#type, rule::initTag{}};
66
67 #define AST_RULE(type) \
68 rule type{#type, rule::initTag{}}; \
69 ast<type##_t> type##_impl = type; \
70 inline rule& getRule(identity<type##_t>) { return type; }
71#endif // NDEBUG
59 72
60extern std::unordered_set<std::string> LuaKeywords; 73extern std::unordered_set<std::string> LuaKeywords;
61extern std::unordered_set<std::string> Keywords; 74extern std::unordered_set<std::string> Keywords;
@@ -92,6 +105,7 @@ protected:
92 bool exportMacro = false; 105 bool exportMacro = false;
93 int exportCount = 0; 106 int exportCount = 0;
94 int moduleFix = 0; 107 int moduleFix = 0;
108 int expLevel = 0;
95 size_t stringOpen = 0; 109 size_t stringOpen = 0;
96 std::string moduleName = "_module_0"s; 110 std::string moduleName = "_module_0"s;
97 std::string buffer; 111 std::string buffer;
@@ -99,6 +113,7 @@ protected:
99 std::stack<bool> noDoStack; 113 std::stack<bool> noDoStack;
100 std::stack<bool> noChainBlockStack; 114 std::stack<bool> noChainBlockStack;
101 std::stack<bool> noTableBlockStack; 115 std::stack<bool> noTableBlockStack;
116 std::stack<bool> noForStack;
102 }; 117 };
103 118
104 template <class T> 119 template <class T>
@@ -115,117 +130,124 @@ private:
115 return cut; 130 return cut;
116 } 131 }
117 132
118 rule empty_block_error; 133 NONE_AST_RULE(empty_block_error);
119 rule leading_spaces_error; 134 NONE_AST_RULE(leading_spaces_error);
120 rule indentation_error; 135 NONE_AST_RULE(indentation_error);
121 rule braces_expression_error; 136 NONE_AST_RULE(braces_expression_error);
137 NONE_AST_RULE(brackets_expression_error);
138
139 NONE_AST_RULE(inc_exp_level);
140 NONE_AST_RULE(dec_exp_level);
122 141
123 rule num_char; 142 NONE_AST_RULE(num_char);
124 rule num_char_hex; 143 NONE_AST_RULE(num_char_hex);
125 rule num_lit; 144 NONE_AST_RULE(num_lit);
126 rule num_expo; 145 NONE_AST_RULE(num_expo);
127 rule num_expo_hex; 146 NONE_AST_RULE(num_expo_hex);
128 rule lj_num; 147 NONE_AST_RULE(lj_num);
129 rule plain_space; 148 NONE_AST_RULE(plain_space);
130 rule line_break; 149 NONE_AST_RULE(line_break);
131 rule any_char; 150 NONE_AST_RULE(any_char);
132 rule white; 151 NONE_AST_RULE(white);
133 rule stop; 152 NONE_AST_RULE(stop);
134 rule comment; 153 NONE_AST_RULE(comment);
135 rule multi_line_open; 154 NONE_AST_RULE(multi_line_open);
136 rule multi_line_close; 155 NONE_AST_RULE(multi_line_close);
137 rule multi_line_content; 156 NONE_AST_RULE(multi_line_content);
138 rule multi_line_comment; 157 NONE_AST_RULE(multi_line_comment);
139 rule escape_new_line; 158 NONE_AST_RULE(escape_new_line);
140 rule space_one; 159 NONE_AST_RULE(space_one);
141 rule space; 160 NONE_AST_RULE(space);
142 rule space_break; 161 NONE_AST_RULE(space_break);
143 rule alpha_num; 162 NONE_AST_RULE(alpha_num);
144 rule not_alpha_num; 163 NONE_AST_RULE(not_alpha_num);
145 rule cut; 164 NONE_AST_RULE(cut);
146 rule check_indent_match; 165 NONE_AST_RULE(check_indent_match);
147 rule check_indent; 166 NONE_AST_RULE(check_indent);
148 rule advance_match; 167 NONE_AST_RULE(advance_match);
149 rule advance; 168 NONE_AST_RULE(advance);
150 rule push_indent_match; 169 NONE_AST_RULE(push_indent_match);
151 rule push_indent; 170 NONE_AST_RULE(push_indent);
152 rule prevent_indent; 171 NONE_AST_RULE(prevent_indent);
153 rule pop_indent; 172 NONE_AST_RULE(pop_indent);
154 rule in_block; 173 NONE_AST_RULE(in_block);
155 rule import_name; 174 NONE_AST_RULE(import_name);
156 rule import_name_list; 175 NONE_AST_RULE(import_name_list);
157 rule import_literal_chain; 176 NONE_AST_RULE(import_literal_chain);
158 rule import_tab_item; 177 NONE_AST_RULE(import_tab_item);
159 rule import_tab_list; 178 NONE_AST_RULE(import_tab_list);
160 rule import_tab_line; 179 NONE_AST_RULE(import_tab_line);
161 rule import_tab_lines; 180 NONE_AST_RULE(import_tab_lines);
162 rule with_exp; 181 NONE_AST_RULE(with_exp);
163 rule disable_do; 182 NONE_AST_RULE(disable_do);
164 rule enable_do; 183 NONE_AST_RULE(enable_do);
165 rule disable_chain; 184 NONE_AST_RULE(disable_chain);
166 rule enable_chain; 185 NONE_AST_RULE(enable_chain);
167 rule disable_do_chain_arg_table_block; 186 NONE_AST_RULE(disable_do_chain_arg_table_block);
168 rule enable_do_chain_arg_table_block; 187 NONE_AST_RULE(enable_do_chain_arg_table_block);
169 rule disable_arg_table_block; 188 NONE_AST_RULE(disable_arg_table_block);
170 rule enable_arg_table_block; 189 NONE_AST_RULE(enable_arg_table_block);
171 rule switch_else; 190 NONE_AST_RULE(disable_for);
172 rule switch_block; 191 NONE_AST_RULE(enable_for);
173 rule if_else_if; 192 NONE_AST_RULE(switch_else);
174 rule if_else; 193 NONE_AST_RULE(switch_block);
175 rule for_args; 194 NONE_AST_RULE(if_else_if);
176 rule for_in; 195 NONE_AST_RULE(if_else);
177 rule comp_clause; 196 NONE_AST_RULE(for_key);
178 rule chain; 197 NONE_AST_RULE(for_args);
179 rule chain_list; 198 NONE_AST_RULE(for_in);
180 rule key_value; 199 NONE_AST_RULE(comp_clause);
181 rule single_string_inner; 200 NONE_AST_RULE(chain);
182 rule interp; 201 NONE_AST_RULE(chain_list);
183 rule double_string_plain; 202 NONE_AST_RULE(key_value);
184 rule lua_string_open; 203 NONE_AST_RULE(single_string_inner);
185 rule lua_string_close; 204 NONE_AST_RULE(interp);
186 rule fn_args_exp_list; 205 NONE_AST_RULE(double_string_plain);
187 rule fn_args; 206 NONE_AST_RULE(lua_string_open);
188 rule destruct_def; 207 NONE_AST_RULE(lua_string_close);
189 rule macro_args_def; 208 NONE_AST_RULE(fn_args_exp_list);
190 rule chain_call; 209 NONE_AST_RULE(fn_args);
191 rule chain_call_list; 210 NONE_AST_RULE(destruct_def);
192 rule chain_index_chain; 211 NONE_AST_RULE(macro_args_def);
193 rule chain_items; 212 NONE_AST_RULE(chain_call);
194 rule chain_dot_chain; 213 NONE_AST_RULE(chain_call_list);
195 rule colon_chain; 214 NONE_AST_RULE(chain_index_chain);
196 rule chain_with_colon; 215 NONE_AST_RULE(chain_items);
197 rule chain_item; 216 NONE_AST_RULE(chain_dot_chain);
198 rule chain_line; 217 NONE_AST_RULE(colon_chain);
199 rule chain_block; 218 NONE_AST_RULE(chain_with_colon);
200 rule meta_index; 219 NONE_AST_RULE(chain_item);
201 rule index; 220 NONE_AST_RULE(chain_line);
202 rule invoke_chain; 221 NONE_AST_RULE(chain_block);
203 rule table_value; 222 NONE_AST_RULE(meta_index);
204 rule table_lit_lines; 223 NONE_AST_RULE(index);
205 rule table_lit_line; 224 NONE_AST_RULE(invoke_chain);
206 rule table_value_list; 225 NONE_AST_RULE(table_value);
207 rule table_block_inner; 226 NONE_AST_RULE(table_lit_lines);
208 rule class_line; 227 NONE_AST_RULE(table_lit_line);
209 rule key_value_line; 228 NONE_AST_RULE(table_value_list);
210 rule key_value_list; 229 NONE_AST_RULE(table_block_inner);
211 rule arg_line; 230 NONE_AST_RULE(class_line);
212 rule arg_block; 231 NONE_AST_RULE(key_value_line);
213 rule invoke_args_with_table; 232 NONE_AST_RULE(key_value_list);
214 rule arg_table_block; 233 NONE_AST_RULE(arg_line);
215 rule pipe_operator; 234 NONE_AST_RULE(arg_block);
216 rule exponential_operator; 235 NONE_AST_RULE(invoke_args_with_table);
217 rule pipe_value; 236 NONE_AST_RULE(arg_table_block);
218 rule pipe_exp; 237 NONE_AST_RULE(pipe_operator);
219 rule expo_value; 238 NONE_AST_RULE(exponential_operator);
220 rule expo_exp; 239 NONE_AST_RULE(pipe_value);
221 rule exp_not_tab; 240 NONE_AST_RULE(pipe_exp);
222 rule local_const_item; 241 NONE_AST_RULE(expo_value);
223 rule empty_line_break; 242 NONE_AST_RULE(expo_exp);
224 rule yue_comment; 243 NONE_AST_RULE(exp_not_tab);
225 rule yue_line_comment; 244 NONE_AST_RULE(local_const_item);
226 rule yue_multiline_comment; 245 NONE_AST_RULE(empty_line_break);
227 rule line; 246 NONE_AST_RULE(yue_comment);
228 rule shebang; 247 NONE_AST_RULE(yue_line_comment);
248 NONE_AST_RULE(yue_multiline_comment);
249 NONE_AST_RULE(line);
250 NONE_AST_RULE(shebang);
229 251
230 AST_RULE(Num) 252 AST_RULE(Num)
231 AST_RULE(Name) 253 AST_RULE(Name)