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