aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2022-04-01 17:47:27 +0800
committerLi Jin <dragon-fly@qq.com>2022-04-01 17:47:27 +0800
commitca1ed557769352c0ac0ca7804dd25e18c1fdf2e1 (patch)
treebf86d3990b90054f8d82aaf87cb9efae444a08ce
parent7be6c300256bfe411942a7ccc66f6bc3afa7390d (diff)
downloadyuescript-ca1ed557769352c0ac0ca7804dd25e18c1fdf2e1.tar.gz
yuescript-ca1ed557769352c0ac0ca7804dd25e18c1fdf2e1.tar.bz2
yuescript-ca1ed557769352c0ac0ca7804dd25e18c1fdf2e1.zip
fix some ambiguous syntax caused by arg table block.
-rw-r--r--spec/inputs/ambiguous.yue30
-rw-r--r--spec/inputs/syntax.yue9
-rw-r--r--spec/outputs/ambiguous.lua69
-rwxr-xr-xsrc/yuescript/yue_compiler.cpp14
-rwxr-xr-xsrc/yuescript/yue_parser.cpp40
-rwxr-xr-xsrc/yuescript/yue_parser.h8
6 files changed, 140 insertions, 30 deletions
diff --git a/spec/inputs/ambiguous.yue b/spec/inputs/ambiguous.yue
index 0e09979..3ae0bfc 100644
--- a/spec/inputs/ambiguous.yue
+++ b/spec/inputs/ambiguous.yue
@@ -28,4 +28,34 @@ do
28 global * 28 global *
29 $v! 29 $v!
30 30
31do
32 f
33 :v
34
35 tb = while f
36 :v
37
38 repeat
39 print v
40 until f
41 :v
42
43 with f
44 :v = tb
45 .x = 1
46
47 x = if f
48 :v
49
50 x = switch f
51 :v
52 when f
53 :v
54
55 nums = for num = 1, len
56 :num
57
58 objects = for item in *items
59 name: item
60
31nil 61nil
diff --git a/spec/inputs/syntax.yue b/spec/inputs/syntax.yue
index e7f0a8d..84c6578 100644
--- a/spec/inputs/syntax.yue
+++ b/spec/inputs/syntax.yue
@@ -267,11 +267,12 @@ z = x and b
267z = x andb 267z = x andb
268 268
269 269
270-- undelimited tables 270while 10 > something(
271 something: "world"
272 )
273 print "yeah"
271 274
272while 10 > something 275-- undelimited tables
273 something: "world"
274 print "yeah"
275 276
276x = 277x =
277 okay: sure 278 okay: sure
diff --git a/spec/outputs/ambiguous.lua b/spec/outputs/ambiguous.lua
index 6039d73..f96cee5 100644
--- a/spec/outputs/ambiguous.lua
+++ b/spec/outputs/ambiguous.lua
@@ -27,4 +27,73 @@ end
27do 27do
28 print(123) 28 print(123)
29end 29end
30do
31 f({
32 v = v
33 })
34 local tb
35 do
36 local _accum_0 = { }
37 local _len_0 = 1
38 while f do
39 _accum_0[_len_0] = {
40 v = v
41 }
42 _len_0 = _len_0 + 1
43 end
44 tb = _accum_0
45 end
46 repeat
47 print(v)
48 until f({
49 v = v
50 })
51 do
52 local _with_0 = f
53 local v = tb.v
54 _with_0.x = 1
55 end
56 local x
57 if f then
58 x = {
59 v = v
60 }
61 end
62 do
63 local _exp_0 = f({
64 v = v
65 })
66 if f == _exp_0 then
67 x = {
68 v = v
69 }
70 end
71 end
72 local nums
73 do
74 local _accum_0 = { }
75 local _len_0 = 1
76 for num = 1, len do
77 _accum_0[_len_0] = {
78 num = num
79 }
80 _len_0 = _len_0 + 1
81 end
82 nums = _accum_0
83 end
84 local objects
85 do
86 local _accum_0 = { }
87 local _len_0 = 1
88 local _list_0 = items
89 for _index_0 = 1, #_list_0 do
90 local item = _list_0[_index_0]
91 _accum_0[_len_0] = {
92 name = item
93 }
94 _len_0 = _len_0 + 1
95 end
96 objects = _accum_0
97 end
98end
30return nil 99return nil
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 4e01c24..26a8c5a 100755
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -60,7 +60,7 @@ using namespace parserlib;
60 60
61typedef std::list<std::string> str_list; 61typedef std::list<std::string> str_list;
62 62
63const std::string_view version = "0.10.7"sv; 63const std::string_view version = "0.10.8"sv;
64const std::string_view extension = "yue"sv; 64const std::string_view extension = "yue"sv;
65 65
66class YueCompilerImpl { 66class YueCompilerImpl {
@@ -1876,8 +1876,16 @@ private:
1876 if (destructNode || (destructNode = value->item.as<simple_table_t>())) { 1876 if (destructNode || (destructNode = value->item.as<simple_table_t>())) {
1877 if (*j != nullNode) { 1877 if (*j != nullNode) {
1878 if (auto ssVal = simpleSingleValueFrom(*j)) { 1878 if (auto ssVal = simpleSingleValueFrom(*j)) {
1879 if (ssVal->value.is<const_value_t>()) { 1879 switch (ssVal->value->getId()) {
1880 throw std::logic_error(_info.errorMessage("can not destructure a const value"sv, ssVal->value)); 1880 case id<const_value_t>():
1881 throw std::logic_error(_info.errorMessage("can not destructure a const value"sv, ssVal->value));
1882 break;
1883 case id<Num_t>():
1884 throw std::logic_error(_info.errorMessage("can not destructure a number"sv, ssVal->value));
1885 break;
1886 case id<FunLit_t>():
1887 throw std::logic_error(_info.errorMessage("can not destructure a function"sv, ssVal->value));
1888 break;
1881 } 1889 }
1882 } 1890 }
1883 } else { 1891 } else {
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index 258997e..ab9b657 100755
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -75,7 +75,7 @@ YueParser::YueParser() {
75 #define key(str) (str >> not_(AlphaNum)) 75 #define key(str) (str >> not_(AlphaNum))
76 #define disable_do(patt) (DisableDo >> ((patt) >> EnableDo | EnableDo >> Cut)) 76 #define disable_do(patt) (DisableDo >> ((patt) >> EnableDo | EnableDo >> Cut))
77 #define disable_chain(patt) (DisableChain >> ((patt) >> EnableChain | EnableChain >> Cut)) 77 #define disable_chain(patt) (DisableChain >> ((patt) >> EnableChain | EnableChain >> Cut))
78 #define disable_do_chain(patt) (DisableDoChain >> ((patt) >> EnableDoChain | EnableDoChain >> Cut)) 78 #define disable_do_chain_arg_table_block(patt) (DisableDoChainArgTableBlock >> ((patt) >> EnableDoChainArgTableBlock | EnableDoChainArgTableBlock >> Cut))
79 #define disable_arg_table_block(patt) (DisableArgTableBlock >> ((patt) >> EnableArgTableBlock | EnableArgTableBlock >> Cut)) 79 #define disable_arg_table_block(patt) (DisableArgTableBlock >> ((patt) >> EnableArgTableBlock | EnableArgTableBlock >> Cut))
80 #define plain_body_with(str) (-(Space >> key(str)) >> InBlock | Space >> key(str) >> Statement) 80 #define plain_body_with(str) (-(Space >> key(str)) >> InBlock | Space >> key(str) >> Statement)
81 #define plain_body (InBlock | Statement) 81 #define plain_body (InBlock | Statement)
@@ -223,8 +223,8 @@ YueParser::YueParser() {
223 223
224 WithExp = ExpList >> -Assign; 224 WithExp = ExpList >> -Assign;
225 225
226 With = Space >> key("with") >> -existential_op >> disable_do_chain(WithExp) >> plain_body_with("do"); 226 With = Space >> key("with") >> -existential_op >> disable_do_chain_arg_table_block(WithExp) >> plain_body_with("do");
227 SwitchCase = Space >> key("when") >> disable_chain(ExpList) >> plain_body_with("then"); 227 SwitchCase = Space >> key("when") >> disable_chain(disable_arg_table_block(ExpList)) >> plain_body_with("then");
228 SwitchElse = Space >> key("else") >> plain_body; 228 SwitchElse = Space >> key("else") >> plain_body;
229 229
230 SwitchBlock = *EmptyLine >> 230 SwitchBlock = *EmptyLine >>
@@ -238,54 +238,56 @@ YueParser::YueParser() {
238 >> -Space >> Break >> SwitchBlock; 238 >> -Space >> Break >> SwitchBlock;
239 239
240 assignment = ExpList >> Assign; 240 assignment = ExpList >> Assign;
241 IfCond = disable_do_chain(disable_arg_table_block(assignment | Exp)); 241 IfCond = disable_do_chain_arg_table_block(assignment | Exp);
242 IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("elseif") >> IfCond >> plain_body_with("then"); 242 IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("elseif") >> IfCond >> plain_body_with("then");
243 IfElse = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("else") >> plain_body; 243 IfElse = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("else") >> plain_body;
244 IfType = (expr("if") | expr("unless")) >> not_(AlphaNum); 244 IfType = (expr("if") | expr("unless")) >> not_(AlphaNum);
245 If = Space >> IfType >> IfCond >> plain_body_with("then") >> *IfElseIf >> -IfElse; 245 If = Space >> IfType >> IfCond >> plain_body_with("then") >> *IfElseIf >> -IfElse;
246 246
247 WhileType = (expr("while") | expr("until")) >> not_(AlphaNum); 247 WhileType = (expr("while") | expr("until")) >> not_(AlphaNum);
248 While = WhileType >> disable_do_chain(Exp) >> plain_body_with("do"); 248 While = WhileType >> disable_do_chain_arg_table_block(Exp) >> plain_body_with("do");
249 Repeat = key("repeat") >> Body >> Break >> *EmptyLine >> CheckIndent >> Space >> key("until") >> Exp; 249 Repeat = key("repeat") >> Body >> Break >> *EmptyLine >> CheckIndent >> Space >> key("until") >> Exp;
250 250
251 for_step_value = sym(',') >> Exp; 251 for_step_value = sym(',') >> Exp;
252 for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; 252 for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value;
253 253
254 For = key("for") >> disable_do_chain(for_args) >> plain_body_with("do"); 254 For = key("for") >> disable_do_chain_arg_table_block(for_args) >> plain_body_with("do");
255 255
256 for_in = star_exp | ExpList; 256 for_in = star_exp | ExpList;
257 257
258 ForEach = key("for") >> AssignableNameList >> Space >> key("in") >> 258 ForEach = key("for") >> AssignableNameList >> Space >> key("in") >>
259 disable_do_chain(for_in) >> plain_body_with("do"); 259 disable_do_chain_arg_table_block(for_in) >> plain_body_with("do");
260 260
261 Do = pl::user(Space >> key("do"), [](const item_t& item) { 261 Do = pl::user(Space >> key("do"), [](const item_t& item) {
262 State* st = reinterpret_cast<State*>(item.user_data); 262 State* st = reinterpret_cast<State*>(item.user_data);
263 return st->doStack.empty() || st->doStack.top(); 263 return st->noDoStack.empty() || !st->noDoStack.top();
264 }) >> Body; 264 }) >> Body;
265 265
266 DisableDo = pl::user(true_(), [](const item_t& item) { 266 DisableDo = pl::user(true_(), [](const item_t& item) {
267 State* st = reinterpret_cast<State*>(item.user_data); 267 State* st = reinterpret_cast<State*>(item.user_data);
268 st->doStack.push(false); 268 st->noDoStack.push(true);
269 return true; 269 return true;
270 }); 270 });
271 271
272 EnableDo = pl::user(true_(), [](const item_t& item) { 272 EnableDo = pl::user(true_(), [](const item_t& item) {
273 State* st = reinterpret_cast<State*>(item.user_data); 273 State* st = reinterpret_cast<State*>(item.user_data);
274 st->doStack.pop(); 274 st->noDoStack.pop();
275 return true; 275 return true;
276 }); 276 });
277 277
278 DisableDoChain = pl::user(true_(), [](const item_t& item) { 278 DisableDoChainArgTableBlock = pl::user(true_(), [](const item_t& item) {
279 State* st = reinterpret_cast<State*>(item.user_data); 279 State* st = reinterpret_cast<State*>(item.user_data);
280 st->doStack.push(false); 280 st->noDoStack.push(true);
281 st->chainBlockStack.push(false); 281 st->noChainBlockStack.push(true);
282 st->noTableBlockStack.push(true);
282 return true; 283 return true;
283 }); 284 });
284 285
285 EnableDoChain = pl::user(true_(), [](const item_t& item) { 286 EnableDoChainArgTableBlock = pl::user(true_(), [](const item_t& item) {
286 State* st = reinterpret_cast<State*>(item.user_data); 287 State* st = reinterpret_cast<State*>(item.user_data);
287 st->doStack.pop(); 288 st->noDoStack.pop();
288 st->chainBlockStack.pop(); 289 st->noChainBlockStack.pop();
290 st->noTableBlockStack.pop();
289 return true; 291 return true;
290 }); 292 });
291 293
@@ -370,20 +372,20 @@ YueParser::YueParser() {
370 372
371 DisableChain = pl::user(true_(), [](const item_t& item) { 373 DisableChain = pl::user(true_(), [](const item_t& item) {
372 State* st = reinterpret_cast<State*>(item.user_data); 374 State* st = reinterpret_cast<State*>(item.user_data);
373 st->chainBlockStack.push(false); 375 st->noChainBlockStack.push(true);
374 return true; 376 return true;
375 }); 377 });
376 378
377 EnableChain = pl::user(true_(), [](const item_t& item) { 379 EnableChain = pl::user(true_(), [](const item_t& item) {
378 State* st = reinterpret_cast<State*>(item.user_data); 380 State* st = reinterpret_cast<State*>(item.user_data);
379 st->chainBlockStack.pop(); 381 st->noChainBlockStack.pop();
380 return true; 382 return true;
381 }); 383 });
382 384
383 chain_line = CheckIndent >> (chain_item | Space >> (chain_dot_chain | ColonChain)) >> -InvokeArgs; 385 chain_line = CheckIndent >> (chain_item | Space >> (chain_dot_chain | ColonChain)) >> -InvokeArgs;
384 chain_block = pl::user(true_(), [](const item_t& item) { 386 chain_block = pl::user(true_(), [](const item_t& item) {
385 State* st = reinterpret_cast<State*>(item.user_data); 387 State* st = reinterpret_cast<State*>(item.user_data);
386 return st->chainBlockStack.empty() || st->chainBlockStack.top(); 388 return st->noChainBlockStack.empty() || !st->noChainBlockStack.top();
387 }) >> +SpaceBreak >> Advance >> ensure( 389 }) >> +SpaceBreak >> Advance >> ensure(
388 chain_line >> *(+SpaceBreak >> chain_line), PopIndent); 390 chain_line >> *(+SpaceBreak >> chain_line), PopIndent);
389 ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -(InvokeArgs | chain_block) >> -table_appending_op; 391 ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -(InvokeArgs | chain_block) >> -table_appending_op;
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h
index 51e6977..6be8451 100755
--- a/src/yuescript/yue_parser.h
+++ b/src/yuescript/yue_parser.h
@@ -77,8 +77,8 @@ protected:
77 std::string moduleName = "_module_0"; 77 std::string moduleName = "_module_0";
78 std::string buffer; 78 std::string buffer;
79 std::stack<int> indents; 79 std::stack<int> indents;
80 std::stack<bool> doStack; 80 std::stack<bool> noDoStack;
81 std::stack<bool> chainBlockStack; 81 std::stack<bool> noChainBlockStack;
82 std::stack<bool> noTableBlockStack; 82 std::stack<bool> noTableBlockStack;
83 }; 83 };
84 84
@@ -135,8 +135,8 @@ private:
135 rule EnableDo; 135 rule EnableDo;
136 rule DisableChain; 136 rule DisableChain;
137 rule EnableChain; 137 rule EnableChain;
138 rule DisableDoChain; 138 rule DisableDoChainArgTableBlock;
139 rule EnableDoChain; 139 rule EnableDoChainArgTableBlock;
140 rule DisableArgTableBlock; 140 rule DisableArgTableBlock;
141 rule EnableArgTableBlock; 141 rule EnableArgTableBlock;
142 rule SwitchElse; 142 rule SwitchElse;