diff options
Diffstat (limited to '')
| -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) |
