diff options
author | Li Jin <dragon-fly@qq.com> | 2023-06-25 17:46:32 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2023-06-25 17:46:32 +0800 |
commit | cd618f934b0e4a30bd6cd4e98f8c1005bf3d6193 (patch) | |
tree | 5bc8bc55f80fe74a3b73101b55eabc60ae1d75c3 | |
parent | 5d246757285a437401347dd6a1a1f8d3cf61e08c (diff) | |
download | yuescript-cd618f934b0e4a30bd6cd4e98f8c1005bf3d6193.tar.gz yuescript-cd618f934b0e4a30bd6cd4e98f8c1005bf3d6193.tar.bz2 yuescript-cd618f934b0e4a30bd6cd4e98f8c1005bf3d6193.zip |
fix more ambiguous Lua codes generation cases.
-rw-r--r-- | spec/inputs/ambiguous.yue | 21 | ||||
-rw-r--r-- | spec/outputs/ambiguous.lua | 15 | ||||
-rw-r--r-- | spec/outputs/attrib.lua | 8 | ||||
-rw-r--r-- | spec/outputs/macro.lua | 8 | ||||
-rw-r--r-- | spec/outputs/teal-lang.lua | 10 | ||||
-rw-r--r-- | spec/outputs/teal-lang.tl | 8 | ||||
-rw-r--r-- | spec/outputs/using.lua | 2 | ||||
-rw-r--r-- | src/yuescript/ast.cpp | 21 | ||||
-rw-r--r-- | src/yuescript/ast.hpp | 10 | ||||
-rw-r--r-- | src/yuescript/parser.cpp | 32 | ||||
-rw-r--r-- | src/yuescript/parser.hpp | 17 | ||||
-rw-r--r-- | src/yuescript/yue_ast.h | 3 | ||||
-rw-r--r-- | src/yuescript/yue_compiler.cpp | 66 | ||||
-rw-r--r-- | src/yuescript/yue_parser.cpp | 38 | ||||
-rw-r--r-- | src/yuescript/yue_parser.h | 8 |
15 files changed, 189 insertions, 78 deletions
diff --git a/spec/inputs/ambiguous.yue b/spec/inputs/ambiguous.yue index 3ae0bfc..37857fe 100644 --- a/spec/inputs/ambiguous.yue +++ b/spec/inputs/ambiguous.yue | |||
@@ -23,6 +23,27 @@ for i = 1, 10 | |||
23 | goto abc | 23 | goto abc |
24 | (print) 5 | 24 | (print) 5 |
25 | 25 | ||
26 | macro lua = (code)-> { | ||
27 | :code | ||
28 | type: "lua" | ||
29 | } | ||
30 | |||
31 | do | ||
32 | print() | ||
33 | 1 |> b |> (a) | ||
34 | print() | ||
35 | <- (fn) | ||
36 | |||
37 | do | ||
38 | print() | ||
39 | () <- async_fn() | ||
40 | print() | ||
41 | $lua[==[ | ||
42 | --[[a comment to insert]] | ||
43 | (haha)() | ||
44 | ]==] | ||
45 | nil | ||
46 | |||
26 | macro v = -> 'print 123' | 47 | macro v = -> 'print 123' |
27 | do | 48 | do |
28 | global * | 49 | global * |
diff --git a/spec/outputs/ambiguous.lua b/spec/outputs/ambiguous.lua index f96cee5..3da6f14 100644 --- a/spec/outputs/ambiguous.lua +++ b/spec/outputs/ambiguous.lua | |||
@@ -25,6 +25,21 @@ for i = 1, 10 do | |||
25 | (print)(5) | 25 | (print)(5) |
26 | end | 26 | end |
27 | do | 27 | do |
28 | print(); | ||
29 | (a)(b(1)) | ||
30 | print(); | ||
31 | (fn)(function() end) | ||
32 | end | ||
33 | do | ||
34 | print() | ||
35 | async_fn(function() | ||
36 | print(); | ||
37 | --[[a comment to insert]] | ||
38 | (haha)() | ||
39 | return nil | ||
40 | end) | ||
41 | end | ||
42 | do | ||
28 | print(123) | 43 | print(123) |
29 | end | 44 | end |
30 | do | 45 | do |
diff --git a/spec/outputs/attrib.lua b/spec/outputs/attrib.lua index fbac28e..aaff747 100644 --- a/spec/outputs/attrib.lua +++ b/spec/outputs/attrib.lua | |||
@@ -64,12 +64,12 @@ do | |||
64 | local _with_0 = io.open("file.txt") | 64 | local _with_0 = io.open("file.txt") |
65 | _with_0:write("Hello") | 65 | _with_0:write("Hello") |
66 | return _with_0 | 66 | return _with_0 |
67 | end)(); | 67 | end)() |
68 | local _ <close> = setmetatable({ }, { | 68 | local _ <close> = setmetatable({ }, { |
69 | __close = function(self) | 69 | __close = function(self) |
70 | return print("second") | 70 | return print("second") |
71 | end | 71 | end |
72 | }); | 72 | }) |
73 | local _ <close> = setmetatable({ }, { | 73 | local _ <close> = setmetatable({ }, { |
74 | __close = function() | 74 | __close = function() |
75 | return print("first") | 75 | return print("first") |
@@ -86,11 +86,11 @@ do | |||
86 | _defers[#_defers + 1] = function() | 86 | _defers[#_defers + 1] = function() |
87 | return print(3) | 87 | return print(3) |
88 | end | 88 | end |
89 | local _ <close> = _defers; | 89 | local _ <close> = _defers |
90 | _defers[#_defers + 1] = function() | 90 | _defers[#_defers + 1] = function() |
91 | return print(2) | 91 | return print(2) |
92 | end | 92 | end |
93 | local _ <close> = _defers; | 93 | local _ <close> = _defers |
94 | _defers[#_defers + 1] = function() | 94 | _defers[#_defers + 1] = function() |
95 | return print(1) | 95 | return print(1) |
96 | end | 96 | end |
diff --git a/spec/outputs/macro.lua b/spec/outputs/macro.lua index fbc1d48..f18baed 100644 --- a/spec/outputs/macro.lua +++ b/spec/outputs/macro.lua | |||
@@ -1,4 +1,4 @@ | |||
1 | assert(item == nil); | 1 | assert(item == nil) |
2 | local v = (item == nil) | 2 | local v = (item == nil) |
3 | if f1() then | 3 | if f1() then |
4 | print("OK") | 4 | print("OK") |
@@ -170,11 +170,11 @@ do | |||
170 | end)() | 170 | end)() |
171 | print(a) | 171 | print(a) |
172 | end | 172 | end |
173 | local x = 0; | 173 | local x = 0 |
174 | local function f(a) | 174 | local function f(a) |
175 | return a + 1 | 175 | return a + 1 |
176 | end | 176 | end |
177 | x = x + f(3); | 177 | x = x + f(3) |
178 | function tb:func() | 178 | function tb:func() |
179 | print(123) | 179 | print(123) |
180 | end | 180 | end |
@@ -277,7 +277,7 @@ print((setmetatable({ | |||
277 | return 998 | 277 | return 998 |
278 | end | 278 | end |
279 | })) | 279 | })) |
280 | print("current line: " .. tostring(268)); | 280 | print("current line: " .. tostring(268)) |
281 | -- TODO | 281 | -- TODO |
282 | do | 282 | do |
283 | print(1) | 283 | print(1) |
diff --git a/spec/outputs/teal-lang.lua b/spec/outputs/teal-lang.lua index 0e627f4..28ba6f8 100644 --- a/spec/outputs/teal-lang.lua +++ b/spec/outputs/teal-lang.lua | |||
@@ -1,13 +1,13 @@ | |||
1 | local a = { | 1 | local a = { |
2 | value = 123 | 2 | value = 123 |
3 | }; | 3 | } |
4 | local b = a.value; | 4 | local b = a.value |
5 | local add = function(a, b) | 5 | local add = function(a, b) |
6 | return a + b | 6 | return a + b |
7 | end | 7 | end |
8 | local s = add(a.value, b) | 8 | local s = add(a.value, b) |
9 | print(s); | 9 | print(s) |
10 | local Point = {}; | 10 | local Point = {} |
11 | Point.new = function(x, y) | 11 | Point.new = function(x, y) |
12 | local point = setmetatable({ }, { | 12 | local point = setmetatable({ }, { |
13 | __index = Point | 13 | __index = Point |
@@ -21,7 +21,7 @@ Point.move = function(self, dx, dy) | |||
21 | self.y = self.y + dy | 21 | self.y = self.y + dy |
22 | end | 22 | end |
23 | local p = Point.new(100, 100) | 23 | local p = Point.new(100, 100) |
24 | p:move(50, 50); | 24 | p:move(50, 50) |
25 | local filter = function(tab, handler) | 25 | local filter = function(tab, handler) |
26 | local _accum_0 = { } | 26 | local _accum_0 = { } |
27 | local _len_0 = 1 | 27 | local _len_0 = 1 |
diff --git a/spec/outputs/teal-lang.tl b/spec/outputs/teal-lang.tl index 8f0bf36..0dc25a1 100644 --- a/spec/outputs/teal-lang.tl +++ b/spec/outputs/teal-lang.tl | |||
@@ -1,14 +1,14 @@ | |||
1 | local a:{string:number} = { | 1 | local a:{string:number} = { |
2 | value = 123 | 2 | value = 123 |
3 | }; | 3 | } |
4 | local b:number = a.value; | 4 | local b:number = a.value |
5 | local function add(a:number, b:number):number | 5 | local function add(a:number, b:number):number |
6 | 6 | ||
7 | return a + b | 7 | return a + b |
8 | 8 | ||
9 | end | 9 | end |
10 | local s = add(a.value, b) | 10 | local s = add(a.value, b) |
11 | print(s); | 11 | print(s) |
12 | local record Point | 12 | local record Point |
13 | x: number | 13 | x: number |
14 | y: number | 14 | y: number |
@@ -28,7 +28,7 @@ function Point:move(dx:number, dy:number) | |||
28 | 28 | ||
29 | end | 29 | end |
30 | local p:Point = Point.new(100, 100) | 30 | local p:Point = Point.new(100, 100) |
31 | p:move(50, 50); | 31 | p:move(50, 50) |
32 | local function filter(tab:{string}, handler:function(item:string):boolean):{string} | 32 | local function filter(tab:{string}, handler:function(item:string):boolean):{string} |
33 | 33 | ||
34 | local _accum_0 = { } | 34 | local _accum_0 = { } |
diff --git a/spec/outputs/using.lua b/spec/outputs/using.lua index ff23a30..8ecc21e 100644 --- a/spec/outputs/using.lua +++ b/spec/outputs/using.lua | |||
@@ -22,7 +22,7 @@ _ = function() | |||
22 | local hello = hello or 2 | 22 | local hello = hello or 2 |
23 | end | 23 | end |
24 | do | 24 | do |
25 | local a = { }; | 25 | local a = { } |
26 | _(function() | 26 | _(function() |
27 | local x, y = a[1], a[2] | 27 | local x, y = a[1], a[2] |
28 | end) | 28 | end) |
diff --git a/src/yuescript/ast.cpp b/src/yuescript/ast.cpp index 239aec6..6db2c21 100644 --- a/src/yuescript/ast.cpp +++ b/src/yuescript/ast.cpp | |||
@@ -138,4 +138,25 @@ ast_node* parse(input& i, rule& g, error_list& el, void* ud) { | |||
138 | return st.front(); | 138 | return st.front(); |
139 | } | 139 | } |
140 | 140 | ||
141 | /** check if the start part of given input matches grammar. | ||
142 | The parse procedures of each rule parsed are executed | ||
143 | before this function returns, if parsing succeeds. | ||
144 | @param i input. | ||
145 | @param g root rule of grammar. | ||
146 | @param ud user data, passed to the parse procedures. | ||
147 | @return true on parsing success, false on failure. | ||
148 | */ | ||
149 | ast_node* start_with(input& i, rule& g, error_list& el, void* ud) { | ||
150 | ast_stack st; | ||
151 | if (!start_with(i, g, el, &st, ud)) { | ||
152 | for (auto node : st) { | ||
153 | delete node; | ||
154 | } | ||
155 | st.clear(); | ||
156 | return nullptr; | ||
157 | } | ||
158 | assert(st.size() == 1); | ||
159 | return st.front(); | ||
160 | } | ||
161 | |||
141 | } // namespace parserlib | 162 | } // namespace parserlib |
diff --git a/src/yuescript/ast.hpp b/src/yuescript/ast.hpp index c6da312..f59b50f 100644 --- a/src/yuescript/ast.hpp +++ b/src/yuescript/ast.hpp | |||
@@ -597,4 +597,14 @@ private: | |||
597 | */ | 597 | */ |
598 | ast_node* parse(input& i, rule& g, error_list& el, void* ud); | 598 | ast_node* parse(input& i, rule& g, error_list& el, void* ud); |
599 | 599 | ||
600 | /** check if the start part of given input matches grammar. | ||
601 | The parse procedures of each rule parsed are executed | ||
602 | before this function returns, if parsing succeeds. | ||
603 | @param i input. | ||
604 | @param g root rule of grammar. | ||
605 | @param ud user data, passed to the parse procedures. | ||
606 | @return true on parsing success, false on failure. | ||
607 | */ | ||
608 | ast_node* start_with(input& i, rule& g, error_list& el, void* ud); | ||
609 | |||
600 | } // namespace parserlib | 610 | } // namespace parserlib |
diff --git a/src/yuescript/parser.cpp b/src/yuescript/parser.cpp index 25b735e..04b7ffd 100644 --- a/src/yuescript/parser.cpp +++ b/src/yuescript/parser.cpp | |||
@@ -1567,10 +1567,11 @@ expr user(const expr& e, const user_handler& handler) { | |||
1567 | @param i input. | 1567 | @param i input. |
1568 | @param g root rule of grammar. | 1568 | @param g root rule of grammar. |
1569 | @param el list of errors. | 1569 | @param el list of errors. |
1570 | @param d user data, passed to the parse procedures. | 1570 | @param st ast object stack. |
1571 | @param ud user data, passed to the parse procedures. | ||
1571 | @return true on parsing success, false on failure. | 1572 | @return true on parsing success, false on failure. |
1572 | */ | 1573 | */ |
1573 | bool parse(input& i, rule& g, error_list& el, void* d, void* ud) { | 1574 | bool parse(input& i, rule& g, error_list& el, void* st, void* ud) { |
1574 | // prepare context | 1575 | // prepare context |
1575 | _context con(i, ud); | 1576 | _context con(i, ud); |
1576 | 1577 | ||
@@ -1591,7 +1592,32 @@ bool parse(input& i, rule& g, error_list& el, void* d, void* ud) { | |||
1591 | } | 1592 | } |
1592 | 1593 | ||
1593 | // success; execute the parse procedures | 1594 | // success; execute the parse procedures |
1594 | con.do_parse_procs(d); | 1595 | con.do_parse_procs(st); |
1596 | return true; | ||
1597 | } | ||
1598 | |||
1599 | /** check the start part of given input. | ||
1600 | The parse procedures of each rule parsed are executed | ||
1601 | before this function returns, if parsing succeeds. | ||
1602 | @param i input. | ||
1603 | @param g root rule of grammar. | ||
1604 | @param el list of errors. | ||
1605 | @param st ast object stack. | ||
1606 | @param ud user data, passed to the parse procedures. | ||
1607 | @return true on parsing success, false on failure. | ||
1608 | */ | ||
1609 | bool start_with(input& i, rule& g, error_list& el, void* st, void* ud) { | ||
1610 | // prepare context | ||
1611 | _context con(i, ud); | ||
1612 | |||
1613 | // parse grammar | ||
1614 | if (!con.parse_non_term(g)) { | ||
1615 | el.push_back(_syntax_error(con)); | ||
1616 | return false; | ||
1617 | } | ||
1618 | |||
1619 | // success; execute the parse procedures | ||
1620 | con.do_parse_procs(st); | ||
1595 | return true; | 1621 | return true; |
1596 | } | 1622 | } |
1597 | 1623 | ||
diff --git a/src/yuescript/parser.hpp b/src/yuescript/parser.hpp index 83682ae..d2612cd 100644 --- a/src/yuescript/parser.hpp +++ b/src/yuescript/parser.hpp | |||
@@ -394,10 +394,23 @@ expr user(const expr& e, const user_handler& handler); | |||
394 | @param i input. | 394 | @param i input. |
395 | @param g root rule of grammar. | 395 | @param g root rule of grammar. |
396 | @param el list of errors. | 396 | @param el list of errors. |
397 | @param d user data, passed to the parse procedures. | 397 | @param st ast object stack. |
398 | @param ud user data, passed to the parse procedures. | ||
398 | @return true on parsing success, false on failure. | 399 | @return true on parsing success, false on failure. |
399 | */ | 400 | */ |
400 | bool parse(input& i, rule& g, error_list& el, void* d, void* ud); | 401 | bool parse(input& i, rule& g, error_list& el, void* st, void* ud); |
402 | |||
403 | /** check if the start part of given input matches grammar. | ||
404 | The parse procedures of each rule parsed are executed | ||
405 | before this function returns, if parsing succeeds. | ||
406 | @param i input. | ||
407 | @param g root rule of grammar. | ||
408 | @param el list of errors. | ||
409 | @param st ast object stack. | ||
410 | @param ud user data, passed to the parse procedures. | ||
411 | @return true on parsing success, false on failure. | ||
412 | */ | ||
413 | bool start_with(input& i, rule& g, error_list& el, void* st, void* ud); | ||
401 | 414 | ||
402 | /** output the specific input range to the specific stream. | 415 | /** output the specific input range to the specific stream. |
403 | @param stream stream. | 416 | @param stream stream. |
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index acb7221..e95e35c 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
@@ -875,8 +875,7 @@ AST_NODE(Statement) | |||
875 | Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t, ChainAssign_t | 875 | Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t, ChainAssign_t |
876 | > content; | 876 | > content; |
877 | ast_ptr<false, StatementAppendix_t> appendix; | 877 | ast_ptr<false, StatementAppendix_t> appendix; |
878 | ast_ptr<false, StatementSep_t> needSep; | 878 | AST_MEMBER(Statement, &sep, &comments, &content, &appendix) |
879 | AST_MEMBER(Statement, &sep, &comments, &content, &appendix, &needSep) | ||
880 | AST_END(Statement, "statement"sv) | 879 | AST_END(Statement, "statement"sv) |
881 | 880 | ||
882 | AST_NODE(Body) | 881 | AST_NODE(Body) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 98d19a7..8574e6c 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -72,7 +72,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
72 | "close"s // Lua 5.4 | 72 | "close"s // Lua 5.4 |
73 | }; | 73 | }; |
74 | 74 | ||
75 | const std::string_view version = "0.17.0"sv; | 75 | const std::string_view version = "0.17.1"sv; |
76 | const std::string_view extension = "yue"sv; | 76 | const std::string_view extension = "yue"sv; |
77 | 77 | ||
78 | class CompileError : public std::logic_error { | 78 | class CompileError : public std::logic_error { |
@@ -1497,25 +1497,6 @@ private: | |||
1497 | case id<ChainAssign_t>(): transformChainAssign(static_cast<ChainAssign_t*>(content), out); break; | 1497 | case id<ChainAssign_t>(): transformChainAssign(static_cast<ChainAssign_t*>(content), out); break; |
1498 | default: YUEE("AST node mismatch", content); break; | 1498 | default: YUEE("AST node mismatch", content); break; |
1499 | } | 1499 | } |
1500 | if (statement->needSep && !out.empty() && !out.back().empty()) { | ||
1501 | auto index = std::string::npos; | ||
1502 | if (_config.reserveLineNumber) { | ||
1503 | index = out.back().rfind(" -- "sv); | ||
1504 | } else { | ||
1505 | index = out.back().find_last_not_of('\n'); | ||
1506 | if (index != std::string::npos) index++; | ||
1507 | } | ||
1508 | if (index != std::string::npos) { | ||
1509 | auto ending = out.back().substr(0, index); | ||
1510 | auto ind = ending.find_last_of(" \t\n"sv); | ||
1511 | if (ind != std::string::npos) { | ||
1512 | ending = ending.substr(ind + 1); | ||
1513 | } | ||
1514 | if (LuaKeywords.find(ending) == LuaKeywords.end()) { | ||
1515 | out.back().insert(index, ";"sv); | ||
1516 | } | ||
1517 | } | ||
1518 | } | ||
1519 | } | 1500 | } |
1520 | 1501 | ||
1521 | str_list getAssignVars(ExpListAssign_t* assignment) { | 1502 | str_list getAssignVars(ExpListAssign_t* assignment) { |
@@ -3543,8 +3524,6 @@ private: | |||
3543 | } | 3524 | } |
3544 | lst->appendix.set(stmt->appendix); | 3525 | lst->appendix.set(stmt->appendix); |
3545 | stmt->appendix.set(nullptr); | 3526 | stmt->appendix.set(nullptr); |
3546 | lst->needSep.set(stmt->needSep); | ||
3547 | stmt->needSep.set(nullptr); | ||
3548 | auto exp = lastExpFromStatement(lst); | 3527 | auto exp = lastExpFromStatement(lst); |
3549 | BREAK_IF(!exp); | 3528 | BREAK_IF(!exp); |
3550 | for (auto val : pipeBody->values.objects()) { | 3529 | for (auto val : pipeBody->values.objects()) { |
@@ -3753,22 +3732,6 @@ private: | |||
3753 | returnNode->valueList.set(expListLow); | 3732 | returnNode->valueList.set(expListLow); |
3754 | returnNode->allowBlockMacroReturn = true; | 3733 | returnNode->allowBlockMacroReturn = true; |
3755 | last->content.set(returnNode); | 3734 | last->content.set(returnNode); |
3756 | last->needSep.set(nullptr); | ||
3757 | auto bLast = ++nodes.rbegin(); | ||
3758 | if (bLast != nodes.rend()) { | ||
3759 | bool isMacro = false; | ||
3760 | BLOCK_START | ||
3761 | BREAK_IF(expListLow->exprs.size() != 1); | ||
3762 | auto exp = static_cast<Exp_t*>(expListLow->exprs.back()); | ||
3763 | BREAK_IF(!exp->opValues.empty()); | ||
3764 | auto chainValue = exp->getByPath<UnaryExp_t, Value_t, ChainValue_t>(); | ||
3765 | BREAK_IF(!chainValue); | ||
3766 | isMacro = isMacroChain(chainValue); | ||
3767 | BLOCK_END | ||
3768 | if (!isMacro) { | ||
3769 | ast_to<Statement_t>(*bLast)->needSep.set(nullptr); | ||
3770 | } | ||
3771 | } | ||
3772 | BLOCK_END | 3735 | BLOCK_END |
3773 | break; | 3736 | break; |
3774 | } | 3737 | } |
@@ -3802,11 +3765,6 @@ private: | |||
3802 | } | 3765 | } |
3803 | newAssignment->action.set(assign); | 3766 | newAssignment->action.set(assign); |
3804 | last->content.set(newAssignment); | 3767 | last->content.set(newAssignment); |
3805 | last->needSep.set(nullptr); | ||
3806 | auto bLast = ++nodes.rbegin(); | ||
3807 | if (bLast != nodes.rend()) { | ||
3808 | static_cast<Statement_t*>(*bLast)->needSep.set(nullptr); | ||
3809 | } | ||
3810 | } else if (!last->content.is<BreakLoop_t>()) { | 3768 | } else if (!last->content.is<BreakLoop_t>()) { |
3811 | throw CompileError("expecting assignable statement or break loop"sv, last); | 3769 | throw CompileError("expecting assignable statement or break loop"sv, last); |
3812 | } | 3770 | } |
@@ -3818,6 +3776,28 @@ private: | |||
3818 | str_list temp; | 3776 | str_list temp; |
3819 | for (auto node : nodes) { | 3777 | for (auto node : nodes) { |
3820 | transformStatement(static_cast<Statement_t*>(node), temp); | 3778 | transformStatement(static_cast<Statement_t*>(node), temp); |
3779 | if (_parser.startWith<StatementSep_t>(temp.back())) { | ||
3780 | auto rit = ++temp.rbegin(); | ||
3781 | if (rit != temp.rend() && !rit->empty()) { | ||
3782 | auto index = std::string::npos; | ||
3783 | if (_config.reserveLineNumber) { | ||
3784 | index = rit->rfind(" -- "sv); | ||
3785 | } else { | ||
3786 | index = rit->find_last_not_of('\n'); | ||
3787 | if (index != std::string::npos) index++; | ||
3788 | } | ||
3789 | if (index != std::string::npos) { | ||
3790 | auto ending = rit->substr(0, index); | ||
3791 | auto ind = ending.find_last_of(" \t\n"sv); | ||
3792 | if (ind != std::string::npos) { | ||
3793 | ending = ending.substr(ind + 1); | ||
3794 | } | ||
3795 | if (LuaKeywords.find(ending) == LuaKeywords.end()) { | ||
3796 | rit->insert(index, ";"sv); | ||
3797 | } | ||
3798 | } | ||
3799 | } | ||
3800 | } | ||
3821 | } | 3801 | } |
3822 | out.push_back(join(temp)); | 3802 | out.push_back(join(temp)); |
3823 | } else { | 3803 | } else { |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index f383275..f72407d 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
@@ -853,13 +853,6 @@ YueParser::YueParser() { | |||
853 | ChainAssign = Seperator >> Exp >> +(space >> '=' >> space >> Exp >> space >> and_('=')) >> space >> Assign; | 853 | ChainAssign = Seperator >> Exp >> +(space >> '=' >> space >> Exp >> space >> and_('=')) >> space >> Assign; |
854 | 854 | ||
855 | StatementAppendix = (IfLine | WhileLine | CompInner) >> space; | 855 | StatementAppendix = (IfLine | WhileLine | CompInner) >> space; |
856 | StatementSep = and_( | ||
857 | *space_break >> check_indent_match >> space >> ( | ||
858 | set("($'\"") | | ||
859 | "[[" | | ||
860 | "[=" | ||
861 | ) | ||
862 | ); | ||
863 | Statement = | 856 | Statement = |
864 | Seperator >> | 857 | Seperator >> |
865 | -( | 858 | -( |
@@ -876,8 +869,9 @@ YueParser::YueParser() { | |||
876 | StatementAppendix >> empty_block_error | 869 | StatementAppendix >> empty_block_error |
877 | ) >> | 870 | ) >> |
878 | space >> | 871 | space >> |
879 | -StatementAppendix >> | 872 | -StatementAppendix; |
880 | -StatementSep; | 873 | |
874 | StatementSep = white >> (set("('\"") | "[[" | "[="); | ||
881 | 875 | ||
882 | Body = in_block | Statement; | 876 | Body = in_block | Statement; |
883 | 877 | ||
@@ -905,6 +899,32 @@ YueParser::YueParser() { | |||
905 | } | 899 | } |
906 | // clang-format on | 900 | // clang-format on |
907 | 901 | ||
902 | bool YueParser::startWith(std::string_view codes, rule& r) { | ||
903 | std::unique_ptr<input> converted; | ||
904 | if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) { | ||
905 | codes = codes.substr(3); | ||
906 | } | ||
907 | try { | ||
908 | if (!codes.empty()) { | ||
909 | converted = std::make_unique<input>(_converter.from_bytes(&codes.front(), &codes.back() + 1)); | ||
910 | } else { | ||
911 | converted = std::make_unique<input>(); | ||
912 | } | ||
913 | } catch (const std::range_error&) { | ||
914 | return false; | ||
915 | } | ||
916 | error_list errors; | ||
917 | try { | ||
918 | State state; | ||
919 | return ::yue::start_with(*converted, r, errors, &state); | ||
920 | } catch (const ParserError&) { | ||
921 | return false; | ||
922 | } catch (const std::logic_error&) { | ||
923 | return false; | ||
924 | } | ||
925 | return true; | ||
926 | } | ||
927 | |||
908 | ParseInfo YueParser::parse(std::string_view codes, rule& r) { | 928 | ParseInfo YueParser::parse(std::string_view codes, rule& r) { |
909 | ParseInfo res; | 929 | ParseInfo res; |
910 | if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) { | 930 | if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) { |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index d4f66eb..d7fbf90 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
@@ -84,11 +84,17 @@ public: | |||
84 | return parse(codes, rEnd).node; | 84 | return parse(codes, rEnd).node; |
85 | } | 85 | } |
86 | 86 | ||
87 | template <class AST> | ||
88 | bool startWith(std::string_view codes) { | ||
89 | return startWith(codes, getRule<AST>()); | ||
90 | } | ||
91 | |||
87 | std::string toString(ast_node* node); | 92 | std::string toString(ast_node* node); |
88 | std::string toString(input::iterator begin, input::iterator end); | 93 | std::string toString(input::iterator begin, input::iterator end); |
89 | 94 | ||
90 | protected: | 95 | protected: |
91 | ParseInfo parse(std::string_view codes, rule& r); | 96 | ParseInfo parse(std::string_view codes, rule& r); |
97 | bool startWith(std::string_view codes, rule& r); | ||
92 | 98 | ||
93 | struct State { | 99 | struct State { |
94 | State() { | 100 | State() { |
@@ -387,8 +393,8 @@ private: | |||
387 | AST_RULE(WhileLine) | 393 | AST_RULE(WhileLine) |
388 | AST_RULE(BreakLoop) | 394 | AST_RULE(BreakLoop) |
389 | AST_RULE(StatementAppendix) | 395 | AST_RULE(StatementAppendix) |
390 | AST_RULE(StatementSep) | ||
391 | AST_RULE(Statement) | 396 | AST_RULE(Statement) |
397 | AST_RULE(StatementSep); | ||
392 | AST_RULE(YueLineComment) | 398 | AST_RULE(YueLineComment) |
393 | AST_RULE(MultilineCommentInner) | 399 | AST_RULE(MultilineCommentInner) |
394 | AST_RULE(YueMultilineComment) | 400 | AST_RULE(YueMultilineComment) |