aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2023-06-25 17:46:32 +0800
committerLi Jin <dragon-fly@qq.com>2023-06-25 17:46:32 +0800
commitcd618f934b0e4a30bd6cd4e98f8c1005bf3d6193 (patch)
tree5bc8bc55f80fe74a3b73101b55eabc60ae1d75c3
parent5d246757285a437401347dd6a1a1f8d3cf61e08c (diff)
downloadyuescript-cd618f934b0e4a30bd6cd4e98f8c1005bf3d6193.tar.gz
yuescript-cd618f934b0e4a30bd6cd4e98f8c1005bf3d6193.tar.bz2
yuescript-cd618f934b0e4a30bd6cd4e98f8c1005bf3d6193.zip
fix more ambiguous Lua codes generation cases.
-rw-r--r--spec/inputs/ambiguous.yue21
-rw-r--r--spec/outputs/ambiguous.lua15
-rw-r--r--spec/outputs/attrib.lua8
-rw-r--r--spec/outputs/macro.lua8
-rw-r--r--spec/outputs/teal-lang.lua10
-rw-r--r--spec/outputs/teal-lang.tl8
-rw-r--r--spec/outputs/using.lua2
-rw-r--r--src/yuescript/ast.cpp21
-rw-r--r--src/yuescript/ast.hpp10
-rw-r--r--src/yuescript/parser.cpp32
-rw-r--r--src/yuescript/parser.hpp17
-rw-r--r--src/yuescript/yue_ast.h3
-rw-r--r--src/yuescript/yue_compiler.cpp66
-rw-r--r--src/yuescript/yue_parser.cpp38
-rw-r--r--src/yuescript/yue_parser.h8
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
26macro lua = (code)-> {
27 :code
28 type: "lua"
29}
30
31do
32 print()
33 1 |> b |> (a)
34 print()
35 <- (fn)
36
37do
38 print()
39 () <- async_fn()
40 print()
41 $lua[==[
42 --[[a comment to insert]]
43 (haha)()
44 ]==]
45 nil
46
26macro v = -> 'print 123' 47macro v = -> 'print 123'
27do 48do
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)
26end 26end
27do 27do
28 print();
29 (a)(b(1))
30 print();
31 (fn)(function() end)
32end
33do
34 print()
35 async_fn(function()
36 print();
37--[[a comment to insert]]
38 (haha)()
39 return nil
40 end)
41end
42do
28 print(123) 43 print(123)
29end 44end
30do 45do
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 @@
1assert(item == nil); 1assert(item == nil)
2local v = (item == nil) 2local v = (item == nil)
3if f1() then 3if f1() then
4 print("OK") 4 print("OK")
@@ -170,11 +170,11 @@ do
170 end)() 170 end)()
171 print(a) 171 print(a)
172end 172end
173local x = 0; 173local x = 0
174local function f(a) 174local function f(a)
175 return a + 1 175 return a + 1
176end 176end
177x = x + f(3); 177x = x + f(3)
178function tb:func() 178function tb:func()
179 print(123) 179 print(123)
180end 180end
@@ -277,7 +277,7 @@ print((setmetatable({
277 return 998 277 return 998
278 end 278 end
279})) 279}))
280print("current line: " .. tostring(268)); 280print("current line: " .. tostring(268))
281-- TODO 281-- TODO
282do 282do
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 @@
1local a = { 1local a = {
2 value = 123 2 value = 123
3}; 3}
4local b = a.value; 4local b = a.value
5local add = function(a, b) 5local add = function(a, b)
6 return a + b 6 return a + b
7end 7end
8local s = add(a.value, b) 8local s = add(a.value, b)
9print(s); 9print(s)
10local Point = {}; 10local Point = {}
11Point.new = function(x, y) 11Point.new = function(x, y)
12local point = setmetatable({ }, { 12local 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
22end 22end
23local p = Point.new(100, 100) 23local p = Point.new(100, 100)
24p:move(50, 50); 24p:move(50, 50)
25local filter = function(tab, handler) 25local 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 @@
1local a:{string:number} = { 1local a:{string:number} = {
2 value = 123 2 value = 123
3}; 3}
4local b:number = a.value; 4local b:number = a.value
5local function add(a:number, b:number):number 5local function add(a:number, b:number):number
6 6
7 return a + b 7 return a + b
8 8
9end 9end
10local s = add(a.value, b) 10local s = add(a.value, b)
11print(s); 11print(s)
12local record Point 12local 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
29end 29end
30local p:Point = Point.new(100, 100) 30local p:Point = Point.new(100, 100)
31p:move(50, 50); 31p:move(50, 50)
32local function filter(tab:{string}, handler:function(item:string):boolean):{string} 32local 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
23end 23end
24do 24do
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*/
149ast_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*/
598ast_node* parse(input& i, rule& g, error_list& el, void* ud); 598ast_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*/
608ast_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*/
1573bool parse(input& i, rule& g, error_list& el, void* d, void* ud) { 1574bool 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*/
1609bool 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*/
400bool parse(input& i, rule& g, error_list& el, void* d, void* ud); 401bool 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*/
413bool 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)
880AST_END(Statement, "statement"sv) 879AST_END(Statement, "statement"sv)
881 880
882AST_NODE(Body) 881AST_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
75const std::string_view version = "0.17.0"sv; 75const std::string_view version = "0.17.1"sv;
76const std::string_view extension = "yue"sv; 76const std::string_view extension = "yue"sv;
77 77
78class CompileError : public std::logic_error { 78class 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
902bool 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
908ParseInfo YueParser::parse(std::string_view codes, rule& r) { 928ParseInfo 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
90protected: 95protected:
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)