diff options
author | Li Jin <dragon-fly@qq.com> | 2023-01-29 10:29:19 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2023-01-29 10:29:19 +0800 |
commit | e10b1b163a9a173f32b956bf1fb9be00194352b5 (patch) | |
tree | 4692fe729bbb588c0565ce78426c932e8b360f22 | |
parent | 32f2a579ec15e6204e44d67ab2b8b4a1796e9a84 (diff) | |
download | yuescript-e10b1b163a9a173f32b956bf1fb9be00194352b5.tar.gz yuescript-e10b1b163a9a173f32b956bf1fb9be00194352b5.tar.bz2 yuescript-e10b1b163a9a173f32b956bf1fb9be00194352b5.zip |
fix cases from issue #120.
-rw-r--r-- | spec/inputs/loops.yue | 6 | ||||
-rw-r--r-- | spec/inputs/return.yue | 2 | ||||
-rw-r--r-- | spec/outputs/5.1/loops.lua | 3 | ||||
-rw-r--r-- | spec/outputs/loops.lua | 3 | ||||
-rw-r--r-- | src/yuescript/parser.cpp | 12 | ||||
-rw-r--r-- | src/yuescript/parser.hpp | 14 | ||||
-rw-r--r-- | src/yuescript/yue_ast.h | 4 | ||||
-rw-r--r-- | src/yuescript/yue_compiler.cpp | 54 | ||||
-rw-r--r-- | src/yuescript/yue_parser.cpp | 64 | ||||
-rw-r--r-- | src/yuescript/yue_parser.h | 250 |
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 | |||
75 | i = 0 | 75 | i = 0 |
76 | x = while i < 10 | 76 | x = 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 | ||
81 | x = for thing in *3 | 82 | x = for thing in *3 |
82 | y = "hello" | 83 | y = "hello" |
84 | break | ||
83 | 85 | ||
84 | x = for x=1,2 | 86 | x = 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 |
8 | do | 8 | do |
9 | return x for x in *things | 9 | for x in *things do return x |
10 | 10 | ||
11 | do | 11 | do |
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 | */ | ||
1225 | rule::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; | |||
450 | class MacroName_t; | 450 | class MacroName_t; |
451 | 451 | ||
452 | AST_NODE(Callable) | 452 | AST_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) |
455 | AST_END(Callable, "callable"sv) | 455 | AST_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) |
532 | AST_END(SimpleValue, "simple_value"sv) | 532 | AST_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 | ||
74 | const std::string_view version = "0.15.23"sv; | 74 | const std::string_view version = "0.15.24"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 { |
@@ -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 | ||
60 | extern std::unordered_set<std::string> LuaKeywords; | 73 | extern std::unordered_set<std::string> LuaKeywords; |
61 | extern std::unordered_set<std::string> Keywords; | 74 | extern 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) |