diff options
author | Li Jin <dragon-fly@qq.com> | 2022-02-14 15:35:54 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2022-02-14 15:35:54 +0800 |
commit | ddb0b9deb720368a425d00bce0c0352469b55911 (patch) | |
tree | 8924f0a6e4d851c2f8545efba2d42c43581fd090 | |
parent | 2c2cad4b4d3680bb30474b38ebed0f938e82636e (diff) | |
download | yuescript-ddb0b9deb720368a425d00bce0c0352469b55911.tar.gz yuescript-ddb0b9deb720368a425d00bce0c0352469b55911.tar.bz2 yuescript-ddb0b9deb720368a425d00bce0c0352469b55911.zip |
fixing issue #77. change table appending syntax to: tb[] = 1
-rw-r--r-- | spec/inputs/syntax.yue | 17 | ||||
-rw-r--r-- | spec/outputs/syntax.lua | 34 | ||||
-rwxr-xr-x | src/yuescript/yue_ast.h | 5 | ||||
-rwxr-xr-x | src/yuescript/yue_compiler.cpp | 193 | ||||
-rwxr-xr-x | src/yuescript/yue_parser.cpp | 6 | ||||
-rwxr-xr-x | src/yuescript/yue_parser.h | 1 |
6 files changed, 147 insertions, 109 deletions
diff --git a/spec/inputs/syntax.yue b/spec/inputs/syntax.yue index 67d3a27..e7f0a8d 100644 --- a/spec/inputs/syntax.yue +++ b/spec/inputs/syntax.yue | |||
@@ -188,16 +188,25 @@ a.b[1].c[2 + 3] += 1 | |||
188 | with tb | 188 | with tb |
189 | .a.c += 1 | 189 | .a.c += 1 |
190 | 190 | ||
191 | tb #= 10 | 191 | tb[] = 10 |
192 | a.b.c #= 1 | 192 | a.b.c[] = 1 |
193 | x #= if v | 193 | x[] = if v |
194 | 1 | 194 | 1 |
195 | else | 195 | else |
196 | 2 | 196 | 2 |
197 | with tb | 197 | with tb |
198 | .b.c #= with vec | 198 | .b.c[] = with vec |
199 | .x = 1 | 199 | .x = 1 |
200 | .y = 2 | 200 | .y = 2 |
201 | a | ||
202 | .b.c | ||
203 | .d\f! | ||
204 | .g[] = 1 | ||
205 | |||
206 | tb = {} | ||
207 | tb[] = 1 | ||
208 | tb[] = 2 | ||
209 | tb[] = 3 | ||
201 | 210 | ||
202 | x = 0 | 211 | x = 0 |
203 | _ = (if ntype(v) == "fndef" then x += 1) for v in *values | 212 | _ = (if ntype(v) == "fndef" then x += 1) for v in *values |
diff --git a/spec/outputs/syntax.lua b/spec/outputs/syntax.lua index 457f1e1..701361e 100644 --- a/spec/outputs/syntax.lua +++ b/spec/outputs/syntax.lua | |||
@@ -195,10 +195,14 @@ do | |||
195 | local _obj_2 = _with_0.a | 195 | local _obj_2 = _with_0.a |
196 | _obj_2.c = _obj_2.c + 1 | 196 | _obj_2.c = _obj_2.c + 1 |
197 | end | 197 | end |
198 | local _obj_2 = tb | 198 | do |
199 | _obj_2[#_obj_2 + 1] = 10 | 199 | local _obj_2 = tb |
200 | local _obj_3 = a.b.c | 200 | _obj_2[#_obj_2 + 1] = 10 |
201 | _obj_3[#_obj_3 + 1] = 1 | 201 | end |
202 | do | ||
203 | local _obj_2 = a.b.c | ||
204 | _obj_2[#_obj_2 + 1] = 1 | ||
205 | end | ||
202 | if v then | 206 | if v then |
203 | x[#x + 1] = 1 | 207 | x[#x + 1] = 1 |
204 | else | 208 | else |
@@ -206,14 +210,24 @@ else | |||
206 | end | 210 | end |
207 | do | 211 | do |
208 | local _with_0 = tb | 212 | local _with_0 = tb |
209 | local _obj_4 = _with_0.b.c | ||
210 | do | 213 | do |
211 | local _with_1 = vec | 214 | local _obj_2 = _with_0.b.c |
212 | _with_1.x = 1 | 215 | do |
213 | _with_1.y = 2 | 216 | local _with_1 = vec |
214 | _obj_4[#_obj_4 + 1] = _with_1 | 217 | _with_1.x = 1 |
218 | _with_1.y = 2 | ||
219 | _obj_2[#_obj_2 + 1] = _with_1 | ||
220 | end | ||
215 | end | 221 | end |
216 | end | 222 | end |
223 | do | ||
224 | local _obj_2 = a.b.c.d:f().g | ||
225 | _obj_2[#_obj_2 + 1] = 1 | ||
226 | end | ||
227 | local tb = { } | ||
228 | tb[#tb + 1] = 1 | ||
229 | tb[#tb + 1] = 2 | ||
230 | tb[#tb + 1] = 3 | ||
217 | x = 0 | 231 | x = 0 |
218 | local _list_0 = values | 232 | local _list_0 = values |
219 | for _index_0 = 1, #_list_0 do | 233 | for _index_0 = 1, #_list_0 do |
@@ -231,7 +245,7 @@ hello = { | |||
231 | ["function"] = "okay", | 245 | ["function"] = "okay", |
232 | good = 230203 | 246 | good = 230203 |
233 | } | 247 | } |
234 | local tb = { | 248 | tb = { |
235 | ["do"] = b, | 249 | ["do"] = b, |
236 | (function() | 250 | (function() |
237 | return { | 251 | return { |
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 7762c91..79e35a5 100755 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
@@ -561,11 +561,14 @@ AST_END(Invoke) | |||
561 | AST_LEAF(existential_op) | 561 | AST_LEAF(existential_op) |
562 | AST_END(existential_op) | 562 | AST_END(existential_op) |
563 | 563 | ||
564 | AST_LEAF(table_appending_op) | ||
565 | AST_END(table_appending_op) | ||
566 | |||
564 | class InvokeArgs_t; | 567 | class InvokeArgs_t; |
565 | 568 | ||
566 | AST_NODE(ChainValue) | 569 | AST_NODE(ChainValue) |
567 | ast_ptr<true, Seperator_t> sep; | 570 | ast_ptr<true, Seperator_t> sep; |
568 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, existential_op_t> items; | 571 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, existential_op_t, table_appending_op_t> items; |
569 | AST_MEMBER(ChainValue, &sep, &items) | 572 | AST_MEMBER(ChainValue, &sep, &items) |
570 | AST_END(ChainValue) | 573 | AST_END(ChainValue) |
571 | 574 | ||
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 6617ec5..6bc9fe8 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -60,7 +60,7 @@ using namespace parserlib; | |||
60 | 60 | ||
61 | typedef std::list<std::string> str_list; | 61 | typedef std::list<std::string> str_list; |
62 | 62 | ||
63 | const std::string_view version = "0.9.9"sv; | 63 | const std::string_view version = "0.9.10"sv; |
64 | const std::string_view extension = "yue"sv; | 64 | const std::string_view extension = "yue"sv; |
65 | 65 | ||
66 | class YueCompilerImpl { | 66 | class YueCompilerImpl { |
@@ -809,6 +809,7 @@ private: | |||
809 | switch (lastItem->getId()) { | 809 | switch (lastItem->getId()) { |
810 | case id<DotChainItem_t>(): | 810 | case id<DotChainItem_t>(): |
811 | case id<Exp_t>(): | 811 | case id<Exp_t>(): |
812 | case id<table_appending_op_t>(): | ||
812 | return true; | 813 | return true; |
813 | } | 814 | } |
814 | } | 815 | } |
@@ -1212,25 +1213,52 @@ private: | |||
1212 | BREAK_IF(!value); | 1213 | BREAK_IF(!value); |
1213 | auto chainValue = value->item.as<ChainValue_t>(); | 1214 | auto chainValue = value->item.as<ChainValue_t>(); |
1214 | BREAK_IF(!chainValue); | 1215 | BREAK_IF(!chainValue); |
1215 | auto dot = ast_cast<DotChainItem_t>(chainValue->items.back()); | 1216 | str_list temp; |
1216 | BREAK_IF(!dot); | 1217 | if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) { |
1217 | BREAK_IF(!dot->name.is<Metatable_t>()); | 1218 | BREAK_IF(!dot->name.is<Metatable_t>()); |
1218 | str_list args; | 1219 | str_list args; |
1219 | chainValue->items.pop_back(); | 1220 | chainValue->items.pop_back(); |
1220 | if (chainValue->items.empty()) { | 1221 | if (chainValue->items.empty()) { |
1221 | if (_withVars.empty()) { | 1222 | if (_withVars.empty()) { |
1222 | throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x)); | 1223 | throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x)); |
1224 | } else { | ||
1225 | args.push_back(_withVars.top()); | ||
1226 | } | ||
1223 | } else { | 1227 | } else { |
1224 | args.push_back(_withVars.top()); | 1228 | transformExp(static_cast<Exp_t*>(*it), args, ExpUsage::Closure); |
1225 | } | 1229 | } |
1226 | } else { | 1230 | if (vit != values.end()) transformAssignItem(*vit, args); |
1227 | transformExp(static_cast<Exp_t*>(*it), args, ExpUsage::Closure); | 1231 | else args.push_back("nil"s); |
1228 | } | 1232 | _buf << indent() << globalVar("setmetatable"sv, x) << '(' << join(args, ", "sv) << ')' << nll(x); |
1229 | if (vit != values.end()) transformAssignItem(*vit, args); | 1233 | temp.push_back(clearBuf()); |
1230 | else args.push_back("nil"s); | 1234 | } else if (ast_is<table_appending_op_t>(chainValue->items.back())) { |
1231 | _buf << indent() << globalVar("setmetatable"sv, x) << '(' << join(args, ", "sv) << ')' << nll(x); | 1235 | chainValue->items.pop_back(); |
1232 | str_list temp; | 1236 | auto varName = singleVariableFrom(chainValue); |
1233 | temp.push_back(clearBuf()); | 1237 | bool isScoped = false; |
1238 | if (varName.empty() || !isLocal(varName)) { | ||
1239 | isScoped = true; | ||
1240 | temp.push_back(indent() + "do"s + nll(x)); | ||
1241 | pushScope(); | ||
1242 | auto objVar = getUnusedName("_obj_"sv); | ||
1243 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
1244 | newAssignment->expList.set(toAst<ExpList_t>(objVar, x)); | ||
1245 | auto assign = x->new_ptr<Assign_t>(); | ||
1246 | assign->values.push_back(*it); | ||
1247 | newAssignment->action.set(assign); | ||
1248 | transformAssignment(newAssignment, temp); | ||
1249 | varName = objVar; | ||
1250 | } | ||
1251 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
1252 | newAssignment->expList.set(toAst<ExpList_t>(varName + "[#"s + varName + "+1]"s, x)); | ||
1253 | auto assign = x->new_ptr<Assign_t>(); | ||
1254 | assign->values.push_back(*vit); | ||
1255 | newAssignment->action.set(assign); | ||
1256 | transformAssignment(newAssignment, temp); | ||
1257 | if (isScoped) { | ||
1258 | popScope(); | ||
1259 | temp.push_back(indent() + "end"s + nlr(x)); | ||
1260 | } | ||
1261 | } else break; | ||
1234 | auto newExpList = x->new_ptr<ExpList_t>(); | 1262 | auto newExpList = x->new_ptr<ExpList_t>(); |
1235 | auto newAssign = x->new_ptr<Assign_t>(); | 1263 | auto newAssign = x->new_ptr<Assign_t>(); |
1236 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | 1264 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); |
@@ -1243,7 +1271,7 @@ private: | |||
1243 | if (value != *vit) newAssign->values.push_back(value); | 1271 | if (value != *vit) newAssign->values.push_back(value); |
1244 | } | 1272 | } |
1245 | if (newExpList->exprs.empty() && newAssign->values.empty()) { | 1273 | if (newExpList->exprs.empty() && newAssign->values.empty()) { |
1246 | out.push_back(temp.back()); | 1274 | out.push_back(join(temp)); |
1247 | return; | 1275 | return; |
1248 | } | 1276 | } |
1249 | if (newExpList->exprs.size() < newAssign->values.size()) { | 1277 | if (newExpList->exprs.size() < newAssign->values.size()) { |
@@ -2016,81 +2044,67 @@ private: | |||
2016 | if (!leftValue) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, leftExp)); | 2044 | if (!leftValue) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, leftExp)); |
2017 | auto chain = leftValue->item.as<ChainValue_t>(); | 2045 | auto chain = leftValue->item.as<ChainValue_t>(); |
2018 | if (!chain) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, chain)); | 2046 | if (!chain) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, chain)); |
2019 | auto op = _parser.toString(update->op); | 2047 | BLOCK_START |
2020 | { | 2048 | { |
2021 | auto dot = ast_cast<DotChainItem_t>(chain->items.back()); | 2049 | auto dot = ast_cast<DotChainItem_t>(chain->items.back()); |
2022 | if (dot && dot->name.is<Metatable_t>()) { | 2050 | if (dot && dot->name.is<Metatable_t>()) { |
2023 | throw std::logic_error(_info.errorMessage("can not apply update to a metatable"sv, leftExp)); | 2051 | throw std::logic_error(_info.errorMessage("can not apply update to a metatable"sv, leftExp)); |
2024 | } | 2052 | } |
2025 | BLOCK_START | 2053 | BREAK_IF(chain->items.size() < 2); |
2026 | if (op == "#"sv) { | 2054 | if (chain->items.size() == 2) { |
2027 | auto varName = singleVariableFrom(chain); | 2055 | if (auto callable = ast_cast<Callable_t>(chain->items.front())) { |
2028 | BREAK_IF(!varName.empty() && isLocal(varName)); | 2056 | ast_node* var = callable->item.as<Variable_t>(); |
2029 | auto objVar = getUnusedName("_obj_"sv); | 2057 | if (auto self = callable->item.as<SelfName_t>()) { |
2030 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | 2058 | var = self->name.as<self_t>(); |
2031 | newAssignment->expList.set(toAst<ExpList_t>(objVar, x)); | ||
2032 | auto assign = x->new_ptr<Assign_t>(); | ||
2033 | assign->values.push_back(leftExp); | ||
2034 | newAssignment->action.set(assign); | ||
2035 | transformAssignment(newAssignment, temp); | ||
2036 | chain->items.clear(); | ||
2037 | chain->items.push_back(toAst<Callable_t>(objVar, x)); | ||
2038 | } else { | ||
2039 | BREAK_IF(chain->items.size() < 2); | ||
2040 | if (chain->items.size() == 2) { | ||
2041 | if (auto callable = ast_cast<Callable_t>(chain->items.front())) { | ||
2042 | ast_node* var = callable->item.as<Variable_t>(); | ||
2043 | if (auto self = callable->item.as<SelfName_t>()) { | ||
2044 | var = self->name.as<self_t>(); | ||
2045 | } | ||
2046 | BREAK_IF(var && isLocal(_parser.toString(var))); | ||
2047 | } | 2059 | } |
2060 | BREAK_IF(var && isLocal(_parser.toString(var))); | ||
2048 | } | 2061 | } |
2049 | auto tmpChain = x->new_ptr<ChainValue_t>(); | ||
2050 | ast_ptr<false, ast_node> ptr(chain->items.back()); | ||
2051 | for (auto item : chain->items.objects()) { | ||
2052 | if (item != ptr) { | ||
2053 | tmpChain->items.push_back(item); | ||
2054 | } | ||
2055 | } | ||
2056 | auto value = x->new_ptr<Value_t>(); | ||
2057 | value->item.set(tmpChain); | ||
2058 | auto exp = newExp(value, x); | ||
2059 | auto objVar = getUnusedName("_obj_"sv); | ||
2060 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
2061 | newAssignment->expList.set(toAst<ExpList_t>(objVar, x)); | ||
2062 | auto assign = x->new_ptr<Assign_t>(); | ||
2063 | assign->values.push_back(exp); | ||
2064 | newAssignment->action.set(assign); | ||
2065 | transformAssignment(newAssignment, temp); | ||
2066 | chain->items.clear(); | ||
2067 | chain->items.push_back(toAst<Callable_t>(objVar, x)); | ||
2068 | chain->items.push_back(ptr); | ||
2069 | } | 2062 | } |
2070 | BLOCK_END | ||
2071 | auto tmpChain = x->new_ptr<ChainValue_t>(); | 2063 | auto tmpChain = x->new_ptr<ChainValue_t>(); |
2064 | ast_ptr<false, ast_node> ptr(chain->items.back()); | ||
2072 | for (auto item : chain->items.objects()) { | 2065 | for (auto item : chain->items.objects()) { |
2073 | bool itemAdded = false; | 2066 | if (item != ptr) { |
2074 | BLOCK_START | 2067 | tmpChain->items.push_back(item); |
2075 | auto exp = ast_cast<Exp_t>(item); | 2068 | } |
2076 | BREAK_IF(!exp); | ||
2077 | auto var = singleVariableFrom(exp); | ||
2078 | BREAK_IF(!var.empty()); | ||
2079 | auto upVar = getUnusedName("_update_"sv); | ||
2080 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
2081 | newAssignment->expList.set(toAst<ExpList_t>(upVar, x)); | ||
2082 | auto assign = x->new_ptr<Assign_t>(); | ||
2083 | assign->values.push_back(exp); | ||
2084 | newAssignment->action.set(assign); | ||
2085 | transformAssignment(newAssignment, temp); | ||
2086 | tmpChain->items.push_back(toAst<Exp_t>(upVar, x)); | ||
2087 | itemAdded = true; | ||
2088 | BLOCK_END | ||
2089 | if (!itemAdded) tmpChain->items.push_back(item); | ||
2090 | } | 2069 | } |
2070 | auto value = x->new_ptr<Value_t>(); | ||
2071 | value->item.set(tmpChain); | ||
2072 | auto exp = newExp(value, x); | ||
2073 | auto objVar = getUnusedName("_obj_"sv); | ||
2074 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
2075 | newAssignment->expList.set(toAst<ExpList_t>(objVar, x)); | ||
2076 | auto assign = x->new_ptr<Assign_t>(); | ||
2077 | assign->values.push_back(exp); | ||
2078 | newAssignment->action.set(assign); | ||
2079 | transformAssignment(newAssignment, temp); | ||
2091 | chain->items.clear(); | 2080 | chain->items.clear(); |
2092 | chain->items.dup(tmpChain->items); | 2081 | chain->items.push_back(toAst<Callable_t>(objVar, x)); |
2082 | chain->items.push_back(ptr); | ||
2093 | } | 2083 | } |
2084 | BLOCK_END | ||
2085 | auto tmpChain = x->new_ptr<ChainValue_t>(); | ||
2086 | for (auto item : chain->items.objects()) { | ||
2087 | bool itemAdded = false; | ||
2088 | BLOCK_START | ||
2089 | auto exp = ast_cast<Exp_t>(item); | ||
2090 | BREAK_IF(!exp); | ||
2091 | auto var = singleVariableFrom(exp); | ||
2092 | BREAK_IF(!var.empty()); | ||
2093 | auto upVar = getUnusedName("_update_"sv); | ||
2094 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
2095 | newAssignment->expList.set(toAst<ExpList_t>(upVar, x)); | ||
2096 | auto assign = x->new_ptr<Assign_t>(); | ||
2097 | assign->values.push_back(exp); | ||
2098 | newAssignment->action.set(assign); | ||
2099 | transformAssignment(newAssignment, temp); | ||
2100 | tmpChain->items.push_back(toAst<Exp_t>(upVar, x)); | ||
2101 | itemAdded = true; | ||
2102 | BLOCK_END | ||
2103 | if (!itemAdded) tmpChain->items.push_back(item); | ||
2104 | } | ||
2105 | chain->items.clear(); | ||
2106 | chain->items.dup(tmpChain->items); | ||
2107 | auto op = _parser.toString(update->op); | ||
2094 | if (op == "??"sv) { | 2108 | if (op == "??"sv) { |
2095 | auto defs = getPredefine(assignment); | 2109 | auto defs = getPredefine(assignment); |
2096 | auto rightExp = x->new_ptr<Exp_t>(); | 2110 | auto rightExp = x->new_ptr<Exp_t>(); |
@@ -2101,16 +2115,6 @@ private: | |||
2101 | if (!defs.empty()) temp.back().insert(0, defs + nll(x)); | 2115 | if (!defs.empty()) temp.back().insert(0, defs + nll(x)); |
2102 | out.push_back(join(temp)); | 2116 | out.push_back(join(temp)); |
2103 | return; | 2117 | return; |
2104 | } else if (op == "#"sv) { | ||
2105 | auto left = _parser.toString(chain->items.front()); | ||
2106 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
2107 | newAssignment->expList.set(toAst<ExpList_t>(left + "[#"s + left + "+1]"s, x)); | ||
2108 | auto assign = x->new_ptr<Assign_t>(); | ||
2109 | assign->values.push_back(update->value); | ||
2110 | newAssignment->action.set(assign); | ||
2111 | transformAssignment(newAssignment, temp); | ||
2112 | out.push_back(join(temp)); | ||
2113 | return; | ||
2114 | } | 2118 | } |
2115 | auto defs = getPredefine(assignment); | 2119 | auto defs = getPredefine(assignment); |
2116 | transformValue(leftValue, temp); | 2120 | transformValue(leftValue, temp); |
@@ -3970,6 +3974,9 @@ private: | |||
3970 | temp.back() = (temp.back().front() == '[' ? "[ "s : "["s) + temp.back() + ']'; | 3974 | temp.back() = (temp.back().front() == '[' ? "[ "s : "["s) + temp.back() + ']'; |
3971 | break; | 3975 | break; |
3972 | case id<InvokeArgs_t>(): transformInvokeArgs(static_cast<InvokeArgs_t*>(item), temp); break; | 3976 | case id<InvokeArgs_t>(): transformInvokeArgs(static_cast<InvokeArgs_t*>(item), temp); break; |
3977 | case id<table_appending_op_t>(): | ||
3978 | transform_table_appending_op(static_cast<table_appending_op_t*>(item), temp); | ||
3979 | break; | ||
3973 | default: YUEE("AST node mismatch", item); break; | 3980 | default: YUEE("AST node mismatch", item); break; |
3974 | } | 3981 | } |
3975 | } | 3982 | } |
@@ -4391,6 +4398,10 @@ private: | |||
4391 | throw std::logic_error(_info.errorMessage("slice syntax not supported here"sv, slice)); | 4398 | throw std::logic_error(_info.errorMessage("slice syntax not supported here"sv, slice)); |
4392 | } | 4399 | } |
4393 | 4400 | ||
4401 | void transform_table_appending_op(table_appending_op_t* op, str_list&) { | ||
4402 | throw std::logic_error(_info.errorMessage("table appending syntax not supported here"sv, op)); | ||
4403 | } | ||
4404 | |||
4394 | void transformInvoke(Invoke_t* invoke, str_list& out) { | 4405 | void transformInvoke(Invoke_t* invoke, str_list& out) { |
4395 | str_list temp; | 4406 | str_list temp; |
4396 | for (auto arg : invoke->args.objects()) { | 4407 | for (auto arg : invoke->args.objects()) { |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 772ae08..3d12190 100755 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
@@ -324,8 +324,7 @@ YueParser::YueParser() { | |||
324 | expr("|") | | 324 | expr("|") | |
325 | expr(">>") | | 325 | expr(">>") | |
326 | expr("<<") | | 326 | expr("<<") | |
327 | expr("??") | | 327 | expr("??"); |
328 | expr("#"); | ||
329 | 328 | ||
330 | Update = Space >> update_op >> expr("=") >> Exp; | 329 | Update = Space >> update_op >> expr("=") >> Exp; |
331 | 330 | ||
@@ -382,7 +381,7 @@ YueParser::YueParser() { | |||
382 | return st->chainBlockStack.empty() || st->chainBlockStack.top(); | 381 | return st->chainBlockStack.empty() || st->chainBlockStack.top(); |
383 | }) >> +SpaceBreak >> Advance >> ensure( | 382 | }) >> +SpaceBreak >> Advance >> ensure( |
384 | chain_line >> *(+SpaceBreak >> chain_line), PopIndent); | 383 | chain_line >> *(+SpaceBreak >> chain_line), PopIndent); |
385 | ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -(InvokeArgs | chain_block); | 384 | ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -(InvokeArgs | chain_block) >> -table_appending_op; |
386 | 385 | ||
387 | simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue); | 386 | simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue); |
388 | Value = SimpleValue | simple_table | ChainValue | String; | 387 | Value = SimpleValue | simple_table | ChainValue | String; |
@@ -427,6 +426,7 @@ YueParser::YueParser() { | |||
427 | Metamethod = Name >> expr('#'); | 426 | Metamethod = Name >> expr('#'); |
428 | 427 | ||
429 | existential_op = expr('?') >> not_(expr('?')); | 428 | existential_op = expr('?') >> not_(expr('?')); |
429 | table_appending_op = expr("[]"); | ||
430 | chain_call = (Callable | String) >> -existential_op >> ChainItems; | 430 | chain_call = (Callable | String) >> -existential_op >> ChainItems; |
431 | chain_item = and_(set(".\\")) >> ChainItems; | 431 | chain_item = and_(set(".\\")) >> ChainItems; |
432 | chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems; | 432 | chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems; |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index e128e82..7dea126 100755 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
@@ -277,6 +277,7 @@ private: | |||
277 | AST_RULE(Slice) | 277 | AST_RULE(Slice) |
278 | AST_RULE(Invoke) | 278 | AST_RULE(Invoke) |
279 | AST_RULE(existential_op) | 279 | AST_RULE(existential_op) |
280 | AST_RULE(table_appending_op) | ||
280 | AST_RULE(TableLit) | 281 | AST_RULE(TableLit) |
281 | AST_RULE(TableBlock) | 282 | AST_RULE(TableBlock) |
282 | AST_RULE(TableBlockIndent) | 283 | AST_RULE(TableBlockIndent) |